From fe5b0b595c926aea0916541ceeaf610bc018cb63 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Feb 2009 17:31:57 +1100 Subject: 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. --- source4/dsdb/samdb/ldb_modules/password_hash.c | 31 +++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2c07fa1be6..da4c57463b 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); -- cgit