diff options
author | Stefan Metzmacher <metze@samba.org> | 2015-03-25 15:14:44 +0000 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2015-07-08 18:38:21 +0200 |
commit | 1a84cb7d0b2a3a5a860c6f06f73ef574ed55dace (patch) | |
tree | 584c3d6e76043177e350dfb98bb1204055012241 /source4/dsdb | |
parent | 0deb1d9c4ab2e283aaedab68c9b6f50c03edd36a (diff) | |
download | samba-1a84cb7d0b2a3a5a860c6f06f73ef574ed55dace.tar.gz |
s4:dsdb/netlogon: add support for CLDAP requests with AAC=0x00000400(ACB_AUTOLOCK) and user="example.com."
Windows reuses the ACB_AUTOLOCK flag to handle SEC_CHAN_DNS_DOMAIN domains,
but this not documented yet...
This is triggered by the NETLOGON_CONTROL_REDISCOVER with a domain string
of "example.com\somedc.example.com".
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source4/dsdb')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/netlogon.c | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/netlogon.c b/source4/dsdb/samdb/ldb_modules/netlogon.c index a381da833cf..c5f194dc4dc 100644 --- a/source4/dsdb/samdb/ldb_modules/netlogon.c +++ b/source4/dsdb/samdb/ldb_modules/netlogon.c @@ -58,7 +58,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, { const char *dom_attrs[] = {"objectGUID", NULL}; const char *none_attrs[] = {NULL}; - struct ldb_result *dom_res = NULL, *user_res = NULL; + struct ldb_result *dom_res = NULL; int ret; const char **services = lpcfg_server_services(lp_ctx); uint32_t server_type; @@ -74,6 +74,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, struct ldb_dn *domain_dn = NULL; struct interface *ifaces; bool user_known = false, am_rodc = false; + uint32_t uac = 0; NTSTATUS status; /* the domain parameter could have an optional trailing "." */ @@ -191,12 +192,48 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, /* 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]) { \ + 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); + /* + * ACB_AUTOLOCK/UF_LOCKOUT seems to be a special + * hack for SEC_CHAN_DNS_DOMAIN. + * + * It's used together with user = "example.com." + */ + if (acct_control != ACB_AUTOLOCK) { + acct_control &= (ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); + } + uac = ds_acb2uf(acct_control); + } + + if (uac == UF_LOCKOUT) { + struct ldb_message *tdo_msg = NULL; + + /* + * ACB_AUTOLOCK/UF_LOCKOUT seems to be a special + * hack for SEC_CHAN_DNS_DOMAIN. + * + * It's used together with user = "example.com." + */ + status = dsdb_trust_search_tdo_by_type(sam_ctx, + SEC_CHAN_DNS_DOMAIN, + user, none_attrs, + mem_ctx, &tdo_msg); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + user_known = false; + } else if (NT_STATUS_IS_OK(status)) { + TALLOC_FREE(tdo_msg); + user_known = true; + } else { + DEBUG(2,("Unable to find reference to TDO '%s' - %s\n", + user, nt_errstr(status))); + return status; + } + } else if (user[0]) { + struct ldb_result *user_res = NULL; /* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */ ret = ldb_search(sam_ctx, mem_ctx, &user_res, @@ -206,7 +243,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, "(!(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)); + UF_ACCOUNTDISABLE, uac); 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), @@ -217,7 +254,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, } else { user_known = false; } - + TALLOC_FREE(user_res); } else { user_known = true; } |