summaryrefslogtreecommitdiff
path: root/source4/dsdb
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2015-03-25 15:14:44 +0000
committerStefan Metzmacher <metze@samba.org>2015-07-08 18:38:21 +0200
commit1a84cb7d0b2a3a5a860c6f06f73ef574ed55dace (patch)
tree584c3d6e76043177e350dfb98bb1204055012241 /source4/dsdb
parent0deb1d9c4ab2e283aaedab68c9b6f50c03edd36a (diff)
downloadsamba-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.c47
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;
}