From 064e7447bebd715c8351d9a0ee31f648990f2336 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 15 May 2004 07:51:38 +0000 Subject: r743: Start on a NETLOGON server in Samba4. Currently this only authentiates the machine, not real users. As a consequence of running the Samba4 NETLOGON test against Samba4, I found a number of issues in the SAMR server, which I have addressed. There are more templates in the provison.ldif for this reason. I also added some debug to our credentials code, and fixed some bugs in the auth_sam module. The static buffer in generate_random_string() bit me badly, so I removed it in favor of a talloc based system. Andrew Bartlett (This used to be commit 94624e519b66def97758b8a48a01ffe9029176f0) --- source4/rpc_server/samr/samdb.c | 202 +++++++++++++++++++++++----------------- 1 file changed, 119 insertions(+), 83 deletions(-) (limited to 'source4/rpc_server/samr/samdb.c') diff --git a/source4/rpc_server/samr/samdb.c b/source4/rpc_server/samr/samdb.c index 2fa17af8ea..2489dae684 100644 --- a/source4/rpc_server/samr/samdb.c +++ b/source4/rpc_server/samr/samdb.c @@ -416,6 +416,68 @@ uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg, return count; } +NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg, + uint8 **lm_pwd, uint8 **nt_pwd) +{ + + const char *unicodePwd = samdb_result_string(msg, "unicodePwd", NULL); + + struct samr_Hash *lmPwdHash, *ntPwdHash; + if (unicodePwd) { + if (nt_pwd) { + ntPwdHash = talloc_p(mem_ctx, struct samr_Hash); + if (!ntPwdHash) { + return NT_STATUS_NO_MEMORY; + } + + E_md4hash(unicodePwd, ntPwdHash->hash); + *nt_pwd = ntPwdHash->hash; + } + + if (lm_pwd) { + BOOL lm_hash_ok; + + lmPwdHash = talloc_p(mem_ctx, struct samr_Hash); + if (!lmPwdHash) { + return NT_STATUS_NO_MEMORY; + } + + /* compute the new nt and lm hashes */ + lm_hash_ok = E_deshash(unicodePwd, lmPwdHash->hash); + + if (lm_hash_ok) { + *lm_pwd = lmPwdHash->hash; + } else { + *lm_pwd = NULL; + } + } + } else { + if (nt_pwd) { + int num_nt; + num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHash", &ntPwdHash); + if (num_nt == 0) { + nt_pwd = NULL; + } else if (num_nt > 1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } else { + *nt_pwd = ntPwdHash[0].hash; + } + } + if (lm_pwd) { + int num_lm; + num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHash", &lmPwdHash); + if (num_lm == 0) { + *lm_pwd = NULL; + } else if (num_lm > 1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } else { + *lm_pwd = lmPwdHash[0].hash; + } + } + + } + return NT_STATUS_OK; +} /* pull a samr_LogonHours structutre from a result set. @@ -438,36 +500,13 @@ struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_ return hours; } -/* mapping between ADS userAccountControl and SAMR acct_flags */ -static const struct { - uint32 uf, acb; -} acct_flags_map[] = { - { UF_ACCOUNTDISABLE, ACB_DISABLED }, - { UF_HOMEDIR_REQUIRED, ACB_HOMDIRREQ }, - { UF_PASSWD_NOTREQD, ACB_PWNOTREQ }, - { UF_TEMP_DUPLICATE_ACCOUNT, ACB_TEMPDUP }, - { UF_NORMAL_ACCOUNT, ACB_NORMAL }, - { UF_MNS_LOGON_ACCOUNT, ACB_MNS }, - { UF_INTERDOMAIN_TRUST_ACCOUNT, ACB_DOMTRUST }, - { UF_WORKSTATION_TRUST_ACCOUNT, ACB_WSTRUST }, - { UF_SERVER_TRUST_ACCOUNT, ACB_SVRTRUST }, - { UF_DONT_EXPIRE_PASSWD, ACB_PWNOEXP }, - { UF_LOCKOUT, ACB_AUTOLOCK } -}; - /* pull a set of account_flags from a result set. */ -uint32 samdb_result_acct_flags(struct ldb_message *msg, const char *attr) +uint16 samdb_result_acct_flags(struct ldb_message *msg, const char *attr) { uint_t userAccountControl = ldb_msg_find_uint(msg, attr, 0); - uint32 i, ret = 0; - for (i=0;i str_charnum(new_pass)) { - return NT_STATUS_PASSWORD_RESTRICTION; - } - - /* yes, this is a minus. The ages are in negative 100nsec units! */ - if (pwdLastSet - minPwdAge > now_double) { - return NT_STATUS_PASSWORD_RESTRICTION; - } - - /* possibly check password complexity */ - if (pwdProperties & DOMAIN_PASSWORD_COMPLEX && - !samdb_password_complexity_ok(new_pass)) { - return NT_STATUS_PASSWORD_RESTRICTION; - } - /* compute the new nt and lm hashes */ lm_hash_ok = E_deshash(new_pass, lmNewHash.hash); E_md4hash(new_pass, ntNewHash.hash); - /* check the immediately past password */ - if (pwdHistoryLength > 0) { - if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) { + if (user_change) { + /* are all password changes disallowed? */ + if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) { return NT_STATUS_PASSWORD_RESTRICTION; } - if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) { + + /* can this user change password? */ + if (userAccountControl & UF_PASSWD_CANT_CHANGE) { return NT_STATUS_PASSWORD_RESTRICTION; } - } - - /* check the password history */ - lmPwdHistory_len = MIN(lmPwdHistory_len, pwdHistoryLength); - ntPwdHistory_len = MIN(ntPwdHistory_len, pwdHistoryLength); - - if (pwdHistoryLength > 0) { - if (unicodePwd && strcmp(unicodePwd, new_pass) == 0) { + + /* yes, this is a minus. The ages are in negative 100nsec units! */ + if (pwdLastSet - minPwdAge > now_double) { return NT_STATUS_PASSWORD_RESTRICTION; } - if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) { - return NT_STATUS_PASSWORD_RESTRICTION; + + /* check the immediately past password */ + if (pwdHistoryLength > 0) { + if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) { + return NT_STATUS_PASSWORD_RESTRICTION; + } + if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) { + return NT_STATUS_PASSWORD_RESTRICTION; + } } - if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) { - return NT_STATUS_PASSWORD_RESTRICTION; + + /* check the password history */ + lmPwdHistory_len = MIN(lmPwdHistory_len, pwdHistoryLength); + ntPwdHistory_len = MIN(ntPwdHistory_len, pwdHistoryLength); + + if (pwdHistoryLength > 0) { + if (unicodePwd && strcmp(unicodePwd, new_pass) == 0) { + return NT_STATUS_PASSWORD_RESTRICTION; + } + if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) { + return NT_STATUS_PASSWORD_RESTRICTION; + } + if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) { + return NT_STATUS_PASSWORD_RESTRICTION; + } + } + + for (i=0;lm_hash_ok && i str_charnum(new_pass)) { + return NT_STATUS_PASSWORD_RESTRICTION; } - for (i=0;i