The Samba-Bugzilla – Attachment 9882 Details for
Bug 10524
samba returns 0 results to the LDAP query with filter (&(&(DnsDomain=NETAPP.TEST)(Host=STORE-SIM))(NtVer=0x00000006))
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
patches cherry-picked from master for 4.1
netlogon-over-ldap-tcp-v4.1.patch (text/plain), 107.99 KB, created by
Andrew Bartlett
on 2014-04-28 08:34:26 UTC
(
hide
)
Description:
patches cherry-picked from master for 4.1
Filename:
MIME Type:
Creator:
Andrew Bartlett
Created:
2014-04-28 08:34:26 UTC
Size:
107.99 KB
patch
obsolete
>From 3853a0383a606376f8a66eb1460517a923eca0a1 Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Fri, 1 Nov 2013 10:24:43 +0100 >Subject: [PATCH 01/10] s4:torture/cldap: Fix a typo > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> >(cherry picked from commit 32ee231da590d7b8aee74728a423b282ae845bce) >--- > source4/torture/ldap/cldap.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/torture/ldap/cldap.c b/source4/torture/ldap/cldap.c >index fc8c337..28859a5 100644 >--- a/source4/torture/ldap/cldap.c >+++ b/source4/torture/ldap/cldap.c >@@ -463,7 +463,7 @@ static bool test_cldap_generic(struct torture_context *tctx, const char *dest) > if (DEBUGLVL(3)) cldap_dump_results(&search); > > printf("Testing objectClass=* and netlogon\n"); >- search.in.filter = "(objectclass2=*)"; >+ search.in.filter = "(objectclass=*)"; > search.in.attributes = attrs3; > > status = cldap_search(cldap, tctx, &search); >-- >1.9.0 > > >From 10840b099cc80409c6422035c8e1ffde28629199 Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Sun, 27 Oct 2013 16:07:04 +0100 >Subject: [PATCH 02/10] s4:cldap_server: Move netlogon parsing into utility > function > >To be used later by netlogon-request over ldap. > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> >(cherry picked from commit 372127416825a8a947cd976f8a4165611c006c43) >--- > source4/cldap_server/cldap_server.h | 11 +++++ > source4/cldap_server/netlogon.c | 96 ++++++++++++++++++++++++------------- > 2 files changed, 73 insertions(+), 34 deletions(-) > >diff --git a/source4/cldap_server/cldap_server.h b/source4/cldap_server/cldap_server.h >index fe7788f..995ceed 100644 >--- a/source4/cldap_server/cldap_server.h >+++ b/source4/cldap_server/cldap_server.h >@@ -47,4 +47,15 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, > struct netlogon_samlogon_response *netlogon, > bool fill_on_blank_request); > >+NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree, >+ struct loadparm_context *lp_ctx, >+ TALLOC_CTX *mem_ctx, >+ const char **domain, >+ const char **host, >+ const char **user, >+ const char **domain_guid, >+ struct dom_sid **domain_sid, >+ int *acct_control, >+ int *version); >+ > #include "cldap_server/proto.h" >diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c >index 6d5efb5..0894b2b 100644 >--- a/source4/cldap_server/netlogon.c >+++ b/source4/cldap_server/netlogon.c >@@ -369,27 +369,26 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, > return NT_STATUS_OK; > } > >- >-/* >- handle incoming cldap requests >-*/ >-void cldapd_netlogon_request(struct cldap_socket *cldap, >- struct cldapd_server *cldapd, >- TALLOC_CTX *tmp_ctx, >- uint32_t message_id, >- struct ldb_parse_tree *tree, >- struct tsocket_address *src) >+NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree, >+ struct loadparm_context *lp_ctx, >+ TALLOC_CTX *tmp_ctx, >+ const char **domain, >+ const char **host, >+ const char **user, >+ const char **domain_guid, >+ struct dom_sid **domain_sid, >+ int *acct_control, >+ int *version) > { > unsigned int i; >- const char *domain = NULL; >- const char *host = NULL; >- const char *user = NULL; >- const char *domain_guid = NULL; >- struct dom_sid *domain_sid = NULL; >- int acct_control = -1; >- int version = -1; >- struct netlogon_samlogon_response netlogon; >- NTSTATUS status = NT_STATUS_INVALID_PARAMETER; >+ >+ *domain = NULL; >+ *host = NULL; >+ *user = NULL; >+ *domain_guid = NULL; >+ *domain_sid = NULL; >+ *acct_control = -1; >+ *version = -1; > > if (tree->operation != LDB_OP_AND) goto failed; > >@@ -398,12 +397,12 @@ void cldapd_netlogon_request(struct cldap_socket *cldap, > struct ldb_parse_tree *t = tree->u.list.elements[i]; > if (t->operation != LDB_OP_EQUALITY) goto failed; > if (strcasecmp(t->u.equality.attr, "DnsDomain") == 0) { >- domain = talloc_strndup(tmp_ctx, >+ *domain = talloc_strndup(tmp_ctx, > (const char *)t->u.equality.value.data, > t->u.equality.value.length); > } > if (strcasecmp(t->u.equality.attr, "Host") == 0) { >- host = talloc_strndup(tmp_ctx, >+ *host = talloc_strndup(tmp_ctx, > (const char *)t->u.equality.value.data, > t->u.equality.value.length); > } >@@ -413,50 +412,79 @@ void cldapd_netlogon_request(struct cldap_socket *cldap, > enc_status = ldap_decode_ndr_GUID(tmp_ctx, > t->u.equality.value, &guid); > if (NT_STATUS_IS_OK(enc_status)) { >- domain_guid = GUID_string(tmp_ctx, &guid); >+ *domain_guid = GUID_string(tmp_ctx, &guid); > } > } > if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) { > enum ndr_err_code ndr_err; > >- domain_sid = talloc(tmp_ctx, struct dom_sid); >- if (domain_sid == NULL) { >+ *domain_sid = talloc(tmp_ctx, struct dom_sid); >+ if (*domain_sid == NULL) { > goto failed; > } > ndr_err = ndr_pull_struct_blob(&t->u.equality.value, >- domain_sid, domain_sid, >+ *domain_sid, *domain_sid, > (ndr_pull_flags_fn_t)ndr_pull_dom_sid); > if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- talloc_free(domain_sid); >+ talloc_free(*domain_sid); > goto failed; > } > } > if (strcasecmp(t->u.equality.attr, "User") == 0) { >- user = talloc_strndup(tmp_ctx, >- (const char *)t->u.equality.value.data, >- t->u.equality.value.length); >+ *user = talloc_strndup(tmp_ctx, >+ (const char *)t->u.equality.value.data, >+ t->u.equality.value.length); > } > if (strcasecmp(t->u.equality.attr, "NtVer") == 0 && > t->u.equality.value.length == 4) { >- version = IVAL(t->u.equality.value.data, 0); >+ *version = IVAL(t->u.equality.value.data, 0); > } > if (strcasecmp(t->u.equality.attr, "AAC") == 0 && > t->u.equality.value.length == 4) { >- acct_control = IVAL(t->u.equality.value.data, 0); >+ *acct_control = IVAL(t->u.equality.value.data, 0); > } > } > >- if ((domain == NULL) && (domain_guid == NULL) && (domain_sid == NULL)) { >- domain = lpcfg_dnsdomain(cldapd->task->lp_ctx); >+ if ((*domain == NULL) && (*domain_guid == NULL) && (*domain_sid == NULL)) { >+ *domain = lpcfg_dnsdomain(lp_ctx); > } > >- if (version == -1) { >+ if (*version == -1) { > goto failed; > } > >+ return NT_STATUS_OK; >+ >+failed: >+ return NT_STATUS_UNSUCCESSFUL; >+} >+ >+/* >+ handle incoming cldap requests >+*/ >+void cldapd_netlogon_request(struct cldap_socket *cldap, >+ struct cldapd_server *cldapd, >+ TALLOC_CTX *tmp_ctx, >+ uint32_t message_id, >+ struct ldb_parse_tree *tree, >+ struct tsocket_address *src) >+{ >+ const char *domain, *host, *user, *domain_guid; >+ struct dom_sid *domain_sid; >+ int acct_control, version; >+ struct netlogon_samlogon_response netlogon; >+ NTSTATUS status = NT_STATUS_INVALID_PARAMETER; >+ > DEBUG(5,("cldap netlogon query domain=%s host=%s user=%s version=%d guid=%s\n", > domain, host, user, version, domain_guid)); > >+ status = parse_netlogon_request(tree, cldapd->task->lp_ctx, tmp_ctx, >+ &domain, &host, &user, &domain_guid, >+ &domain_sid, &acct_control, &version); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto failed; >+ } >+ > status = fill_netlogon_samlogon_response(cldapd->samctx, tmp_ctx, > domain, NULL, domain_sid, > domain_guid, >-- >1.9.0 > > >From b287dd9a87c76ec82f940d7626d384f7c2dde142 Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Fri, 6 Sep 2013 16:20:43 +0200 >Subject: [PATCH 03/10] provision: Fix string replacement ordering > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> >(cherry picked from commit ca8acb681a1ccaddf85376ff30c9b13b1a4c943d) >--- > python/samba/provision/__init__.py | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py >index 4af6b69..46d2cbc 100644 >--- a/python/samba/provision/__init__.py >+++ b/python/samba/provision/__init__.py >@@ -595,7 +595,7 @@ def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None, > raise ProvisioningError("guess_names: 'realm =' was not specified in supplied %s. Please remove the smb.conf file and let provision generate it" % lp.configfile) > > if lp.get("realm").upper() != realm: >- raise ProvisioningError("guess_names: 'realm=%s' in %s must match chosen realm '%s'! Please remove the smb.conf file and let provision generate it" % (lp.get("realm").upper(), realm, lp.configfile)) >+ raise ProvisioningError("guess_names: 'realm=%s' in %s must match chosen realm '%s'! Please remove the smb.conf file and let provision generate it" % (lp.get("realm").upper(), lp.configfile, realm)) > > if lp.get("server role").lower() != serverrole: > raise ProvisioningError("guess_names: 'server role=%s' in %s must match chosen server role '%s'! Please remove the smb.conf file and let provision generate it" % (lp.get("server role"), lp.configfile, serverrole)) >-- >1.9.0 > > >From ebc089d3c96a9868bdbefe05cc6bc41b864474cb Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Fri, 1 Nov 2013 06:55:41 +0100 >Subject: [PATCH 04/10] s4:dsdb/rootdse: Pass rootdse context to > rootdse_add_dynamic > >This replaced the *module parameter, and uses ac->module in the function >instead, same for *req and *attrs. > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> >(cherry picked from commit 7a5a62547bc10053fb1e4850e0acacb6a837f36f) >--- > source4/dsdb/samdb/ldb_modules/rootdse.c | 39 ++++++++++++++++---------------- > 1 file changed, 19 insertions(+), 20 deletions(-) > >diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c >index 167201e..bcae804 100644 >--- a/source4/dsdb/samdb/ldb_modules/rootdse.c >+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c >@@ -43,6 +43,11 @@ struct private_data { > bool block_anonymous; > }; > >+struct rootdse_context { >+ struct ldb_module *module; >+ struct ldb_request *req; >+}; >+ > /* > return 1 if a specific attribute has been requested > */ >@@ -216,11 +221,11 @@ static int dsdb_module_we_are_master(struct ldb_module *module, struct ldb_dn *d > /* > add dynamically generated attributes to rootDSE result > */ >-static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *msg, >- const char * const *attrs, struct ldb_request *req) >+static int rootdse_add_dynamic(struct rootdse_context *ac, struct ldb_message *msg) > { > struct ldb_context *ldb; >- struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data); >+ struct private_data *priv = talloc_get_type(ldb_module_get_private(ac->module), struct private_data); >+ const char * const *attrs = ac->req->op.search.attrs; > char **server_sasl; > const struct dsdb_schema *schema; > int *val; >@@ -241,7 +246,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms > }; > unsigned int i; > >- ldb = ldb_module_get_ctx(module); >+ ldb = ldb_module_get_ctx(ac->module); > schema = dsdb_get_schema(ldb, NULL); > > msg->dn = ldb_dn_new(msg, ldb, NULL); >@@ -262,11 +267,11 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms > struct ldb_result *res; > int ret; > const char *dns_attrs[] = { "dNSHostName", NULL }; >- ret = dsdb_module_search_dn(module, msg, &res, samdb_server_dn(ldb, msg), >+ ret = dsdb_module_search_dn(ac->module, msg, &res, samdb_server_dn(ldb, msg), > dns_attrs, > DSDB_FLAG_NEXT_MODULE | > DSDB_FLAG_AS_SYSTEM, >- req); >+ ac->req); > if (ret == LDB_SUCCESS) { > const char *hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL); > if (hostname != NULL) { >@@ -402,7 +407,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms > > for (i=0; i<3; i++) { > bool master; >- int ret = dsdb_module_we_are_master(module, dns[i], &master, req); >+ int ret = dsdb_module_we_are_master(ac->module, dns[i], &master, ac->req); > if (ret != LDB_SUCCESS) { > goto failed; > } >@@ -474,7 +479,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms > > /* TODO: lots more dynamic attributes should be added here */ > >- edn_control = ldb_request_get_control(req, LDB_CONTROL_EXTENDED_DN_OID); >+ edn_control = ldb_request_get_control(ac->req, LDB_CONTROL_EXTENDED_DN_OID); > > /* convert any GUID attributes to be in the right form */ > for (i=0; guid_attrs[i]; i++) { >@@ -486,17 +491,17 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms > > if (!do_attribute(attrs, guid_attrs[i])) continue; > >- attr_dn = ldb_msg_find_attr_as_dn(ldb, req, msg, guid_attrs[i]); >+ attr_dn = ldb_msg_find_attr_as_dn(ldb, ac->req, msg, guid_attrs[i]); > if (attr_dn == NULL) { > continue; > } > >- ret = dsdb_module_search_dn(module, req, &res, >+ ret = dsdb_module_search_dn(ac->module, ac->req, &res, > attr_dn, no_attrs, > DSDB_FLAG_NEXT_MODULE | > DSDB_FLAG_AS_SYSTEM | > DSDB_SEARCH_SHOW_EXTENDED_DN, >- req); >+ ac->req); > if (ret != LDB_SUCCESS) { > return ldb_operr(ldb); > } >@@ -534,8 +539,8 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms > int ret; > for (i=0; dn_attrs[i]; i++) { > if (!do_attribute(attrs, dn_attrs[i])) continue; >- ret = expand_dn_in_message(module, msg, dn_attrs[i], >- edn_control, req); >+ ret = expand_dn_in_message(ac->module, msg, dn_attrs[i], >+ edn_control, ac->req); > if (ret != LDB_SUCCESS) { > DEBUG(0,(__location__ ": Failed to expand DN in rootDSE for %s\n", > dn_attrs[i])); >@@ -554,11 +559,6 @@ failed: > handle search requests > */ > >-struct rootdse_context { >- struct ldb_module *module; >- struct ldb_request *req; >-}; >- > static struct rootdse_context *rootdse_init_context(struct ldb_module *module, > struct ldb_request *req) > { >@@ -609,8 +609,7 @@ static int rootdse_callback(struct ldb_request *req, struct ldb_reply *ares) > > /* for each record returned post-process to add any dynamic > attributes that have been asked for */ >- ret = rootdse_add_dynamic(ac->module, ares->message, >- ac->req->op.search.attrs, ac->req); >+ ret = rootdse_add_dynamic(ac, ares->message); > if (ret != LDB_SUCCESS) { > talloc_free(ares); > return ldb_module_done(ac->req, NULL, NULL, ret); >-- >1.9.0 > > >From 15c7ab99f1a28e313b455b49330e5bb35dc06bcb Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Sun, 27 Oct 2013 06:55:48 +0100 >Subject: [PATCH 05/10] s4:dsdb/rootdse: Support netlogon request > >This patch adds support for a netlogon ldap style request >over the tcp socket. This is available since win2k3+ [1]. > >The automatic client join & configuration daemon "realmd" makes >use of this ability. >Realmd can now be used to join a computer to a samba 4 domain. >(See also: >https://lists.samba.org/archive/samba-technical/2013-October/095606.html) > >Tested with: >ldapsearch -h samba-srv -x -b '' -s base "(&(NtVer=\06\00\00\00)(AAC=\00\00\00\00))" NetLogon > >And compared the result in wireshark with cldap request issued by >examples/misc/cldap.pl. > >[1]: http://wiki.wireshark.org/MS-CLDAP?action=recall&rev=8 > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> >(cherry picked from commit 0620c79d76b69811fd6c00d912db05477d894724) >--- > source4/dsdb/samdb/ldb_modules/rootdse.c | 83 +++++++++++++++++++--- > .../dsdb/samdb/ldb_modules/wscript_build_server | 2 +- > source4/ldap_server/ldap_backend.c | 3 + > 3 files changed, 77 insertions(+), 11 deletions(-) > >diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c >index bcae804..f905aa2 100644 >--- a/source4/dsdb/samdb/ldb_modules/rootdse.c >+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c >@@ -34,6 +34,8 @@ > #include "param/param.h" > #include "lib/messaging/irpc.h" > #include "librpc/gen_ndr/ndr_irpc_c.h" >+#include "lib/tsocket/tsocket.h" >+#include "cldap_server/cldap_server.h" > > struct private_data { > unsigned int num_controls; >@@ -46,6 +48,7 @@ struct private_data { > struct rootdse_context { > struct ldb_module *module; > struct ldb_request *req; >+ struct ldb_val netlogon; > }; > > /* >@@ -477,6 +480,12 @@ static int rootdse_add_dynamic(struct rootdse_context *ac, struct ldb_message *m > } > } > >+ if (ac->netlogon.length > 0) { >+ if (ldb_msg_add_steal_value(msg, "netlogon", &ac->netlogon) != LDB_SUCCESS) { >+ goto failed; >+ } >+ } >+ > /* TODO: lots more dynamic attributes should be added here */ > > edn_control = ldb_request_get_control(ac->req, LDB_CONTROL_EXTENDED_DN_OID); >@@ -597,16 +606,6 @@ static int rootdse_callback(struct ldb_request *req, struct ldb_reply *ares) > > switch (ares->type) { > case LDB_REPLY_ENTRY: >- /* >- * if the client explicit asks for the 'netlogon' attribute >- * the reply_entry needs to be skipped >- */ >- if (ac->req->op.search.attrs && >- ldb_attr_in_list(ac->req->op.search.attrs, "netlogon")) { >- talloc_free(ares); >- return LDB_SUCCESS; >- } >- > /* for each record returned post-process to add any dynamic > attributes that have been asked for */ > ret = rootdse_add_dynamic(ac, ares->message); >@@ -743,6 +742,62 @@ static int rootdse_filter_operations(struct ldb_module *module, struct ldb_reque > return LDB_ERR_OPERATIONS_ERROR; > } > >+static int rootdse_handle_netlogon(struct rootdse_context *ac) >+{ >+ struct ldb_context *ldb; >+ struct ldb_parse_tree *tree; >+ struct loadparm_context *lp_ctx; >+ struct tsocket_address *src_addr; >+ TALLOC_CTX *tmp_ctx = talloc_new(ac->req); >+ const char *domain, *host, *user, *domain_guid; >+ char *src_addr_s = NULL; >+ struct dom_sid *domain_sid; >+ int acct_control = -1; >+ int version = -1; >+ NTSTATUS status; >+ struct netlogon_samlogon_response netlogon; >+ int ret = LDB_ERR_OPERATIONS_ERROR; >+ >+ ldb = ldb_module_get_ctx(ac->module); >+ tree = ac->req->op.search.tree; >+ lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"), >+ struct loadparm_context); >+ src_addr = talloc_get_type(ldb_get_opaque(ldb, "remoteAddress"), >+ struct tsocket_address); >+ if (src_addr) { >+ src_addr_s = tsocket_address_inet_addr_string(src_addr, >+ tmp_ctx); >+ } >+ >+ status = parse_netlogon_request(tree, lp_ctx, tmp_ctx, >+ &domain, &host, &user, &domain_guid, >+ &domain_sid, &acct_control, &version); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto failed; >+ } >+ >+ status = fill_netlogon_samlogon_response(ldb, tmp_ctx, >+ domain, NULL, domain_sid, >+ domain_guid, >+ user, acct_control, >+ src_addr_s, >+ version, lp_ctx, >+ &netlogon, false); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto failed; >+ } >+ >+ status = push_netlogon_samlogon_response(&ac->netlogon, ac, &netlogon); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto failed; >+ } >+ >+ ret = LDB_SUCCESS; >+failed: >+ talloc_free(tmp_ctx); >+ return ret; >+} >+ > static int rootdse_search(struct ldb_module *module, struct ldb_request *req) > { > struct ldb_context *ldb; >@@ -773,6 +828,14 @@ static int rootdse_search(struct ldb_module *module, struct ldb_request *req) > return ldb_operr(ldb); > } > >+ if (do_attribute_explicit(req->op.search.attrs, "netlogon")) { >+ ret = rootdse_handle_netlogon(ac); >+ /* We have to return an empty result, so dont forward `ret' */ >+ if (ret != LDB_SUCCESS) { >+ return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS); >+ } >+ } >+ > /* in our db we store the rootDSE with a DN of @ROOTDSE */ > ret = ldb_build_search_req(&down_req, ldb, ac, > ldb_dn_new(ac, ldb, "@ROOTDSE"), >diff --git a/source4/dsdb/samdb/ldb_modules/wscript_build_server b/source4/dsdb/samdb/ldb_modules/wscript_build_server >index 41eb0f3..7ad1d3b 100755 >--- a/source4/dsdb/samdb/ldb_modules/wscript_build_server >+++ b/source4/dsdb/samdb/ldb_modules/wscript_build_server >@@ -106,7 +106,7 @@ bld.SAMBA_MODULE('ldb_rootdse', > init_function='ldb_rootdse_module_init', > module_init_name='ldb_init_module', > internal_module=False, >- deps='talloc samdb MESSAGING samba-security DSDB_MODULE_HELPERS RPC_NDR_IRPC' >+ deps='talloc samdb MESSAGING samba-security DSDB_MODULE_HELPERS RPC_NDR_IRPC CLDAPD' > ) > > >diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c >index f415e9b..4a195e5 100644 >--- a/source4/ldap_server/ldap_backend.c >+++ b/source4/ldap_server/ldap_backend.c >@@ -225,6 +225,9 @@ NTSTATUS ldapsrv_backend_Init(struct ldapsrv_connection *conn) > ldb_set_opaque(conn->ldb, "supportedSASLMechanisms", sasl_mechs); > } > >+ ldb_set_opaque(conn->ldb, "remoteAddress", >+ conn->connection->remote_address); >+ > return NT_STATUS_OK; > } > >-- >1.9.0 > > >From 9ef202be0f6c760b5b512db2ca3fc9032625fc18 Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Fri, 1 Nov 2013 10:52:02 +0100 >Subject: [PATCH 06/10] s4:cldap_server: Do not handle netlogon ourself anymore > >Netlogon is now handled by the ldb rootdse module. > >The netlogon files will be moved to dsdb in the next commit. > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> >(cherry picked from commit 7106dcf2b8525ec653f24e417d846f9d00172b6d) >--- > source4/cldap_server/cldap_server.c | 12 --------- > source4/cldap_server/netlogon.c | 50 ------------------------------------- > source4/cldap_server/rootdse.c | 5 ++++ > 3 files changed, 5 insertions(+), 62 deletions(-) > >diff --git a/source4/cldap_server/cldap_server.c b/source4/cldap_server/cldap_server.c >index a6248d4..774142e 100644 >--- a/source4/cldap_server/cldap_server.c >+++ b/source4/cldap_server/cldap_server.c >@@ -80,18 +80,6 @@ static void cldapd_request_handler(struct cldap_socket *cldap, > return; > } > >- if (search->num_attributes == 1 && >- strcasecmp(search->attributes[0], "netlogon") == 0) { >- cldapd_netlogon_request(cldap, >- cldapd, >- in, >- in->ldap_msg->messageid, >- search->tree, >- in->src); >- talloc_free(in); >- return; >- } >- > cldapd_rootdse_request(cldap, cldapd, in, > in->ldap_msg->messageid, > search, in->src); >diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c >index 0894b2b..231bd16 100644 >--- a/source4/cldap_server/netlogon.c >+++ b/source4/cldap_server/netlogon.c >@@ -458,53 +458,3 @@ NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree, > failed: > return NT_STATUS_UNSUCCESSFUL; > } >- >-/* >- handle incoming cldap requests >-*/ >-void cldapd_netlogon_request(struct cldap_socket *cldap, >- struct cldapd_server *cldapd, >- TALLOC_CTX *tmp_ctx, >- uint32_t message_id, >- struct ldb_parse_tree *tree, >- struct tsocket_address *src) >-{ >- const char *domain, *host, *user, *domain_guid; >- struct dom_sid *domain_sid; >- int acct_control, version; >- struct netlogon_samlogon_response netlogon; >- NTSTATUS status = NT_STATUS_INVALID_PARAMETER; >- >- DEBUG(5,("cldap netlogon query domain=%s host=%s user=%s version=%d guid=%s\n", >- domain, host, user, version, domain_guid)); >- >- status = parse_netlogon_request(tree, cldapd->task->lp_ctx, tmp_ctx, >- &domain, &host, &user, &domain_guid, >- &domain_sid, &acct_control, &version); >- if (!NT_STATUS_IS_OK(status)) { >- goto failed; >- } >- >- status = fill_netlogon_samlogon_response(cldapd->samctx, tmp_ctx, >- domain, NULL, domain_sid, >- domain_guid, >- user, acct_control, >- tsocket_address_inet_addr_string(src, tmp_ctx), >- version, cldapd->task->lp_ctx, >- &netlogon, false); >- if (!NT_STATUS_IS_OK(status)) { >- goto failed; >- } >- >- status = cldap_netlogon_reply(cldap, message_id, src, version, &netlogon); >- if (!NT_STATUS_IS_OK(status)) { >- goto failed; >- } >- >- return; >- >-failed: >- DEBUG(2,("cldap netlogon query failed domain=%s host=%s version=%d - %s\n", >- domain, host, version, nt_errstr(status))); >- cldap_empty_reply(cldap, message_id, src); >-} >diff --git a/source4/cldap_server/rootdse.c b/source4/cldap_server/rootdse.c >index b895616..3f389ce 100644 >--- a/source4/cldap_server/rootdse.c >+++ b/source4/cldap_server/rootdse.c >@@ -158,6 +158,11 @@ void cldapd_rootdse_request(struct cldap_socket *cldap, > reply.response = NULL; > reply.result = &result; > >+ /* Note: The remoteAddress should rather be set on a ldb request. >+ * We can set this savely on the context here, >+ * since cldapd_rootdse_fill operates synchronously. */ >+ ldb_set_opaque(cldapd->samctx, "remoteAddress", src); >+ > cldapd_rootdse_fill(cldapd, tmp_ctx, search, &reply.response, > reply.result); > >-- >1.9.0 > > >From 3199d75589dfa0ec3f2247550efed7c3622971ad Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Tue, 5 Nov 2013 20:39:56 +0100 >Subject: [PATCH 07/10] s4:dsdb: Move cldap netlogon functions into > samdb/ldb_modules > >As netlogon is handled by the samdb now, >the corresponding functions should live there as well. > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> >(cherry picked from commit 68ebb09193e73cff4389ccb9e3b190b12ee0a84a) >--- > source4/cldap_server/cldap_server.h | 26 -- > source4/cldap_server/netlogon.c | 460 --------------------- > source4/cldap_server/wscript_build | 2 +- > source4/dsdb/samdb/ldb_modules/netlogon.c | 460 +++++++++++++++++++++ > source4/dsdb/samdb/ldb_modules/util.h | 2 + > source4/dsdb/samdb/ldb_modules/wscript_build | 2 +- > .../dsdb/samdb/ldb_modules/wscript_build_server | 2 +- > source4/nbt_server/dgram/netlogon.c | 2 +- > source4/nbt_server/wscript_build | 2 +- > source4/rpc_server/netlogon/dcerpc_netlogon.c | 2 +- > source4/rpc_server/wscript_build | 2 +- > 11 files changed, 469 insertions(+), 493 deletions(-) > delete mode 100644 source4/cldap_server/netlogon.c > create mode 100644 source4/dsdb/samdb/ldb_modules/netlogon.c > >diff --git a/source4/cldap_server/cldap_server.h b/source4/cldap_server/cldap_server.h >index 995ceed..0725284 100644 >--- a/source4/cldap_server/cldap_server.h >+++ b/source4/cldap_server/cldap_server.h >@@ -32,30 +32,4 @@ struct cldapd_server { > > struct ldap_SearchRequest; > >-/* used by netlogon DCE/RPC server */ >-NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, >- TALLOC_CTX *mem_ctx, >- const char *domain, >- const char *netbios_domain, >- struct dom_sid *domain_sid, >- const char *domain_guid, >- const char *user, >- uint32_t acct_control, >- const char *src_address, >- uint32_t version, >- struct loadparm_context *lp_ctx, >- struct netlogon_samlogon_response *netlogon, >- bool fill_on_blank_request); >- >-NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree, >- struct loadparm_context *lp_ctx, >- TALLOC_CTX *mem_ctx, >- const char **domain, >- const char **host, >- const char **user, >- const char **domain_guid, >- struct dom_sid **domain_sid, >- int *acct_control, >- int *version); >- > #include "cldap_server/proto.h" >diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c >deleted file mode 100644 >index 231bd16..0000000 >--- a/source4/cldap_server/netlogon.c >+++ /dev/null >@@ -1,460 +0,0 @@ >-/* >- Unix SMB/CIFS implementation. >- >- CLDAP server - netlogon handling >- >- Copyright (C) Andrew Tridgell 2005 >- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008 >- >- 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.h> >-#include <ldb_errors.h> >-#include "lib/events/events.h" >-#include "smbd/service_task.h" >-#include "cldap_server/cldap_server.h" >-#include "librpc/gen_ndr/ndr_misc.h" >-#include "libcli/ldap/ldap_ndr.h" >-#include "libcli/security/security.h" >-#include "dsdb/samdb/samdb.h" >-#include "auth/auth.h" >-#include "ldb_wrap.h" >-#include "system/network.h" >-#include "lib/socket/netif.h" >-#include "param/param.h" >-#include "../lib/tsocket/tsocket.h" >-#include "libds/common/flag_mapping.h" >-#include "lib/util/util_net.h" >- >-/* >- fill in the cldap netlogon union for a given version >-*/ >-NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, >- TALLOC_CTX *mem_ctx, >- const char *domain, >- const char *netbios_domain, >- struct dom_sid *domain_sid, >- const char *domain_guid, >- const char *user, >- uint32_t acct_control, >- const char *src_address, >- uint32_t version, >- struct loadparm_context *lp_ctx, >- struct netlogon_samlogon_response *netlogon, >- bool fill_on_blank_request) >-{ >- const char *dom_attrs[] = {"objectGUID", NULL}; >- const char *none_attrs[] = {NULL}; >- struct ldb_result *dom_res = NULL, *user_res = NULL; >- int ret; >- const char **services = lpcfg_server_services(lp_ctx); >- uint32_t server_type; >- const char *pdc_name; >- struct GUID domain_uuid; >- const char *dns_domain; >- const char *forest_domain; >- const char *pdc_dns_name; >- const char *flatname; >- const char *server_site; >- const char *client_site; >- const char *pdc_ip; >- struct ldb_dn *domain_dn = NULL; >- struct interface *ifaces; >- bool user_known = false, am_rodc = false; >- NTSTATUS status; >- >- /* the domain parameter could have an optional trailing "." */ >- if (domain && domain[strlen(domain)-1] == '.') { >- domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1); >- NT_STATUS_HAVE_NO_MEMORY(domain); >- } >- >- /* Lookup using long or short domainname */ >- if (domain && (strcasecmp_m(domain, lpcfg_dnsdomain(lp_ctx)) == 0)) { >- domain_dn = ldb_get_default_basedn(sam_ctx); >- } >- if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) { >- domain_dn = ldb_get_default_basedn(sam_ctx); >- } >- if (domain_dn) { >- const char *domain_identifier = domain != NULL ? domain >- : netbios_domain; >- ret = ldb_search(sam_ctx, mem_ctx, &dom_res, >- domain_dn, LDB_SCOPE_BASE, dom_attrs, >- "objectClass=domain"); >- if (ret != LDB_SUCCESS) { >- DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", >- domain_identifier, >- ldb_dn_get_linearized(domain_dn), >- ldb_errstring(sam_ctx))); >- return NT_STATUS_NO_SUCH_DOMAIN; >- } >- if (dom_res->count != 1) { >- DEBUG(2,("Error finding domain '%s'/'%s' in sam\n", >- domain_identifier, >- ldb_dn_get_linearized(domain_dn))); >- return NT_STATUS_NO_SUCH_DOMAIN; >- } >- } >- >- /* Lookup using GUID or SID */ >- if ((dom_res == NULL) && (domain_guid || domain_sid)) { >- if (domain_guid) { >- struct GUID binary_guid; >- struct ldb_val guid_val; >- >- /* By this means, we ensure we don't have funny stuff in the GUID */ >- >- status = GUID_from_string(domain_guid, &binary_guid); >- if (!NT_STATUS_IS_OK(status)) { >- return status; >- } >- >- /* And this gets the result into the binary format we want anyway */ >- status = GUID_to_ndr_blob(&binary_guid, mem_ctx, &guid_val); >- if (!NT_STATUS_IS_OK(status)) { >- return status; >- } >- ret = ldb_search(sam_ctx, mem_ctx, &dom_res, >- NULL, LDB_SCOPE_SUBTREE, >- dom_attrs, >- "(&(objectCategory=DomainDNS)(objectGUID=%s))", >- ldb_binary_encode(mem_ctx, guid_val)); >- } else { /* domain_sid case */ >- ret = ldb_search(sam_ctx, mem_ctx, &dom_res, >- NULL, LDB_SCOPE_SUBTREE, >- dom_attrs, >- "(&(objectCategory=DomainDNS)(objectSid=%s))", >- dom_sid_string(mem_ctx, domain_sid)); >- } >- >- if (ret != LDB_SUCCESS) { >- DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam: %s\n", >- domain_guid, dom_sid_string(mem_ctx, domain_sid), >- ldb_errstring(sam_ctx))); >- return NT_STATUS_NO_SUCH_DOMAIN; >- } else if (dom_res->count == 1) { >- /* Ok, now just check it is our domain */ >- if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx), >- dom_res->msgs[0]->dn) != 0) { >- DEBUG(2,("The GUID '%s' or SID '%s' doesn't identify our domain\n", >- domain_guid, >- dom_sid_string(mem_ctx, domain_sid))); >- return NT_STATUS_NO_SUCH_DOMAIN; >- } >- } else { >- DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam\n", >- domain_guid, dom_sid_string(mem_ctx, domain_sid))); >- return NT_STATUS_NO_SUCH_DOMAIN; >- } >- } >- >- if (dom_res == NULL && fill_on_blank_request) { >- /* blank inputs gives our domain - tested against >- w2k8r2. Without this ADUC on Win7 won't start */ >- domain_dn = ldb_get_default_basedn(sam_ctx); >- ret = ldb_search(sam_ctx, mem_ctx, &dom_res, >- domain_dn, LDB_SCOPE_BASE, dom_attrs, >- "objectClass=domain"); >- if (ret != LDB_SUCCESS) { >- DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", >- lpcfg_dnsdomain(lp_ctx), >- ldb_dn_get_linearized(domain_dn), >- ldb_errstring(sam_ctx))); >- return NT_STATUS_NO_SUCH_DOMAIN; >- } >- } >- >- if (dom_res == NULL) { >- DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n")); >- return NT_STATUS_NO_SUCH_DOMAIN; >- } >- >- /* work around different inputs for not-specified users */ >- if (!user) { >- user = ""; >- } >- >- /* Enquire about any valid username with just a CLDAP packet - >- * if kerberos didn't also do this, the security folks would >- * scream... */ >- if (user[0]) { \ >- /* Only allow some bits to be enquired: [MS-ATDS] 7.3.3.2 */ >- if (acct_control == (uint32_t)-1) { >- acct_control = 0; >- } >- acct_control = acct_control & (ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); >- >- /* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */ >- ret = ldb_search(sam_ctx, mem_ctx, &user_res, >- dom_res->msgs[0]->dn, LDB_SCOPE_SUBTREE, >- none_attrs, >- "(&(objectClass=user)(samAccountName=%s)" >- "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))" >- "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))", >- ldb_binary_encode_string(mem_ctx, user), >- UF_ACCOUNTDISABLE, ds_acb2uf(acct_control)); >- if (ret != LDB_SUCCESS) { >- DEBUG(2,("Unable to find reference to user '%s' with ACB 0x%8x under %s: %s\n", >- user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn), >- ldb_errstring(sam_ctx))); >- return NT_STATUS_NO_SUCH_USER; >- } else if (user_res->count == 1) { >- user_known = true; >- } else { >- user_known = false; >- } >- >- } else { >- user_known = true; >- } >- >- server_type = DS_SERVER_DS; >- >- if (samdb_is_pdc(sam_ctx)) { >- server_type |= DS_SERVER_PDC; >- } >- >- if (samdb_is_gc(sam_ctx)) { >- server_type |= DS_SERVER_GC; >- } >- >- if (str_list_check(services, "ldap")) { >- server_type |= DS_SERVER_LDAP; >- } >- >- if (str_list_check(services, "kdc")) { >- server_type |= DS_SERVER_KDC; >- } >- >- if (str_list_check(services, "ntp_signd")) { >- server_type |= DS_SERVER_TIMESERV | DS_SERVER_GOOD_TIMESERV; >- } >- >- if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) { >- server_type |= DS_SERVER_WRITABLE; >- } >- >- if (dsdb_functional_level(sam_ctx) >= DS_DOMAIN_FUNCTION_2008) { >- if (server_type & DS_SERVER_WRITABLE) { >- server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6; >- } else { >- server_type |= DS_SERVER_SELECT_SECRET_DOMAIN_6; >- } >- } >- >- if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) { >- pdc_name = lpcfg_netbios_name(lp_ctx); >- } else { >- pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", >- lpcfg_netbios_name(lp_ctx)); >- NT_STATUS_HAVE_NO_MEMORY(pdc_name); >- } >- domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); >- dns_domain = lpcfg_dnsdomain(lp_ctx); >- forest_domain = samdb_forest_name(sam_ctx, mem_ctx); >- NT_STATUS_HAVE_NO_MEMORY(forest_domain); >- pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s", >- strlower_talloc(mem_ctx, >- lpcfg_netbios_name(lp_ctx)), >- dns_domain); >- NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name); >- flatname = lpcfg_workgroup(lp_ctx); >- >- server_site = samdb_server_site_name(sam_ctx, mem_ctx); >- NT_STATUS_HAVE_NO_MEMORY(server_site); >- client_site = samdb_client_site_name(sam_ctx, mem_ctx, >- src_address, NULL); >- NT_STATUS_HAVE_NO_MEMORY(client_site); >- if (strcasecmp(server_site, client_site) == 0) { >- server_type |= DS_SERVER_CLOSEST; >- } >- >- load_interface_list(mem_ctx, lp_ctx, &ifaces); >- if (src_address) { >- pdc_ip = iface_list_best_ip(ifaces, src_address); >- } else { >- pdc_ip = iface_list_first_v4(ifaces); >- } >- if (pdc_ip == NULL || !is_ipaddress_v4(pdc_ip)) { >- /* this matches windows behaviour */ >- pdc_ip = "127.0.0.1"; >- } >- >- ZERO_STRUCTP(netlogon); >- >- /* check if either of these bits is present */ >- if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) { >- uint32_t extra_flags = 0; >- netlogon->ntver = NETLOGON_NT_VERSION_5EX; >- >- /* could check if the user exists */ >- if (user_known) { >- netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_RESPONSE_EX; >- } else { >- netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_USER_UNKNOWN_EX; >- } >- netlogon->data.nt5_ex.pdc_name = pdc_name; >- netlogon->data.nt5_ex.user_name = user; >- netlogon->data.nt5_ex.domain_name = flatname; >- netlogon->data.nt5_ex.domain_uuid = domain_uuid; >- netlogon->data.nt5_ex.forest = forest_domain; >- netlogon->data.nt5_ex.dns_domain = dns_domain; >- netlogon->data.nt5_ex.pdc_dns_name = pdc_dns_name; >- netlogon->data.nt5_ex.server_site = server_site; >- netlogon->data.nt5_ex.client_site = client_site; >- if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) { >- /* note that this is always a IPV4 address */ >- extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP; >- netlogon->data.nt5_ex.sockaddr.sockaddr_family = 2; >- netlogon->data.nt5_ex.sockaddr.pdc_ip = pdc_ip; >- netlogon->data.nt5_ex.sockaddr.remaining = data_blob_talloc_zero(mem_ctx, 8); >- } >- netlogon->data.nt5_ex.server_type = server_type; >- netlogon->data.nt5_ex.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5EX|extra_flags; >- netlogon->data.nt5_ex.lmnt_token = 0xFFFF; >- netlogon->data.nt5_ex.lm20_token = 0xFFFF; >- >- } else if (version & NETLOGON_NT_VERSION_5) { >- netlogon->ntver = NETLOGON_NT_VERSION_5; >- >- /* could check if the user exists */ >- if (user_known) { >- netlogon->data.nt5.command = LOGON_SAM_LOGON_RESPONSE; >- } else { >- netlogon->data.nt5.command = LOGON_SAM_LOGON_USER_UNKNOWN; >- } >- netlogon->data.nt5.pdc_name = pdc_name; >- netlogon->data.nt5.user_name = user; >- netlogon->data.nt5.domain_name = flatname; >- netlogon->data.nt5.domain_uuid = domain_uuid; >- netlogon->data.nt5.forest = forest_domain; >- netlogon->data.nt5.dns_domain = dns_domain; >- netlogon->data.nt5.pdc_dns_name = pdc_dns_name; >- netlogon->data.nt5.pdc_ip = pdc_ip; >- netlogon->data.nt5.server_type = server_type; >- netlogon->data.nt5.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5; >- netlogon->data.nt5.lmnt_token = 0xFFFF; >- netlogon->data.nt5.lm20_token = 0xFFFF; >- >- } else /* (version & NETLOGON_NT_VERSION_1) and all other cases */ { >- netlogon->ntver = NETLOGON_NT_VERSION_1; >- /* could check if the user exists */ >- if (user_known) { >- netlogon->data.nt4.command = LOGON_SAM_LOGON_RESPONSE; >- } else { >- netlogon->data.nt4.command = LOGON_SAM_LOGON_USER_UNKNOWN; >- } >- netlogon->data.nt4.pdc_name = pdc_name; >- netlogon->data.nt4.user_name = user; >- netlogon->data.nt4.domain_name = flatname; >- netlogon->data.nt4.nt_version = NETLOGON_NT_VERSION_1; >- netlogon->data.nt4.lmnt_token = 0xFFFF; >- netlogon->data.nt4.lm20_token = 0xFFFF; >- } >- >- return NT_STATUS_OK; >-} >- >-NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree, >- struct loadparm_context *lp_ctx, >- TALLOC_CTX *tmp_ctx, >- const char **domain, >- const char **host, >- const char **user, >- const char **domain_guid, >- struct dom_sid **domain_sid, >- int *acct_control, >- int *version) >-{ >- unsigned int i; >- >- *domain = NULL; >- *host = NULL; >- *user = NULL; >- *domain_guid = NULL; >- *domain_sid = NULL; >- *acct_control = -1; >- *version = -1; >- >- if (tree->operation != LDB_OP_AND) goto failed; >- >- /* extract the query elements */ >- for (i=0;i<tree->u.list.num_elements;i++) { >- struct ldb_parse_tree *t = tree->u.list.elements[i]; >- if (t->operation != LDB_OP_EQUALITY) goto failed; >- if (strcasecmp(t->u.equality.attr, "DnsDomain") == 0) { >- *domain = talloc_strndup(tmp_ctx, >- (const char *)t->u.equality.value.data, >- t->u.equality.value.length); >- } >- if (strcasecmp(t->u.equality.attr, "Host") == 0) { >- *host = talloc_strndup(tmp_ctx, >- (const char *)t->u.equality.value.data, >- t->u.equality.value.length); >- } >- if (strcasecmp(t->u.equality.attr, "DomainGuid") == 0) { >- NTSTATUS enc_status; >- struct GUID guid; >- enc_status = ldap_decode_ndr_GUID(tmp_ctx, >- t->u.equality.value, &guid); >- if (NT_STATUS_IS_OK(enc_status)) { >- *domain_guid = GUID_string(tmp_ctx, &guid); >- } >- } >- if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) { >- enum ndr_err_code ndr_err; >- >- *domain_sid = talloc(tmp_ctx, struct dom_sid); >- if (*domain_sid == NULL) { >- goto failed; >- } >- ndr_err = ndr_pull_struct_blob(&t->u.equality.value, >- *domain_sid, *domain_sid, >- (ndr_pull_flags_fn_t)ndr_pull_dom_sid); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- talloc_free(*domain_sid); >- goto failed; >- } >- } >- if (strcasecmp(t->u.equality.attr, "User") == 0) { >- *user = talloc_strndup(tmp_ctx, >- (const char *)t->u.equality.value.data, >- t->u.equality.value.length); >- } >- if (strcasecmp(t->u.equality.attr, "NtVer") == 0 && >- t->u.equality.value.length == 4) { >- *version = IVAL(t->u.equality.value.data, 0); >- } >- if (strcasecmp(t->u.equality.attr, "AAC") == 0 && >- t->u.equality.value.length == 4) { >- *acct_control = IVAL(t->u.equality.value.data, 0); >- } >- } >- >- if ((*domain == NULL) && (*domain_guid == NULL) && (*domain_sid == NULL)) { >- *domain = lpcfg_dnsdomain(lp_ctx); >- } >- >- if (*version == -1) { >- goto failed; >- } >- >- return NT_STATUS_OK; >- >-failed: >- return NT_STATUS_UNSUCCESSFUL; >-} >diff --git a/source4/cldap_server/wscript_build b/source4/cldap_server/wscript_build >index 6ffdb4a..928b91b 100644 >--- a/source4/cldap_server/wscript_build >+++ b/source4/cldap_server/wscript_build >@@ -10,7 +10,7 @@ bld.SAMBA_MODULE('service_cldap', > > > bld.SAMBA_SUBSYSTEM('CLDAPD', >- source='netlogon.c rootdse.c', >+ source='rootdse.c', > autoproto='proto.h', > deps='cli_cldap ldbsamba' > ) >diff --git a/source4/dsdb/samdb/ldb_modules/netlogon.c b/source4/dsdb/samdb/ldb_modules/netlogon.c >new file mode 100644 >index 0000000..a381da8 >--- /dev/null >+++ b/source4/dsdb/samdb/ldb_modules/netlogon.c >@@ -0,0 +1,460 @@ >+/* >+ Unix SMB/CIFS implementation. >+ >+ CLDAP server - netlogon handling >+ >+ Copyright (C) Andrew Tridgell 2005 >+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008 >+ >+ 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.h> >+#include <ldb_errors.h> >+#include "lib/events/events.h" >+#include "smbd/service_task.h" >+#include "librpc/gen_ndr/ndr_misc.h" >+#include "libcli/ldap/ldap_ndr.h" >+#include "libcli/security/security.h" >+#include "dsdb/samdb/samdb.h" >+#include "dsdb/samdb/ldb_modules/util.h" >+#include "auth/auth.h" >+#include "ldb_wrap.h" >+#include "system/network.h" >+#include "lib/socket/netif.h" >+#include "param/param.h" >+#include "../lib/tsocket/tsocket.h" >+#include "libds/common/flag_mapping.h" >+#include "lib/util/util_net.h" >+ >+/* >+ fill in the cldap netlogon union for a given version >+*/ >+NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, >+ TALLOC_CTX *mem_ctx, >+ const char *domain, >+ const char *netbios_domain, >+ struct dom_sid *domain_sid, >+ const char *domain_guid, >+ const char *user, >+ uint32_t acct_control, >+ const char *src_address, >+ uint32_t version, >+ struct loadparm_context *lp_ctx, >+ struct netlogon_samlogon_response *netlogon, >+ bool fill_on_blank_request) >+{ >+ const char *dom_attrs[] = {"objectGUID", NULL}; >+ const char *none_attrs[] = {NULL}; >+ struct ldb_result *dom_res = NULL, *user_res = NULL; >+ int ret; >+ const char **services = lpcfg_server_services(lp_ctx); >+ uint32_t server_type; >+ const char *pdc_name; >+ struct GUID domain_uuid; >+ const char *dns_domain; >+ const char *forest_domain; >+ const char *pdc_dns_name; >+ const char *flatname; >+ const char *server_site; >+ const char *client_site; >+ const char *pdc_ip; >+ struct ldb_dn *domain_dn = NULL; >+ struct interface *ifaces; >+ bool user_known = false, am_rodc = false; >+ NTSTATUS status; >+ >+ /* the domain parameter could have an optional trailing "." */ >+ if (domain && domain[strlen(domain)-1] == '.') { >+ domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1); >+ NT_STATUS_HAVE_NO_MEMORY(domain); >+ } >+ >+ /* Lookup using long or short domainname */ >+ if (domain && (strcasecmp_m(domain, lpcfg_dnsdomain(lp_ctx)) == 0)) { >+ domain_dn = ldb_get_default_basedn(sam_ctx); >+ } >+ if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) { >+ domain_dn = ldb_get_default_basedn(sam_ctx); >+ } >+ if (domain_dn) { >+ const char *domain_identifier = domain != NULL ? domain >+ : netbios_domain; >+ ret = ldb_search(sam_ctx, mem_ctx, &dom_res, >+ domain_dn, LDB_SCOPE_BASE, dom_attrs, >+ "objectClass=domain"); >+ if (ret != LDB_SUCCESS) { >+ DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", >+ domain_identifier, >+ ldb_dn_get_linearized(domain_dn), >+ ldb_errstring(sam_ctx))); >+ return NT_STATUS_NO_SUCH_DOMAIN; >+ } >+ if (dom_res->count != 1) { >+ DEBUG(2,("Error finding domain '%s'/'%s' in sam\n", >+ domain_identifier, >+ ldb_dn_get_linearized(domain_dn))); >+ return NT_STATUS_NO_SUCH_DOMAIN; >+ } >+ } >+ >+ /* Lookup using GUID or SID */ >+ if ((dom_res == NULL) && (domain_guid || domain_sid)) { >+ if (domain_guid) { >+ struct GUID binary_guid; >+ struct ldb_val guid_val; >+ >+ /* By this means, we ensure we don't have funny stuff in the GUID */ >+ >+ status = GUID_from_string(domain_guid, &binary_guid); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ /* And this gets the result into the binary format we want anyway */ >+ status = GUID_to_ndr_blob(&binary_guid, mem_ctx, &guid_val); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ ret = ldb_search(sam_ctx, mem_ctx, &dom_res, >+ NULL, LDB_SCOPE_SUBTREE, >+ dom_attrs, >+ "(&(objectCategory=DomainDNS)(objectGUID=%s))", >+ ldb_binary_encode(mem_ctx, guid_val)); >+ } else { /* domain_sid case */ >+ ret = ldb_search(sam_ctx, mem_ctx, &dom_res, >+ NULL, LDB_SCOPE_SUBTREE, >+ dom_attrs, >+ "(&(objectCategory=DomainDNS)(objectSid=%s))", >+ dom_sid_string(mem_ctx, domain_sid)); >+ } >+ >+ if (ret != LDB_SUCCESS) { >+ DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam: %s\n", >+ domain_guid, dom_sid_string(mem_ctx, domain_sid), >+ ldb_errstring(sam_ctx))); >+ return NT_STATUS_NO_SUCH_DOMAIN; >+ } else if (dom_res->count == 1) { >+ /* Ok, now just check it is our domain */ >+ if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx), >+ dom_res->msgs[0]->dn) != 0) { >+ DEBUG(2,("The GUID '%s' or SID '%s' doesn't identify our domain\n", >+ domain_guid, >+ dom_sid_string(mem_ctx, domain_sid))); >+ return NT_STATUS_NO_SUCH_DOMAIN; >+ } >+ } else { >+ DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam\n", >+ domain_guid, dom_sid_string(mem_ctx, domain_sid))); >+ return NT_STATUS_NO_SUCH_DOMAIN; >+ } >+ } >+ >+ if (dom_res == NULL && fill_on_blank_request) { >+ /* blank inputs gives our domain - tested against >+ w2k8r2. Without this ADUC on Win7 won't start */ >+ domain_dn = ldb_get_default_basedn(sam_ctx); >+ ret = ldb_search(sam_ctx, mem_ctx, &dom_res, >+ domain_dn, LDB_SCOPE_BASE, dom_attrs, >+ "objectClass=domain"); >+ if (ret != LDB_SUCCESS) { >+ DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", >+ lpcfg_dnsdomain(lp_ctx), >+ ldb_dn_get_linearized(domain_dn), >+ ldb_errstring(sam_ctx))); >+ return NT_STATUS_NO_SUCH_DOMAIN; >+ } >+ } >+ >+ if (dom_res == NULL) { >+ DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n")); >+ return NT_STATUS_NO_SUCH_DOMAIN; >+ } >+ >+ /* work around different inputs for not-specified users */ >+ if (!user) { >+ user = ""; >+ } >+ >+ /* Enquire about any valid username with just a CLDAP packet - >+ * if kerberos didn't also do this, the security folks would >+ * scream... */ >+ if (user[0]) { \ >+ /* Only allow some bits to be enquired: [MS-ATDS] 7.3.3.2 */ >+ if (acct_control == (uint32_t)-1) { >+ acct_control = 0; >+ } >+ acct_control = acct_control & (ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); >+ >+ /* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */ >+ ret = ldb_search(sam_ctx, mem_ctx, &user_res, >+ dom_res->msgs[0]->dn, LDB_SCOPE_SUBTREE, >+ none_attrs, >+ "(&(objectClass=user)(samAccountName=%s)" >+ "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))" >+ "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))", >+ ldb_binary_encode_string(mem_ctx, user), >+ UF_ACCOUNTDISABLE, ds_acb2uf(acct_control)); >+ if (ret != LDB_SUCCESS) { >+ DEBUG(2,("Unable to find reference to user '%s' with ACB 0x%8x under %s: %s\n", >+ user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn), >+ ldb_errstring(sam_ctx))); >+ return NT_STATUS_NO_SUCH_USER; >+ } else if (user_res->count == 1) { >+ user_known = true; >+ } else { >+ user_known = false; >+ } >+ >+ } else { >+ user_known = true; >+ } >+ >+ server_type = DS_SERVER_DS; >+ >+ if (samdb_is_pdc(sam_ctx)) { >+ server_type |= DS_SERVER_PDC; >+ } >+ >+ if (samdb_is_gc(sam_ctx)) { >+ server_type |= DS_SERVER_GC; >+ } >+ >+ if (str_list_check(services, "ldap")) { >+ server_type |= DS_SERVER_LDAP; >+ } >+ >+ if (str_list_check(services, "kdc")) { >+ server_type |= DS_SERVER_KDC; >+ } >+ >+ if (str_list_check(services, "ntp_signd")) { >+ server_type |= DS_SERVER_TIMESERV | DS_SERVER_GOOD_TIMESERV; >+ } >+ >+ if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) { >+ server_type |= DS_SERVER_WRITABLE; >+ } >+ >+ if (dsdb_functional_level(sam_ctx) >= DS_DOMAIN_FUNCTION_2008) { >+ if (server_type & DS_SERVER_WRITABLE) { >+ server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6; >+ } else { >+ server_type |= DS_SERVER_SELECT_SECRET_DOMAIN_6; >+ } >+ } >+ >+ if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) { >+ pdc_name = lpcfg_netbios_name(lp_ctx); >+ } else { >+ pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", >+ lpcfg_netbios_name(lp_ctx)); >+ NT_STATUS_HAVE_NO_MEMORY(pdc_name); >+ } >+ domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); >+ dns_domain = lpcfg_dnsdomain(lp_ctx); >+ forest_domain = samdb_forest_name(sam_ctx, mem_ctx); >+ NT_STATUS_HAVE_NO_MEMORY(forest_domain); >+ pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s", >+ strlower_talloc(mem_ctx, >+ lpcfg_netbios_name(lp_ctx)), >+ dns_domain); >+ NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name); >+ flatname = lpcfg_workgroup(lp_ctx); >+ >+ server_site = samdb_server_site_name(sam_ctx, mem_ctx); >+ NT_STATUS_HAVE_NO_MEMORY(server_site); >+ client_site = samdb_client_site_name(sam_ctx, mem_ctx, >+ src_address, NULL); >+ NT_STATUS_HAVE_NO_MEMORY(client_site); >+ if (strcasecmp(server_site, client_site) == 0) { >+ server_type |= DS_SERVER_CLOSEST; >+ } >+ >+ load_interface_list(mem_ctx, lp_ctx, &ifaces); >+ if (src_address) { >+ pdc_ip = iface_list_best_ip(ifaces, src_address); >+ } else { >+ pdc_ip = iface_list_first_v4(ifaces); >+ } >+ if (pdc_ip == NULL || !is_ipaddress_v4(pdc_ip)) { >+ /* this matches windows behaviour */ >+ pdc_ip = "127.0.0.1"; >+ } >+ >+ ZERO_STRUCTP(netlogon); >+ >+ /* check if either of these bits is present */ >+ if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) { >+ uint32_t extra_flags = 0; >+ netlogon->ntver = NETLOGON_NT_VERSION_5EX; >+ >+ /* could check if the user exists */ >+ if (user_known) { >+ netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_RESPONSE_EX; >+ } else { >+ netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_USER_UNKNOWN_EX; >+ } >+ netlogon->data.nt5_ex.pdc_name = pdc_name; >+ netlogon->data.nt5_ex.user_name = user; >+ netlogon->data.nt5_ex.domain_name = flatname; >+ netlogon->data.nt5_ex.domain_uuid = domain_uuid; >+ netlogon->data.nt5_ex.forest = forest_domain; >+ netlogon->data.nt5_ex.dns_domain = dns_domain; >+ netlogon->data.nt5_ex.pdc_dns_name = pdc_dns_name; >+ netlogon->data.nt5_ex.server_site = server_site; >+ netlogon->data.nt5_ex.client_site = client_site; >+ if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) { >+ /* note that this is always a IPV4 address */ >+ extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP; >+ netlogon->data.nt5_ex.sockaddr.sockaddr_family = 2; >+ netlogon->data.nt5_ex.sockaddr.pdc_ip = pdc_ip; >+ netlogon->data.nt5_ex.sockaddr.remaining = data_blob_talloc_zero(mem_ctx, 8); >+ } >+ netlogon->data.nt5_ex.server_type = server_type; >+ netlogon->data.nt5_ex.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5EX|extra_flags; >+ netlogon->data.nt5_ex.lmnt_token = 0xFFFF; >+ netlogon->data.nt5_ex.lm20_token = 0xFFFF; >+ >+ } else if (version & NETLOGON_NT_VERSION_5) { >+ netlogon->ntver = NETLOGON_NT_VERSION_5; >+ >+ /* could check if the user exists */ >+ if (user_known) { >+ netlogon->data.nt5.command = LOGON_SAM_LOGON_RESPONSE; >+ } else { >+ netlogon->data.nt5.command = LOGON_SAM_LOGON_USER_UNKNOWN; >+ } >+ netlogon->data.nt5.pdc_name = pdc_name; >+ netlogon->data.nt5.user_name = user; >+ netlogon->data.nt5.domain_name = flatname; >+ netlogon->data.nt5.domain_uuid = domain_uuid; >+ netlogon->data.nt5.forest = forest_domain; >+ netlogon->data.nt5.dns_domain = dns_domain; >+ netlogon->data.nt5.pdc_dns_name = pdc_dns_name; >+ netlogon->data.nt5.pdc_ip = pdc_ip; >+ netlogon->data.nt5.server_type = server_type; >+ netlogon->data.nt5.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5; >+ netlogon->data.nt5.lmnt_token = 0xFFFF; >+ netlogon->data.nt5.lm20_token = 0xFFFF; >+ >+ } else /* (version & NETLOGON_NT_VERSION_1) and all other cases */ { >+ netlogon->ntver = NETLOGON_NT_VERSION_1; >+ /* could check if the user exists */ >+ if (user_known) { >+ netlogon->data.nt4.command = LOGON_SAM_LOGON_RESPONSE; >+ } else { >+ netlogon->data.nt4.command = LOGON_SAM_LOGON_USER_UNKNOWN; >+ } >+ netlogon->data.nt4.pdc_name = pdc_name; >+ netlogon->data.nt4.user_name = user; >+ netlogon->data.nt4.domain_name = flatname; >+ netlogon->data.nt4.nt_version = NETLOGON_NT_VERSION_1; >+ netlogon->data.nt4.lmnt_token = 0xFFFF; >+ netlogon->data.nt4.lm20_token = 0xFFFF; >+ } >+ >+ return NT_STATUS_OK; >+} >+ >+NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree, >+ struct loadparm_context *lp_ctx, >+ TALLOC_CTX *tmp_ctx, >+ const char **domain, >+ const char **host, >+ const char **user, >+ const char **domain_guid, >+ struct dom_sid **domain_sid, >+ int *acct_control, >+ int *version) >+{ >+ unsigned int i; >+ >+ *domain = NULL; >+ *host = NULL; >+ *user = NULL; >+ *domain_guid = NULL; >+ *domain_sid = NULL; >+ *acct_control = -1; >+ *version = -1; >+ >+ if (tree->operation != LDB_OP_AND) goto failed; >+ >+ /* extract the query elements */ >+ for (i=0;i<tree->u.list.num_elements;i++) { >+ struct ldb_parse_tree *t = tree->u.list.elements[i]; >+ if (t->operation != LDB_OP_EQUALITY) goto failed; >+ if (strcasecmp(t->u.equality.attr, "DnsDomain") == 0) { >+ *domain = talloc_strndup(tmp_ctx, >+ (const char *)t->u.equality.value.data, >+ t->u.equality.value.length); >+ } >+ if (strcasecmp(t->u.equality.attr, "Host") == 0) { >+ *host = talloc_strndup(tmp_ctx, >+ (const char *)t->u.equality.value.data, >+ t->u.equality.value.length); >+ } >+ if (strcasecmp(t->u.equality.attr, "DomainGuid") == 0) { >+ NTSTATUS enc_status; >+ struct GUID guid; >+ enc_status = ldap_decode_ndr_GUID(tmp_ctx, >+ t->u.equality.value, &guid); >+ if (NT_STATUS_IS_OK(enc_status)) { >+ *domain_guid = GUID_string(tmp_ctx, &guid); >+ } >+ } >+ if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) { >+ enum ndr_err_code ndr_err; >+ >+ *domain_sid = talloc(tmp_ctx, struct dom_sid); >+ if (*domain_sid == NULL) { >+ goto failed; >+ } >+ ndr_err = ndr_pull_struct_blob(&t->u.equality.value, >+ *domain_sid, *domain_sid, >+ (ndr_pull_flags_fn_t)ndr_pull_dom_sid); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ talloc_free(*domain_sid); >+ goto failed; >+ } >+ } >+ if (strcasecmp(t->u.equality.attr, "User") == 0) { >+ *user = talloc_strndup(tmp_ctx, >+ (const char *)t->u.equality.value.data, >+ t->u.equality.value.length); >+ } >+ if (strcasecmp(t->u.equality.attr, "NtVer") == 0 && >+ t->u.equality.value.length == 4) { >+ *version = IVAL(t->u.equality.value.data, 0); >+ } >+ if (strcasecmp(t->u.equality.attr, "AAC") == 0 && >+ t->u.equality.value.length == 4) { >+ *acct_control = IVAL(t->u.equality.value.data, 0); >+ } >+ } >+ >+ if ((*domain == NULL) && (*domain_guid == NULL) && (*domain_sid == NULL)) { >+ *domain = lpcfg_dnsdomain(lp_ctx); >+ } >+ >+ if (*version == -1) { >+ goto failed; >+ } >+ >+ return NT_STATUS_OK; >+ >+failed: >+ return NT_STATUS_UNSUCCESSFUL; >+} >diff --git a/source4/dsdb/samdb/ldb_modules/util.h b/source4/dsdb/samdb/ldb_modules/util.h >index c213042..e407305 100644 >--- a/source4/dsdb/samdb/ldb_modules/util.h >+++ b/source4/dsdb/samdb/ldb_modules/util.h >@@ -25,10 +25,12 @@ struct dsdb_attribute; > struct dsdb_fsmo_extended_op; > struct security_descriptor; > struct dom_sid; >+struct netlogon_samlogon_response; > > #include "librpc/gen_ndr/misc.h" > #include "dsdb/samdb/ldb_modules/util_proto.h" > #include "dsdb/common/util.h" >+#include "../libcli/netlogon/netlogon.h" > > /* extend the dsdb_request_add_controls() flags for module > specific functions */ >diff --git a/source4/dsdb/samdb/ldb_modules/wscript_build b/source4/dsdb/samdb/ldb_modules/wscript_build >index 7e45c60..0df5fe0 100755 >--- a/source4/dsdb/samdb/ldb_modules/wscript_build >+++ b/source4/dsdb/samdb/ldb_modules/wscript_build >@@ -7,7 +7,7 @@ bld.SAMBA_LIBRARY('dsdb-module', > grouping_library=True) > > bld.SAMBA_SUBSYSTEM('DSDB_MODULE_HELPERS', >- source='util.c acl_util.c schema_util.c', >+ source='util.c acl_util.c schema_util.c netlogon.c', > autoproto='util_proto.h', > deps='ldb ndr samdb-common samba-security' > ) >diff --git a/source4/dsdb/samdb/ldb_modules/wscript_build_server b/source4/dsdb/samdb/ldb_modules/wscript_build_server >index 7ad1d3b..41eb0f3 100755 >--- a/source4/dsdb/samdb/ldb_modules/wscript_build_server >+++ b/source4/dsdb/samdb/ldb_modules/wscript_build_server >@@ -106,7 +106,7 @@ bld.SAMBA_MODULE('ldb_rootdse', > init_function='ldb_rootdse_module_init', > module_init_name='ldb_init_module', > internal_module=False, >- deps='talloc samdb MESSAGING samba-security DSDB_MODULE_HELPERS RPC_NDR_IRPC CLDAPD' >+ deps='talloc samdb MESSAGING samba-security DSDB_MODULE_HELPERS RPC_NDR_IRPC' > ) > > >diff --git a/source4/nbt_server/dgram/netlogon.c b/source4/nbt_server/dgram/netlogon.c >index 3f0fa54..0e5294c 100644 >--- a/source4/nbt_server/dgram/netlogon.c >+++ b/source4/nbt_server/dgram/netlogon.c >@@ -28,7 +28,7 @@ > #include "auth/auth.h" > #include "param/param.h" > #include "smbd/service_task.h" >-#include "cldap_server/cldap_server.h" >+#include "dsdb/samdb/ldb_modules/util.h" > #include "libcli/security/security.h" > #include "nbt_server/dgram/proto.h" > >diff --git a/source4/nbt_server/wscript_build b/source4/nbt_server/wscript_build >index 665ccd4..9d0c24a 100644 >--- a/source4/nbt_server/wscript_build >+++ b/source4/nbt_server/wscript_build >@@ -30,7 +30,7 @@ bld.SAMBA_SUBSYSTEM('NBTD_WINS', > bld.SAMBA_SUBSYSTEM('NBTD_DGRAM', > source='dgram/request.c dgram/netlogon.c dgram/browse.c', > autoproto='dgram/proto.h', >- deps='LIBCLI_DGRAM CLDAPD', >+ deps='LIBCLI_DGRAM DSDB_MODULE_HELPERS', > enabled=bld.AD_DC_BUILD_IS_ENABLED() > ) > >diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c >index d463e85..b3b9989 100644 >--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c >+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c >@@ -33,7 +33,7 @@ > #include "lib/messaging/irpc.h" > #include "librpc/gen_ndr/ndr_irpc_c.h" > #include "../libcli/ldap/ldap_ndr.h" >-#include "cldap_server/cldap_server.h" >+#include "dsdb/samdb/ldb_modules/util.h" > #include "lib/tsocket/tsocket.h" > #include "librpc/gen_ndr/ndr_netlogon.h" > #include "librpc/gen_ndr/ndr_irpc.h" >diff --git a/source4/rpc_server/wscript_build b/source4/rpc_server/wscript_build >index cc8efdb..2907f00 100755 >--- a/source4/rpc_server/wscript_build >+++ b/source4/rpc_server/wscript_build >@@ -96,7 +96,7 @@ bld.SAMBA_MODULE('dcerpc_netlogon', > source='netlogon/dcerpc_netlogon.c', > subsystem='dcerpc_server', > init_function='dcerpc_server_netlogon_init', >- deps='DCERPC_COMMON RPC_NDR_IRPC COMMON_SCHANNEL ndr-standard auth4_sam samba-hostconfig CLDAPD' >+ deps='DCERPC_COMMON RPC_NDR_IRPC COMMON_SCHANNEL ndr-standard auth4_sam samba-hostconfig DSDB_MODULE_HELPERS' > ) > > >-- >1.9.0 > > >From c44f885e1db54b3fa2c6bcabc0a91465abe28822 Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Mon, 28 Oct 2013 14:19:57 +0100 >Subject: [PATCH 08/10] libcli/cldap: Add utility to create netlogon filter > >This utility is splitted of from cldap_netlogon_send. > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> >(cherry picked from commit e306250a250d20a43cbe4c72ece34ebd475fa39c) >--- > libcli/cldap/cldap.c | 90 +++++++++++++++++++++++++++++----------------------- > libcli/cldap/cldap.h | 2 ++ > 2 files changed, 52 insertions(+), 40 deletions(-) > >diff --git a/libcli/cldap/cldap.c b/libcli/cldap/cldap.c >index 24ce39f..e543091 100644 >--- a/libcli/cldap/cldap.c >+++ b/libcli/cldap/cldap.c >@@ -882,81 +882,91 @@ struct cldap_netlogon_state { > struct cldap_search search; > }; > >-static void cldap_netlogon_state_done(struct tevent_req *subreq); >-/* >- queue a cldap netlogon for send >-*/ >-struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx, >- struct tevent_context *ev, >- struct cldap_socket *cldap, >- const struct cldap_netlogon *io) >+char *cldap_netlogon_create_filter(TALLOC_CTX *mem_ctx, >+ const struct cldap_netlogon *io) > { >- struct tevent_req *req, *subreq; >- struct cldap_netlogon_state *state; > char *filter; >- static const char * const attr[] = { "NetLogon", NULL }; > >- req = tevent_req_create(mem_ctx, &state, >- struct cldap_netlogon_state); >- if (!req) { >+ filter = talloc_asprintf(mem_ctx, "(&(NtVer=%s)", >+ ldap_encode_ndr_uint32(mem_ctx, io->in.version)); >+ if (filter == NULL) > return NULL; >- } > >- filter = talloc_asprintf(state, "(&(NtVer=%s)", >- ldap_encode_ndr_uint32(state, io->in.version)); >- if (tevent_req_nomem(filter, req)) { >- goto post; >- } > if (io->in.user) { > filter = talloc_asprintf_append_buffer(filter, "(User=%s)", io->in.user); >- if (tevent_req_nomem(filter, req)) { >- goto post; >+ if (filter == NULL) { >+ return NULL; > } > } > if (io->in.host) { > filter = talloc_asprintf_append_buffer(filter, "(Host=%s)", io->in.host); >- if (tevent_req_nomem(filter, req)) { >- goto post; >+ if (filter == NULL) { >+ return NULL; > } > } > if (io->in.realm) { > filter = talloc_asprintf_append_buffer(filter, "(DnsDomain=%s)", io->in.realm); >- if (tevent_req_nomem(filter, req)) { >- goto post; >+ if (filter == NULL) { >+ return NULL; > } > } > if (io->in.acct_control != -1) { > filter = talloc_asprintf_append_buffer(filter, "(AAC=%s)", >- ldap_encode_ndr_uint32(state, io->in.acct_control)); >- if (tevent_req_nomem(filter, req)) { >- goto post; >+ ldap_encode_ndr_uint32(mem_ctx, io->in.acct_control)); >+ if (filter == NULL) { >+ return NULL; > } > } > if (io->in.domain_sid) { >- struct dom_sid *sid = dom_sid_parse_talloc(state, io->in.domain_sid); >- if (tevent_req_nomem(sid, req)) { >- goto post; >+ struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, io->in.domain_sid); >+ if (filter == NULL) { >+ return NULL; > } > filter = talloc_asprintf_append_buffer(filter, "(domainSid=%s)", >- ldap_encode_ndr_dom_sid(state, sid)); >- if (tevent_req_nomem(filter, req)) { >- goto post; >+ ldap_encode_ndr_dom_sid(mem_ctx, sid)); >+ if (filter == NULL) { >+ return NULL; > } > } > if (io->in.domain_guid) { > struct GUID guid; > NTSTATUS status; > status = GUID_from_string(io->in.domain_guid, &guid); >- if (tevent_req_nterror(req, status)) { >- goto post; >+ if (filter == NULL) { >+ return NULL; > } > filter = talloc_asprintf_append_buffer(filter, "(DomainGuid=%s)", >- ldap_encode_ndr_GUID(state, &guid)); >- if (tevent_req_nomem(filter, req)) { >- goto post; >+ ldap_encode_ndr_GUID(mem_ctx, &guid)); >+ if (filter == NULL) { >+ return NULL; > } > } > filter = talloc_asprintf_append_buffer(filter, ")"); >+ >+ return filter; >+} >+ >+static void cldap_netlogon_state_done(struct tevent_req *subreq); >+/* >+ queue a cldap netlogon for send >+*/ >+struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ struct cldap_socket *cldap, >+ const struct cldap_netlogon *io) >+{ >+ struct tevent_req *req, *subreq; >+ struct cldap_netlogon_state *state; >+ char *filter; >+ static const char * const attr[] = { "NetLogon", NULL }; >+ >+ req = tevent_req_create(mem_ctx, &state, >+ struct cldap_netlogon_state); >+ if (!req) { >+ return NULL; >+ } >+ >+ filter = cldap_netlogon_create_filter(state, io); > if (tevent_req_nomem(filter, req)) { > goto post; > } >diff --git a/libcli/cldap/cldap.h b/libcli/cldap/cldap.h >index 0bc9454..cd76fee 100644 >--- a/libcli/cldap/cldap.h >+++ b/libcli/cldap/cldap.h >@@ -123,6 +123,8 @@ NTSTATUS cldap_netlogon_recv(struct tevent_req *req, > NTSTATUS cldap_netlogon(struct cldap_socket *cldap, > TALLOC_CTX *mem_ctx, > struct cldap_netlogon *io); >+char *cldap_netlogon_create_filter(TALLOC_CTX *mem_ctx, >+ const struct cldap_netlogon *io); > > NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, > uint32_t message_id, >-- >1.9.0 > > >From 378242e65aac3810d0b079e49dd6d3205a85f4ad Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Mon, 28 Oct 2013 14:21:20 +0100 >Subject: [PATCH 09/10] s4:torture/ldap: Add test for netlogon over tcp > >This patch moves the udp netlogon tests from cldap.c >to netlogon.c and passes a generic netlogon-send >function as parameter. > >Therefore a tcp replacement for cldap_netlogon is also added. >The two variants tcp and udp are added as 2 new torture tests: > >ldap.netlogon-udp & ldap.netlogon-tcp >Both tests succeed. > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> >(cherry picked from commit 767bd6a4d49efce1c554bb0bc8130d74331b0bd8) >--- > source4/torture/ldap/cldap.c | 329 ------------------------- > source4/torture/ldap/common.c | 2 + > source4/torture/ldap/netlogon.c | 516 ++++++++++++++++++++++++++++++++++++++++ > source4/torture/wscript_build | 2 +- > 4 files changed, 519 insertions(+), 330 deletions(-) > create mode 100644 source4/torture/ldap/netlogon.c > >diff --git a/source4/torture/ldap/cldap.c b/source4/torture/ldap/cldap.c >index 28859a5..6a925cf 100644 >--- a/source4/torture/ldap/cldap.c >+++ b/source4/torture/ldap/cldap.c >@@ -24,7 +24,6 @@ > #include "includes.h" > #include "libcli/cldap/cldap.h" > #include "libcli/ldap/ldap_client.h" >-#include "librpc/gen_ndr/netlogon.h" > #include "param/param.h" > #include "../lib/tsocket/tsocket.h" > >@@ -36,332 +35,6 @@ > #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"); >-/* >- test netlogon operations >-*/ >-static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest) >-{ >- struct cldap_socket *cldap; >- 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; >- >- ret = tsocket_address_inet_from_strings(tctx, "ip", >- dest, >- lpcfg_cldap_port(tctx->lp_ctx), >- &dest_addr); >- CHECK_VAL(ret, 0); >- >- status = cldap_socket_init(tctx, NULL, dest_addr, &cldap); >- CHECK_STATUS(status, NT_STATUS_OK); >- >- 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 = cldap_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 = cldap_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 = cldap_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 = cldap_netlogon(cldap, tctx, &search); >- CHECK_STATUS(status, NT_STATUS_OK); >- >- printf("Trying with User=NULL\n"); >- search.in.user = NULL; >- status = cldap_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 = cldap_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 = cldap_netlogon(cldap, tctx, &search); >- CHECK_STATUS(status, NT_STATUS_OK); >- >- printf("Trying with User=NULL\n"); >- search.in.user = NULL; >- status = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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 = cldap_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_cldap_netlogon_flags(struct torture_context *tctx, >- const char *dest) >-{ >- struct cldap_socket *cldap; >- NTSTATUS status; >- struct cldap_netlogon search; >- struct netlogon_samlogon_response n1; >- uint32_t server_type; >- struct tsocket_address *dest_addr; >- int ret; >- >- 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); >- >- 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 = cldap_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; >-} > > /* > convert a ldap result message to a ldb message. This allows us to >@@ -488,8 +161,6 @@ bool torture_cldap(struct torture_context *torture) > bool ret = true; > const char *host = torture_setting_string(torture, "host", NULL); > >- ret &= test_cldap_netlogon(torture, host); >- ret &= test_cldap_netlogon_flags(torture, host); > ret &= test_cldap_generic(torture, host); > > return ret; >diff --git a/source4/torture/ldap/common.c b/source4/torture/ldap/common.c >index 6b13229..e6290ba 100644 >--- a/source4/torture/ldap/common.c >+++ b/source4/torture/ldap/common.c >@@ -136,6 +136,8 @@ 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-udp", torture_netlogon_udp); >+ torture_suite_add_simple_test(suite, "netlogon-tcp", torture_netlogon_tcp); > 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 0000000..9ed058e >--- /dev/null >+++ b/source4/torture/ldap/netlogon.c >@@ -0,0 +1,516 @@ >+/* >+ Unix SMB/CIFS mplementation. >+ >+ test CLDAP/LDAP netlogon operations >+ >+ Copyright (C) Andrew Tridgell 2005 >+ Copyright (C) Matthias Dieter Wallnöfer 2009 >+ >+ 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 "libcli/cldap/cldap.h" >+#include "libcli/ldap/ldap_client.h" >+#include "librpc/gen_ndr/netlogon.h" >+#include "param/param.h" >+#include "../lib/tsocket/tsocket.h" >+ >+#include "torture/torture.h" >+#include "torture/ldap/proto.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"); >+ >+typedef NTSTATUS (*request_netlogon_t)(void *con, >+ TALLOC_CTX *mem_ctx, >+ struct cldap_netlogon *io); >+ >+/* >+ test netlogon operations >+*/ >+static bool test_ldap_netlogon(struct torture_context *tctx, >+ request_netlogon_t request_netlogon, >+ void *cldap, >+ const char *dest) >+{ >+ NTSTATUS status; >+ struct cldap_netlogon search, empty_search; >+ struct netlogon_samlogon_response n1; >+ struct GUID guid; >+ int i; >+ >+ 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 = request_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 = request_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 = request_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 = request_netlogon(cldap, tctx, &search); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ printf("Trying with User=NULL\n"); >+ search.in.user = NULL; >+ status = request_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 = request_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 = request_netlogon(cldap, tctx, &search); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ printf("Trying with User=NULL\n"); >+ search.in.user = NULL; >+ status = request_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 = request_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 = request_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 = request_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 = request_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 = request_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 = request_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 = request_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 = request_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 = request_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 = request_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 = request_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 = request_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 = request_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 = request_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, >+ request_netlogon_t request_netlogon, >+ void *cldap, >+ const char *dest) >+{ >+ NTSTATUS status; >+ struct cldap_netlogon search; >+ struct netlogon_samlogon_response n1; >+ uint32_t server_type; >+ >+ 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 = request_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; >+} >+ >+static NTSTATUS tcp_ldap_rootdse(void *data, >+ TALLOC_CTX *mem_ctx, >+ struct cldap_search *io) >+{ >+ struct ldap_connection *conn = talloc_get_type(data, >+ struct ldap_connection); >+ struct ldap_message *msg, *result; >+ struct ldap_request *req; >+ int i; >+ NTSTATUS status; >+ >+ 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, io->in.filter); >+ msg->r.SearchRequest.num_attributes = str_list_length(io->in.attributes); >+ msg->r.SearchRequest.attributes = io->in.attributes; >+ >+ req = ldap_request_send(conn, msg); >+ if (req == NULL) { >+ printf("Could not setup ldap search\n"); >+ return NT_STATUS_UNSUCCESSFUL; >+ } >+ >+ ZERO_STRUCT(io->out); >+ for (i = 0; i < 2; ++i) { >+ status = ldap_result_n(req, i, &result); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ switch (result->type) { >+ case LDAP_TAG_SearchResultEntry: >+ if (i != 0) { >+ return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); >+ } >+ io->out.response = &result->r.SearchResultEntry; >+ break; >+ case LDAP_TAG_SearchResultDone: >+ io->out.result = &result->r.SearchResultDone; >+ if (io->out.result->resultcode != LDAP_SUCCESS) { >+ return NT_STATUS_LDAP(io->out.result->resultcode); >+ } >+ >+ return NT_STATUS_OK; >+ default: >+ return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); >+ } >+ } >+ >+ return NT_STATUS_OK; >+} >+ >+static NTSTATUS tcp_ldap_netlogon(void *conn, >+ TALLOC_CTX *mem_ctx, >+ struct cldap_netlogon *io) >+{ >+ struct cldap_search search; >+ struct ldap_SearchResEntry *res; >+ NTSTATUS status; >+ DATA_BLOB *blob; >+ >+ ZERO_STRUCT(search); >+ search.in.attributes = (const char *[]) { "netlogon", NULL }; >+ search.in.filter = cldap_netlogon_create_filter(mem_ctx, io); >+ if (search.in.filter == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ status = tcp_ldap_rootdse(conn, mem_ctx, &search); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ res = search.out.response; >+ if (res == NULL) { >+ return NT_STATUS_NOT_FOUND; >+ } >+ >+ 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; >+ } >+ >+ blob = res->attributes[0].values; >+ status = pull_netlogon_samlogon_response(blob, 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; >+} >+ >+bool torture_netlogon_tcp(struct torture_context *tctx) >+{ >+ const char *host = torture_setting_string(tctx, "host", NULL); >+ bool ret = true; >+ NTSTATUS status; >+ struct ldap_connection *conn; >+ TALLOC_CTX *mem_ctx; >+ const char *url; >+ >+ mem_ctx = talloc_init("torture_ldap_netlogon"); >+ >+ url = talloc_asprintf(mem_ctx, "ldap://%s/", host); >+ >+ status = torture_ldap_connection(tctx, &conn, url); >+ if (!NT_STATUS_IS_OK(status)) { >+ return false; >+ } >+ >+ ret &= test_ldap_netlogon(tctx, tcp_ldap_netlogon, conn, host); >+ ret &= test_ldap_netlogon_flags(tctx, tcp_ldap_netlogon, conn, host); >+ >+ return ret; >+} >+ >+static NTSTATUS udp_ldap_netlogon(void *data, >+ TALLOC_CTX *mem_ctx, >+ struct cldap_netlogon *io) >+{ >+ struct cldap_socket *cldap = talloc_get_type(data, >+ struct cldap_socket); >+ >+ return cldap_netlogon(cldap, mem_ctx, io); >+} >+ >+bool torture_netlogon_udp(struct torture_context *tctx) >+{ >+ const char *host = torture_setting_string(tctx, "host", NULL); >+ bool ret = true; >+ int r; >+ struct cldap_socket *cldap; >+ NTSTATUS status; >+ struct tsocket_address *dest_addr; >+ >+ r = tsocket_address_inet_from_strings(tctx, "ip", >+ host, >+ lpcfg_cldap_port(tctx->lp_ctx), >+ &dest_addr); >+ CHECK_VAL(r, 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); >+ >+ ret &= test_ldap_netlogon(tctx, udp_ldap_netlogon, cldap, host); >+ ret &= test_ldap_netlogon_flags(tctx, udp_ldap_netlogon, cldap, host); >+ >+ return ret; >+} >diff --git a/source4/torture/wscript_build b/source4/torture/wscript_build >index c3c997a..61c3a09 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, >-- >1.9.0 > > >From fc2ee372a89defe9c34f21e6f1c90f4f948f1bbd Mon Sep 17 00:00:00 2001 >From: Benjamin Franzke <benjaminfranzke@googlemail.com> >Date: Thu, 31 Oct 2013 21:23:57 +0100 >Subject: [PATCH 10/10] s4:torture/netlogon: Test netlogon with additional > attrs > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Nadezhda Ivanova <nivanova@symas.com> > >se enter the commit message for your changes. Lines starting > >Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> >Autobuild-Date(master): Tue Nov 12 00:57:19 CET 2013 on sn-devel-104 > >(cherry picked from commit 0dd512eead6dc999511e9e21f5304a224653db85) >--- > source4/torture/ldap/netlogon.c | 83 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 83 insertions(+) > >diff --git a/source4/torture/ldap/netlogon.c b/source4/torture/ldap/netlogon.c >index 9ed058e..8c6345b 100644 >--- a/source4/torture/ldap/netlogon.c >+++ b/source4/torture/ldap/netlogon.c >@@ -24,6 +24,7 @@ > #include "includes.h" > #include "libcli/cldap/cldap.h" > #include "libcli/ldap/ldap_client.h" >+#include "libcli/ldap/ldap_ndr.h" > #include "librpc/gen_ndr/netlogon.h" > #include "param/param.h" > #include "../lib/tsocket/tsocket.h" >@@ -41,6 +42,10 @@ typedef NTSTATUS (*request_netlogon_t)(void *con, > TALLOC_CTX *mem_ctx, > struct cldap_netlogon *io); > >+typedef NTSTATUS (*request_rootdse_t)(void *con, >+ TALLOC_CTX *mem_ctx, >+ struct cldap_search *io); >+ > /* > test netlogon operations > */ >@@ -456,6 +461,82 @@ static NTSTATUS tcp_ldap_netlogon(void *conn, > return NT_STATUS_OK; > } > >+static NTSTATUS udp_ldap_rootdse(void *data, TALLOC_CTX *mem_ctx, >+ struct cldap_search *io) >+{ >+ struct cldap_socket *cldap = talloc_get_type(data, >+ struct cldap_socket); >+ >+ return cldap_search(cldap, mem_ctx, io); >+} >+ >+static bool test_netlogon_extra_attrs(struct torture_context *tctx, >+ request_rootdse_t request_rootdse, >+ void *conn) >+{ >+ struct cldap_search io; >+ NTSTATUS status; >+ const char *attrs[] = { >+ "netlogon", >+ "supportedCapabilities", >+ NULL >+ }; >+ const char *attrs2[] = { "netlogon", "*", NULL }; >+ struct ldb_message ldbmsg = { NULL, 0, NULL }; >+ >+ ZERO_STRUCT(io); >+ io.in.dest_address = NULL; >+ io.in.dest_port = 0; >+ io.in.timeout = 2; >+ io.in.retries = 2; >+ /* Additional attributes may be requested next to netlogon */ >+ torture_comment(tctx, "Requesting netlogon with additional attribute\n"); >+ io.in.filter = >+ talloc_asprintf(tctx, "(&" >+ "(NtVer=%s)(AAC=%s)" >+ /* Query for LDAP_CAP_ACTIVE_DIRECTORY_OID */ >+ "(supportedCapabilities=1.2.840.113556.1.4.800)" >+ ")", >+ ldap_encode_ndr_uint32(tctx, >+ NETLOGON_NT_VERSION_5EX), >+ ldap_encode_ndr_uint32(tctx, 0)); >+ torture_assert(tctx, io.in.filter != NULL, "OOM"); >+ io.in.attributes = attrs; >+ status = request_rootdse(conn, tctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ torture_assert(tctx, io.out.response != NULL, "No Entries found."); >+ CHECK_VAL(io.out.response->num_attributes, 2); >+ >+ /* netlogon + '*' attr return zero results */ >+ torture_comment(tctx, "Requesting netlogon and '*' attributes\n"); >+ io.in.attributes = attrs2; >+ status = request_rootdse(conn, tctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ torture_assert(tctx, io.out.response != NULL, "No Entries found."); >+ ldbmsg.num_elements = io.out.response->num_attributes; >+ ldbmsg.elements = io.out.response->attributes; >+ torture_assert(tctx, ldb_msg_find_element(&ldbmsg, "netlogon") != NULL, >+ "Attribute netlogon not found in Result Entry\n"); >+ >+ /* Wildcards are not allowed in filters when netlogon is requested. */ >+ torture_comment(tctx, "Requesting netlogon with invalid attr filter\n"); >+ io.in.filter = >+ talloc_asprintf(tctx, >+ "(&(NtVer=%s)(AAC=%s)(supportedCapabilities=*))", >+ ldap_encode_ndr_uint32(tctx, >+ NETLOGON_NT_VERSION_5EX), >+ ldap_encode_ndr_uint32(tctx, 0)); >+ torture_assert(tctx, io.in.filter != NULL, "OOM"); >+ io.in.attributes = attrs; >+ status = request_rootdse(conn, tctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ torture_assert(tctx, io.out.response == NULL, >+ "A wildcard filter should return no entries."); >+ >+ return true; >+} >+ >+ > bool torture_netlogon_tcp(struct torture_context *tctx) > { > const char *host = torture_setting_string(tctx, "host", NULL); >@@ -476,6 +557,7 @@ bool torture_netlogon_tcp(struct torture_context *tctx) > > ret &= test_ldap_netlogon(tctx, tcp_ldap_netlogon, conn, host); > ret &= test_ldap_netlogon_flags(tctx, tcp_ldap_netlogon, conn, host); >+ ret &= test_netlogon_extra_attrs(tctx, tcp_ldap_rootdse, conn); > > return ret; > } >@@ -511,6 +593,7 @@ bool torture_netlogon_udp(struct torture_context *tctx) > > ret &= test_ldap_netlogon(tctx, udp_ldap_netlogon, cldap, host); > ret &= test_ldap_netlogon_flags(tctx, udp_ldap_netlogon, cldap, host); >+ ret &= test_netlogon_extra_attrs(tctx, udp_ldap_rootdse, cldap); > > return ret; > } >-- >1.9.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
metze
:
review+
Actions:
View
Attachments on
bug 10524
:
9860
|
9861
|
9881
| 9882