diff options
Diffstat (limited to 'source3/passdb/pdb_get_set.c')
-rw-r--r-- | source3/passdb/pdb_get_set.c | 141 |
1 files changed, 78 insertions, 63 deletions
diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 30775e49fe..d7fc02f807 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -239,8 +239,7 @@ const DOM_SID *pdb_get_group_sid(struct samu *sampass) /* Just set it to the 'Domain Users' RID of 512 which will always resolve to a name */ - sid_copy( gsid, get_global_sam_sid() ); - sid_append_rid( gsid, DOMAIN_GROUP_RID_USERS ); + sid_compose(gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_USERS); sampass->group_sid = gsid; @@ -552,8 +551,8 @@ bool pdb_set_group_sid(struct samu *sampass, const DOM_SID *g_sid, enum pdb_valu if ( sid_to_gid( g_sid, &gid ) ) { sid_copy(sampass->group_sid, g_sid); } else { - sid_copy( sampass->group_sid, get_global_sam_sid() ); - sid_append_rid( sampass->group_sid, DOMAIN_GROUP_RID_USERS ); + sid_compose(sampass->group_sid, get_global_sam_sid(), + DOMAIN_GROUP_RID_USERS); } DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n", @@ -876,6 +875,7 @@ bool pdb_set_lanman_passwd(struct samu *sampass, const uint8 pwd[LM_HASH_LEN], e bool pdb_set_pw_history(struct samu *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag) { if (historyLen && pwd){ + data_blob_free(&(sampass->nt_pw_his)); sampass->nt_pw_his = data_blob_talloc(sampass, pwd, historyLen*PW_HISTORY_ENTRY_LEN); if (!sampass->nt_pw_his.length) { @@ -980,6 +980,9 @@ bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext) { uchar new_lanman_p16[LM_HASH_LEN]; uchar new_nt_p16[NT_HASH_LEN]; + uchar *pwhistory; + uint32 pwHistLen; + uint32 current_history_len; if (!plaintext) return False; @@ -1009,68 +1012,80 @@ bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext) if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) return False; - /* Store the password history. */ - if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) { - uchar *pwhistory; - uint32 pwHistLen; - pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); - if (pwHistLen != 0){ - uint32 current_history_len; - /* We need to make sure we don't have a race condition here - the - account policy history length can change between when the pw_history - was first loaded into the struct samu struct and now.... JRA. */ - pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); - - if (current_history_len != pwHistLen) { - /* After closing and reopening struct samu the history - values will sync up. We can't do this here. */ - - /* current_history_len > pwHistLen is not a problem - we - have more history than we need. */ - - if (current_history_len < pwHistLen) { - /* Ensure we have space for the needed history. */ - uchar *new_history = (uchar *)TALLOC(sampass, - pwHistLen*PW_HISTORY_ENTRY_LEN); - if (!new_history) { - return False; - } - - /* And copy it into the new buffer. */ - if (current_history_len) { - memcpy(new_history, pwhistory, - current_history_len*PW_HISTORY_ENTRY_LEN); - } - /* Clearing out any extra space. */ - memset(&new_history[current_history_len*PW_HISTORY_ENTRY_LEN], - '\0', (pwHistLen-current_history_len)*PW_HISTORY_ENTRY_LEN); - /* Finally replace it. */ - pwhistory = new_history; - } - } - if (pwhistory && pwHistLen){ - /* Make room for the new password in the history list. */ - if (pwHistLen > 1) { - memmove(&pwhistory[PW_HISTORY_ENTRY_LEN], - pwhistory, (pwHistLen -1)*PW_HISTORY_ENTRY_LEN ); - } - /* Create the new salt as the first part of the history entry. */ - generate_random_buffer(pwhistory, PW_HISTORY_SALT_LEN); - - /* Generate the md5 hash of the salt+new password as the second - part of the history entry. */ - - E_md5hash(pwhistory, new_nt_p16, &pwhistory[PW_HISTORY_SALT_LEN]); - pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED); - } else { - DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n")); - } - } else { - /* Set the history length to zero. */ - pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED); + if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) == 0) { + /* + * No password history for non-user accounts + */ + return true; + } + + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); + + if (pwHistLen == 0) { + /* Set the history length to zero. */ + pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED); + return true; + } + + /* + * We need to make sure we don't have a race condition here - + * the account policy history length can change between when + * the pw_history was first loaded into the struct samu struct + * and now.... JRA. + */ + pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); + + if ((current_history_len != 0) && (pwhistory == NULL)) { + DEBUG(1, ("pdb_set_plaintext_passwd: pwhistory == NULL!\n")); + return false; + } + + if (current_history_len < pwHistLen) { + /* + * Ensure we have space for the needed history. This + * also takes care of an account which did not have + * any history at all so far, i.e. pwhistory==NULL + */ + uchar *new_history = talloc_zero_array( + sampass, uchar, + pwHistLen*PW_HISTORY_ENTRY_LEN); + + if (!new_history) { + return False; } + + memcpy(new_history, pwhistory, + current_history_len*PW_HISTORY_ENTRY_LEN); + + pwhistory = new_history; } + /* + * Make room for the new password in the history list. + */ + if (pwHistLen > 1) { + memmove(&pwhistory[PW_HISTORY_ENTRY_LEN], pwhistory, + (pwHistLen-1)*PW_HISTORY_ENTRY_LEN ); + } + + /* + * Fill the salt area with 0-s: this indicates that + * a plain nt hash is stored in the has area. + * The old format was to store a 16 byte salt and + * then an md5hash of the nt_hash concatenated with + * the salt. + */ + memset(pwhistory, 0, PW_HISTORY_SALT_LEN); + + /* + * Store the plain nt hash in the second 16 bytes. + * The old format was to store the md5 hash of + * the salt+newpw. + */ + memcpy(&pwhistory[PW_HISTORY_SALT_LEN], new_nt_p16, SALTED_MD5_HASH_LEN); + + pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED); + return True; } |