The branch, master has been updated via fe5b0b595c926aea0916541ceeaf610bc018cb63 (commit) via 72c2da9d327288552084efad831ef8c3518de835 (commit) from b4a4d4c9d06c93188d9705f944cde8ed359bd3f3 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit fe5b0b595c926aea0916541ceeaf610bc018cb63 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Feb 10 17:31:57 2009 +1100 added a workaround to the handling of unicodePwd for Win7-beta The Win7-beta domain process has changed. It no longer uses SAMR for setting the password, and instead uses a ldap modify on a SASL encrypted ldap connection. We didn't handle that as the unicodePwd attribute has a dual use, holding the nt style MD4 hases for DRS replication, but holding a UTF-16 plaintext password for a LDAP modify. This patch copes with the ldap unicodePwd modify by recognising the format and creating the correct attributes on the fly. Note that this assumes we will never get a unicodePwd attribute set in NT MD4 format with the first 2 and last 2 bytes set to 0x22 0x00. Andrew Bartlett is looking at a more robust solution, possibly using a flag to say that this modify came via ldap, and not internal ldb calls. commit 72c2da9d327288552084efad831ef8c3518de835 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Feb 10 17:28:05 2009 +1100 fixed two problems with the DsRGetDCNameEx2 call, as used by Win7-beta. The first problem is that we removed the dnsDomain attribute a while back, so we were returning NULL for two fields. We now return the realm. The second problem is that Win7-beta sends the domain in the form the user typed it, so it may be in either the short or long form. We check for the short form and convert if needed. ----------------------------------------------------------------------- Summary of changes: source4/dsdb/samdb/ldb_modules/password_hash.c | 31 +++++++++++++++++++++++- source4/rpc_server/netlogon/dcerpc_netlogon.c | 12 +++++++-- 2 files changed, 39 insertions(+), 4 deletions(-) Changeset truncated at 500 lines: diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2c07fa1..da4c574 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -109,6 +109,7 @@ struct setup_password_fields_io { struct { const struct ldb_val *cleartext_utf8; const struct ldb_val *cleartext_utf16; + struct ldb_val quoted_utf16; struct samr_Password *nt_hash; struct samr_Password *lm_hash; } n; @@ -2102,6 +2103,7 @@ static int password_hash_mod_do_mod(struct ph_context *ac) struct ldb_message *orig_msg; struct ldb_message *searched_msg; struct setup_password_fields_io io; + const struct ldb_val *quoted_utf16; int ret; ldb = ldb_module_get_ctx(ac->module); @@ -2138,7 +2140,34 @@ static int password_hash_mod_do_mod(struct ph_context *ac) io.n.cleartext_utf8 = ldb_msg_find_ldb_val(orig_msg, "userPassword"); io.n.cleartext_utf16 = ldb_msg_find_ldb_val(orig_msg, "clearTextPassword"); - io.n.nt_hash = samdb_result_hash(io.ac, orig_msg, "unicodePwd"); + + /* this rather strange looking piece of code is there to + handle a ldap client setting a password remotely using the + unicodePwd ldap field. The syntax is that the password is + in UTF-16LE, with a " at either end. Unfortunately the + unicodePwd field is also used to store the nt hashes + internally in Samba, and is used in the nt hash format on + the wire in DRS replication, so we have a single name for + two distinct values. The code below leaves us with a small + chance (less than 1 in 2^32) of a mixup, if someone manages + to create a MD4 hash which starts and ends in 0x22 0x00, as + that would then be treated as a UTF16 password rather than + a nthash */ + quoted_utf16 = ldb_msg_find_ldb_val(orig_msg, "unicodePwd"); + if (quoted_utf16 && + quoted_utf16->length >= 4 && + quoted_utf16->data[0] == '"' && + quoted_utf16->data[1] == 0 && + quoted_utf16->data[quoted_utf16->length-2] == '"' && + quoted_utf16->data[quoted_utf16->length-1] == 0) { + io.n.quoted_utf16.data = talloc_memdup(orig_msg, quoted_utf16->data+2, quoted_utf16->length-4); + io.n.quoted_utf16.length = quoted_utf16->length-4; + io.n.cleartext_utf16 = &io.n.quoted_utf16; + io.n.nt_hash = NULL; + } else { + io.n.nt_hash = samdb_result_hash(io.ac, orig_msg, "unicodePwd"); + } + io.n.lm_hash = samdb_result_hash(io.ac, orig_msg, "dBCSPwd"); io.o.kvno = samdb_result_uint(searched_msg, "msDs-KeyVersionNumber", 0); diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index a9150d1..d5484d0 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1166,7 +1166,7 @@ static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_c static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_DsRGetDCNameEx2 *r) { - const char * const attrs[] = { "dnsDomain", "objectGUID", NULL }; + const char * const attrs[] = { "objectGUID", NULL }; void *sam_ctx; struct ldb_message **res; struct ldb_dn *domain_dn; @@ -1180,6 +1180,12 @@ static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TA return WERR_DS_SERVICE_UNAVAILABLE; } + /* Win7-beta will send the domain name in the form the user typed, so we have to cope + with both the short and long form here */ + if (strcasecmp(r->in.domain_name, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx)) == 0) { + r->in.domain_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx); + } + domain_dn = samdb_dns_domain_to_dn(sam_ctx, mem_ctx, r->in.domain_name); if (domain_dn == NULL) { @@ -1205,8 +1211,8 @@ static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TA W_ERROR_HAVE_NO_MEMORY(info->dc_address); info->dc_address_type = DS_ADDRESS_TYPE_INET; info->domain_guid = samdb_result_guid(res[0], "objectGUID"); - info->domain_name = samdb_result_string(res[0], "dnsDomain", NULL); - info->forest_name = samdb_result_string(res[0], "dnsDomain", NULL); + info->domain_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx); + info->forest_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx); info->dc_flags = DS_DNS_FOREST | DS_DNS_DOMAIN | DS_DNS_CONTROLLER | -- Samba Shared Repository