diff options
Diffstat (limited to 'source4/torture')
-rw-r--r-- | source4/torture/ldap/common.c | 1 | ||||
-rw-r--r-- | source4/torture/ldap/netlogon.c | 458 | ||||
-rwxr-xr-x | source4/torture/wscript_build | 2 |
3 files changed, 460 insertions, 1 deletions
diff --git a/source4/torture/ldap/common.c b/source4/torture/ldap/common.c index 3af3d02491..586b85eca0 100644 --- a/source4/torture/ldap/common.c +++ b/source4/torture/ldap/common.c @@ -136,6 +136,7 @@ NTSTATUS torture_ldap_init(void) torture_suite_add_simple_test(suite, "basic", torture_ldap_basic); torture_suite_add_simple_test(suite, "sort", torture_ldap_sort); torture_suite_add_simple_test(suite, "cldap", torture_cldap); + torture_suite_add_simple_test(suite, "netlogon", torture_netlogon); torture_suite_add_simple_test(suite, "schema", torture_ldap_schema); torture_suite_add_simple_test(suite, "uptodatevector", torture_ldap_uptodatevector); torture_suite_add_simple_test(suite, "nested-search", test_ldap_nested_search); diff --git a/source4/torture/ldap/netlogon.c b/source4/torture/ldap/netlogon.c new file mode 100644 index 0000000000..7da0c30115 --- /dev/null +++ b/source4/torture/ldap/netlogon.c @@ -0,0 +1,458 @@ +/* + Unix SMB/CIFS mplementation. + LDAP protocol helper functions for SAMBA + + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Simo Sorce 2004 + Copyright (C) Matthias Dieter Wallnöfer 2009-2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "includes.h" +#include "ldb_wrap.h" +#include "libcli/ldap/ldap_client.h" +#include "lib/cmdline/popt_common.h" + +#include "torture/torture.h" +#include "torture/ldap/proto.h" + +#include "libcli/cldap/cldap.h" +#include "librpc/gen_ndr/netlogon.h" + +#define CHECK_STATUS(status, correct) torture_assert_ntstatus_equal(tctx, status, correct, "incorrect status") + +#define CHECK_VAL(v, correct) torture_assert_int_equal(tctx, (v), (correct), "incorrect value"); + +#define CHECK_STRING(v, correct) torture_assert_str_equal(tctx, v, correct, "incorrect value"); + +static NTSTATUS ldap_netlogon(struct ldap_connection *conn, + TALLOC_CTX *mem_ctx, + struct cldap_netlogon *io) +{ + char *filter; + struct ldap_message *msg, *result; + struct ldap_request *req; + struct ldap_SearchResEntry *res; + DATA_BLOB *data; + NTSTATUS status; + int ret; + + filter = cldap_netlogon_create_filter(mem_ctx, io); + if (filter == NULL) { + return NT_STATUS_NO_MEMORY; + } + + msg = new_ldap_message(mem_ctx); + if (!msg) { + return NT_STATUS_NO_MEMORY; + } + + msg->type = LDAP_TAG_SearchRequest; + msg->r.SearchRequest.basedn = ""; + msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE; + msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER; + msg->r.SearchRequest.timelimit = 0; + msg->r.SearchRequest.sizelimit = 0; + msg->r.SearchRequest.attributesonly = false; + msg->r.SearchRequest.tree = ldb_parse_tree(msg, filter); + msg->r.SearchRequest.num_attributes = 1; + msg->r.SearchRequest.attributes = (const char *[]) { "netlogon" }; + + req = ldap_request_send(conn, msg); + if (req == NULL) { + printf("Could not setup ldap search\n"); + return NT_STATUS_UNSUCCESSFUL; + } + + status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry); + if (!NT_STATUS_IS_OK(status)) { + /* Throw same error as cldap_netlogon. */ + if (NT_STATUS_EQUAL(status, NT_STATUS_UNEXPECTED_NETWORK_ERROR)) { + return NT_STATUS_NOT_FOUND; + } else { + return status; + } + } + + res = &result->r.SearchResultEntry; + if (res->num_attributes != 1 || + strcasecmp(res->attributes[0].name, "netlogon") != 0 || + res->attributes[0].num_values != 1 || + res->attributes[0].values->length < 2) { + return NT_STATUS_UNEXPECTED_NETWORK_ERROR; + } + + data = res->attributes[0].values; + status = pull_netlogon_samlogon_response(data, mem_ctx, + &io->out.netlogon); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (io->in.map_response) { + map_netlogon_samlogon_response(&io->out.netlogon); + } + + return NT_STATUS_OK; +} + +/* + test netlogon operations +*/ +static bool test_ldap_netlogon(struct torture_context *tctx, + struct ldap_connection *cldap, + const char *dest) +{ + NTSTATUS status; + struct cldap_netlogon search, empty_search; + struct netlogon_samlogon_response n1; + struct GUID guid; + int i; + struct tsocket_address *dest_addr; + int ret; + + ZERO_STRUCT(search); + search.in.dest_address = NULL; + search.in.dest_port = 0; + search.in.acct_control = -1; + search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; + search.in.map_response = true; + + empty_search = search; + + printf("Trying without any attributes\n"); + search = empty_search; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + + n1 = search.out.netlogon; + + search.in.user = "Administrator"; + search.in.realm = n1.data.nt5_ex.dns_domain; + search.in.host = "__cldap_torture__"; + + printf("Scanning for netlogon levels\n"); + for (i=0;i<256;i++) { + search.in.version = i; + printf("Trying netlogon level %d\n", i); + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + } + + printf("Scanning for netlogon level bits\n"); + for (i=0;i<31;i++) { + search.in.version = (1<<i); + printf("Trying netlogon level 0x%x\n", i); + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + } + + search.in.version = NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_IP; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + + printf("Trying with User=NULL\n"); + search.in.user = NULL; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); + torture_assert(tctx, + strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL, + "PDC name should not be in UNC form"); + + printf("Trying with User=Administrator\n"); + search.in.user = "Administrator"; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); + torture_assert(tctx, + strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL, + "PDC name should not be in UNC form"); + + search.in.version = NETLOGON_NT_VERSION_5; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + + printf("Trying with User=NULL\n"); + search.in.user = NULL; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); + torture_assert(tctx, + strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") != NULL, + "PDC name should be in UNC form"); + + printf("Trying with User=Administrator\n"); + search.in.user = "Administrator"; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); + torture_assert(tctx, + strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") != NULL, + "PDC name should be in UNC form"); + + search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; + + printf("Trying with a GUID\n"); + search.in.realm = NULL; + search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid); + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); + CHECK_STRING(GUID_string(tctx, &search.out.netlogon.data.nt5_ex.domain_uuid), search.in.domain_guid); + torture_assert(tctx, + strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL, + "PDC name should not be in UNC form"); + + printf("Trying with a incorrect GUID\n"); + guid = GUID_random(); + search.in.user = NULL; + search.in.domain_guid = GUID_string(tctx, &guid); + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_NOT_FOUND); + + printf("Trying with a AAC\n"); + search.in.acct_control = ACB_WSTRUST|ACB_SVRTRUST; + search.in.realm = n1.data.nt5_ex.dns_domain; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); + + printf("Trying with a zero AAC\n"); + search.in.acct_control = 0x0; + search.in.realm = n1.data.nt5_ex.dns_domain; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); + + printf("Trying with a zero AAC and user=Administrator\n"); + search.in.acct_control = 0x0; + search.in.user = "Administrator"; + search.in.realm = n1.data.nt5_ex.dns_domain; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "Administrator"); + + printf("Trying with a bad AAC\n"); + search.in.user = NULL; + search.in.acct_control = 0xFF00FF00; + search.in.realm = n1.data.nt5_ex.dns_domain; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); + + printf("Trying with a user only\n"); + search = empty_search; + search.in.user = "Administrator"; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); + CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); + CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); + + printf("Trying with just a bad username\n"); + search.in.user = "___no_such_user___"; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); + CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); + CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); + + printf("Trying with just a bad domain\n"); + search = empty_search; + search.in.realm = "___no_such_domain___"; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_NOT_FOUND); + + printf("Trying with a incorrect domain and correct guid\n"); + search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid); + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); + CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); + CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); + + printf("Trying with a incorrect domain and incorrect guid\n"); + search.in.domain_guid = GUID_string(tctx, &guid); + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_NOT_FOUND); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); + CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); + CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); + + printf("Trying with a incorrect GUID and correct domain\n"); + search.in.domain_guid = GUID_string(tctx, &guid); + search.in.realm = n1.data.nt5_ex.dns_domain; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); + CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); + CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); + CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); + + printf("Proof other results\n"); + search.in.user = "Administrator"; + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); + CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); + CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); + CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); + CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); + + return true; +} + +/* + test cldap netlogon server type flags +*/ +static bool test_ldap_netlogon_flags(struct torture_context *tctx, + struct ldap_connection *cldap, + const char *dest) +{ + NTSTATUS status; + struct cldap_netlogon search; + struct netlogon_samlogon_response n1; + uint32_t server_type; + struct tsocket_address *dest_addr; + int ret; +#if 0 + ret = tsocket_address_inet_from_strings(tctx, "ip", + dest, + lpcfg_cldap_port(tctx->lp_ctx), + &dest_addr); + CHECK_VAL(ret, 0); + + /* cldap_socket_init should now know about the dest. address */ + status = cldap_socket_init(tctx, NULL, dest_addr, &cldap); + CHECK_STATUS(status, NT_STATUS_OK); +#endif + + printf("Printing out netlogon server type flags: %s\n", dest); + + ZERO_STRUCT(search); + search.in.dest_address = NULL; + search.in.dest_port = 0; + search.in.acct_control = -1; + search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; + search.in.map_response = true; + + status = ldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + + n1 = search.out.netlogon; + if (n1.ntver == NETLOGON_NT_VERSION_5) + server_type = n1.data.nt5.server_type; + else if (n1.ntver == NETLOGON_NT_VERSION_5EX) + server_type = n1.data.nt5_ex.server_type; + + printf("The word is: %i\n", server_type); + if (server_type & NBT_SERVER_PDC) + printf("NBT_SERVER_PDC "); + if (server_type & NBT_SERVER_GC) + printf("NBT_SERVER_GC "); + if (server_type & NBT_SERVER_LDAP) + printf("NBT_SERVER_LDAP "); + if (server_type & NBT_SERVER_DS) + printf("NBT_SERVER_DS "); + if (server_type & NBT_SERVER_KDC) + printf("NBT_SERVER_KDC "); + if (server_type & NBT_SERVER_TIMESERV) + printf("NBT_SERVER_TIMESERV "); + if (server_type & NBT_SERVER_CLOSEST) + printf("NBT_SERVER_CLOSEST "); + if (server_type & NBT_SERVER_WRITABLE) + printf("NBT_SERVER_WRITABLE "); + if (server_type & NBT_SERVER_GOOD_TIMESERV) + printf("NBT_SERVER_GOOD_TIMESERV "); + if (server_type & NBT_SERVER_NDNC) + printf("NBT_SERVER_NDNC "); + if (server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) + printf("NBT_SERVER_SELECT_SECRET_DOMAIN_6"); + if (server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) + printf("NBT_SERVER_FULL_SECRET_DOMAIN_6"); + if (server_type & DS_DNS_CONTROLLER) + printf("DS_DNS_CONTROLLER "); + if (server_type & DS_DNS_DOMAIN) + printf("DS_DNS_DOMAIN "); + if (server_type & DS_DNS_FOREST_ROOT) + printf("DS_DNS_FOREST_ROOT "); + + printf("\n"); + + return true; +} + +bool torture_netlogon(struct torture_context *torture) +{ + bool ret = true; + NTSTATUS status; + struct ldap_connection *conn; + TALLOC_CTX *mem_ctx; + const char *host = torture_setting_string(torture, "host", NULL); + //const char *userdn = torture_setting_string(torture, "ldap_userdn", NULL); + //const char *secret = torture_setting_string(torture, "ldap_secret", NULL); + const char *url; + //const char *basedn; + //const char **partitions; + + mem_ctx = talloc_init("torture_ldap_netlogon"); + + url = talloc_asprintf(mem_ctx, "ldap://%s/", host); + + status = torture_ldap_connection(torture, &conn, url); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + + ret &= test_ldap_netlogon(torture, conn, host); + ret &= test_ldap_netlogon_flags(torture, conn, host); + + return ret; +} diff --git a/source4/torture/wscript_build b/source4/torture/wscript_build index c3c997ada2..61c3a09148 100755 --- a/source4/torture/wscript_build +++ b/source4/torture/wscript_build @@ -108,7 +108,7 @@ bld.SAMBA_MODULE('TORTURE_UNIX', bld.SAMBA_MODULE('TORTURE_LDAP', - source='ldap/common.c ldap/basic.c ldap/schema.c ldap/uptodatevector.c ldap/cldap.c ldap/cldapbench.c ldap/ldap_sort.c ldap/nested_search.c', + source='ldap/common.c ldap/basic.c ldap/schema.c ldap/uptodatevector.c ldap/cldap.c ldap/netlogon.c ldap/cldapbench.c ldap/ldap_sort.c ldap/nested_search.c', subsystem='smbtorture', deps='cli-ldap cli_cldap samdb POPT_CREDENTIALS torture ldbsamba', internal_module=True, |