[SCM] Samba Shared Repository - branch v3-5-test updated

Karolin Seeger kseeger at samba.org
Mon Jan 25 04:47:42 MST 2010


The branch, v3-5-test has been updated
       via  5eb9b66... s3:auth: fix account unlock regression introduced with fix for bug #4347
       via  fcadc52... s3:auth: don't update the bad pw count if pw is among last 2 history entries
       via  0d6ad51... s3:auth:check_sam_security: introduce a bool var to control pad_pw_count incrementation
       via  d909861... s3:passdb: store the plain nt passwords hashes in history, not salted md5
       via  f260d6a... s3:smbd:password_in_history: treat entry with 0 salt as 0 + plain nt hash
       via  640dfa8... s3:auth:check_sam_security: improve calling and logging of pdb_update_sam_account
       via  093607e... s3:auth:check_sam_security: fix a leading tab/ws mixup
       via  10a847f... s3:auth:check_sam_security: create (and use) a common exit point
       via  1bb4a2c... s3:auth:check_sam_security: null out sampass after it has been stolen.
       via  2925209... s3:auth:sam_password_ok: take username, acct_ctrl and nt/lm hashes, not sampass
       via  c9e05e1... s3:auth: use data_blob_null instead of data_blob(NULL, 0) in sam_password_ok()
       via  c3bd0b5... s3:auth:sam_password_ok: fix allocation of a data blob.
       via  761a8b8... s3:auth:sam_password_ok: enhance readability (imho) by adding some pointers
       via  232602e... s3:check_sam_security: untangle assignment from statement
       via  a92102c... s3: Factor password_in_history() out of check_passwd_history()
       via  7e430f3... Simplify E_md5hash a bit
       via  2042f49... s3: Simplify pdb_set_plaintext_passwd: pwhistory==NULL can not happen anymore
       via  bfa814b... s3: Simplify pdb_set_plaintext_passwd: pwHistLen==0 was checked above
       via  58b2f41... s3: Add a paranoia check to pdb_set_plaintext_passwd()
       via  76a9af7... s3: Simplify pdb_set_plaintext_passwd() by removing a redundant condition
       via  8a4463c... s3: Simplify pdb_set_plaintext_passwd: memcpy deals fine with 0 bytes
       via  501dd6f... s3: Simplify pdb_set_plaintext_passwd by using talloc_zero_array
       via  a5a4776... s3: Make use of talloc_array in pdb_set_plaintext_passwd()
       via  7097be6... s3: Simplify pdb_set_plaintext_passwd() a bit
       via  0630fdc... s3: Simplify pdb_set_plaintext_passwd() slightly
       via  53e9ffb... s3: Fix a typo
       via  7758648... s3: Avoid a memset(, 0, ) call
      from  b3f2d34... WHATSNEW: Update changes since 3.5.0rc1.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test


- Log -----------------------------------------------------------------
commit 5eb9b66de0fd0adc59339a944f02f5fe25868568
Author: Michael Adam <obnox at samba.org>
Date:   Thu Jan 14 14:24:35 2010 +0100

    s3:auth: fix account unlock regression introduced with fix for bug #4347
    
    By an oversight, the patchset for #4347 made the unlocking of a locked
    account after the lockout duration ineffective.
    Thanks to Björn for finding this!
    
    Michael

commit fcadc524779a50ee379fb4feb02448944dc174dc
Author: Michael Adam <obnox at samba.org>
Date:   Wed Jan 6 17:29:04 2010 +0100

    s3:auth: don't update the bad pw count if pw is among last 2 history entries
    
    This conforms to the behaviour of Windows 2003:
    http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/security/bpactlck.mspx
    
    This is supposed to fixes Bug #4347 .
    
    Michael

commit 0d6ad513e27e83b6a460954f3120395f13f65088
Author: Michael Adam <obnox at samba.org>
Date:   Wed Jan 6 16:35:44 2010 +0100

    s3:auth:check_sam_security: introduce a bool var to control pad_pw_count incrementation
    
    This is a preparatory patch for the last part in fixing bug #4347 .
    
    Michael

commit d909861c64cf874b1625039b0e1eace507a29b28
Author: Michael Adam <obnox at samba.org>
Date:   Tue Jan 5 18:28:48 2010 +0100

    s3:passdb: store the plain nt passwords hashes in history, not salted md5
    
    This is in order to be able to do challenge response with the history,
    so that this can be checked when an invalid password was entered:
    If the given password is wrong but in the history, then the bad password
    count should not be updated...
    
    The "lucky" bit here is that the md5 has and the nt hash (md4) both are
    16 bytes long.
    
    This is part of the fix for bug #4347 .
    
    Michael

commit f260d6a48dce32208424aa9bfbf2b1e293e48045
Author: Michael Adam <obnox at samba.org>
Date:   Tue Jan 5 16:58:30 2010 +0100

    s3:smbd:password_in_history: treat entry with 0 salt as 0 + plain nt hash
    
    This is to introduce a new format of the password history, maintaining backwards
    compatibility: The old format was 16 byte hash + 16 byte md5(salt + nt hash).
    The new format is 16 zero bytes and 16 bytes nt hash.
    
    This will allow us to respect the last X entries of the nt password history
    when deciding whether to increment the bad password count.
    
    This is part of the fix for bug #4347 .
    
    Michael

commit 640dfa851a296a403e218096444b203da13ebf10
Author: Michael Adam <obnox at samba.org>
Date:   Wed Jan 6 13:53:10 2010 +0100

    s3:auth:check_sam_security: improve calling and logging of pdb_update_sam_account
    
    Log what went wrongl, and also call pdb_update_sam_account inside
    become_root/unbecome_root: do the logging outside.
    
    Michael

commit 093607e082657ebbf2b49dd5d615c5e6f14c8dcb
Author: Michael Adam <obnox at samba.org>
Date:   Wed Jan 6 13:40:58 2010 +0100

    s3:auth:check_sam_security: fix a leading tab/ws mixup
    
    Michael

commit 10a847fe9d03d1fe62aa96fee251e10bea1da463
Author: Michael Adam <obnox at samba.org>
Date:   Wed Jan 6 12:36:56 2010 +0100

    s3:auth:check_sam_security: create (and use) a common exit point
    
    for use after sam_password_ok() has been called.
    
    Michael

commit 1bb4a2ca3a1e11b395b3b819e468ecac67e16d64
Author: Michael Adam <obnox at samba.org>
Date:   Wed Jan 6 12:32:51 2010 +0100

    s3:auth:check_sam_security: null out sampass after it has been stolen.
    
    So that a later talloc_free would not harm. I could have used
    talloc_move instead of talloc steal in make_server_info_sam(),
    but this would have required a change of the signature.
    
    Michael

commit 2925209acc8bcda487fa8f05365ea8fedb232218
Author: Michael Adam <obnox at samba.org>
Date:   Mon Jan 4 18:15:24 2010 +0100

    s3:auth:sam_password_ok: take username, acct_ctrl and nt/lm hashes, not sampass
    
    This is in preparation to extending check_sam_security to also check
    against the password history before updating the bad password count.
    This way, sam_password_ok can more easily be reused for that purpose.
    
    Michael

commit c9e05e11b152401d63ae9b8b40c717d0bd3d0646
Author: Michael Adam <obnox at samba.org>
Date:   Mon Jan 4 15:37:24 2010 +0100

    s3:auth: use data_blob_null instead of data_blob(NULL, 0) in sam_password_ok()
    
    This way it is more explicit that there is no allocated data here
    that may leak.
    
    Michael

commit c3bd0b5951f09f102abaa19fb2e1f55711b975d2
Author: Michael Adam <obnox at samba.org>
Date:   Wed Dec 30 15:37:23 2009 +0100

    s3:auth:sam_password_ok: fix allocation of a data blob.
    
    data_blob(mem_ctx, 16) does not use mem_ctx as a talloc ctx but
    copies 16 bytes from mem_ctx into the newly allocated data blob.
    This can not have been intentional. A blank uint8_t array of
    length 16 is allocated by passing NULL instead of mem_ctx.
    And using data_blob_talloc(mem_ctx, NULL, 16) adds the allocated
    blank 16 byte array to mem_ctx - so this is what must have been
    intended.
    
    Michael

commit 761a8b8fa5b5d05d5802fecf07229de40d33c558
Author: Michael Adam <obnox at samba.org>
Date:   Wed Dec 30 15:35:50 2009 +0100

    s3:auth:sam_password_ok: enhance readability (imho) by adding some pointers
    
    and removing bool variables and several checks.
    
    Michael

commit 232602ee2914851b0af851aa5dada3bf1c99dcff
Author: Michael Adam <obnox at samba.org>
Date:   Wed Dec 30 12:46:22 2009 +0100

    s3:check_sam_security: untangle assignment from statement
    
    Michael

commit a92102cf3044ad3be49d6f746ed3f95c49d30412
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 20:54:33 2009 +0100

    s3: Factor password_in_history() out of check_passwd_history()

commit 7e430f3093c5bc06d8ca1186f982fe51af8c5637
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 19:29:36 2009 +0100

    Simplify E_md5hash a bit

commit 2042f4937db80939ca3d70816d864b4d762d46fb
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 19:18:09 2009 +0100

    s3: Simplify pdb_set_plaintext_passwd: pwhistory==NULL can not happen anymore

commit bfa814be469e5a7c22e45ff8261de749e51414b2
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 19:16:58 2009 +0100

    s3: Simplify pdb_set_plaintext_passwd: pwHistLen==0 was checked above

commit 58b2f41c14e590724e2cb45f23ff7e75d5d2e7ab
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 19:12:50 2009 +0100

    s3: Add a paranoia check to pdb_set_plaintext_passwd()

commit 76a9af7cac4a6d6ba00d81a946db094ecfd43817
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 18:50:38 2009 +0100

    s3: Simplify pdb_set_plaintext_passwd() by removing a redundant condition
    
    if (current_history_len != pwHistLen) {
         if (current_history_len < pwHistLen) {
         }
    }
    
    The second "if" is a bit pointless here

commit 8a4463c61292872e9a294a6b026ec6d65d2219b8
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 18:44:38 2009 +0100

    s3: Simplify pdb_set_plaintext_passwd: memcpy deals fine with 0 bytes

commit 501dd6fe17e72d8e487a622c0e66cb5938e66731
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 18:43:03 2009 +0100

    s3: Simplify pdb_set_plaintext_passwd by using talloc_zero_array

commit a5a477648f301b9c435609b0c6f4d76d4229b9ae
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 18:39:19 2009 +0100

    s3: Make use of talloc_array in pdb_set_plaintext_passwd()

commit 7097be60809252c6faf0388d0019384f01a7ff42
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 18:24:04 2009 +0100

    s3: Simplify pdb_set_plaintext_passwd() a bit
    
    Remove an indentation by the early return in
    
    +       if (pwHistLen == 0) {
    +               /* Set the history length to zero. */
    +               pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED);
    +               return true;
    +       }

commit 0630fdc5ec8440c8338c7302dc5b52849e3f50be
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 18:13:28 2009 +0100

    s3: Simplify pdb_set_plaintext_passwd() slightly
    
    No functional change, this just removes an indentation level by the early
    "return True;" in
    
    +       if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) == 0) {
    +               /*
    +                * No password history for non-user accounts
    +                */
    +               return true;
    +       }
    
    Volker

commit 53e9ffb3a66acfa9af2bf4c616b2b83daf723f49
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 17:51:39 2009 +0100

    s3: Fix a typo

commit 7758648556aba5242f913d6cc0f46a2d9f1cfaa9
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 14 17:43:56 2009 +0100

    s3: Avoid a memset(, 0, ) call

-----------------------------------------------------------------------

Summary of changes:
 libcli/auth/smbencrypt.c     |    8 +--
 source3/auth/auth_sam.c      |  197 +++++++++++++++++++++++++++++++-----------
 source3/include/proto.h      |    3 +
 source3/passdb/pdb_get_set.c |  133 ++++++++++++++++-------------
 source3/smbd/chgpasswd.c     |   87 +++++++++++++------
 5 files changed, 287 insertions(+), 141 deletions(-)


Changeset truncated at 500 lines:

diff --git a/libcli/auth/smbencrypt.c b/libcli/auth/smbencrypt.c
index a3182cd..f7c60e7 100644
--- a/libcli/auth/smbencrypt.c
+++ b/libcli/auth/smbencrypt.c
@@ -100,13 +100,9 @@ bool E_md4hash(const char *passwd, uint8_t p16[16])
 void E_md5hash(const uint8_t salt[16], const uint8_t nthash[16], uint8_t hash_out[16])
 {
 	struct MD5Context tctx;
-	uint8_t array[32];
-
-	memset(hash_out, '\0', 16);
-	memcpy(array, salt, 16);
-	memcpy(&array[16], nthash, 16);
 	MD5Init(&tctx);
-	MD5Update(&tctx, array, 32);
+	MD5Update(&tctx, salt, 16);
+	MD5Update(&tctx, nthash, 16);
 	MD5Final(hash_out, &tctx);
 }
 
diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
index f0500b3..bd99b3a 100644
--- a/source3/auth/auth_sam.c
+++ b/source3/auth/auth_sam.c
@@ -33,21 +33,23 @@
 
 static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
 				TALLOC_CTX *mem_ctx,
-				struct samu *sampass, 
+				const char *username,
+				uint32_t acct_ctrl,
+				const uint8_t *lm_pw,
+				const uint8_t *nt_pw,
 				const auth_usersupplied_info *user_info, 
 				DATA_BLOB *user_sess_key, 
 				DATA_BLOB *lm_sess_key)
 {
-	uint32 acct_ctrl;
-	const uint8 *lm_pw, *nt_pw;
-	struct samr_Password lm_hash, nt_hash, client_lm_hash, client_nt_hash;
-	const char *username = pdb_get_username(sampass);
-	bool got_lm = false, got_nt = false;
+	struct samr_Password _lm_hash, _nt_hash, _client_lm_hash, _client_nt_hash;
+	struct samr_Password *lm_hash = NULL;
+	struct samr_Password *nt_hash = NULL;
+	struct samr_Password *client_lm_hash = NULL;
+	struct samr_Password *client_nt_hash = NULL;
 
-	*user_sess_key = data_blob(NULL, 0);
-	*lm_sess_key = data_blob(NULL, 0);
+	*user_sess_key = data_blob_null;
+	*lm_sess_key = data_blob_null;
 
-	acct_ctrl = pdb_get_acct_ctrl(sampass);
 	if (acct_ctrl & ACB_PWNOTREQ) {
 		if (lp_null_passwords()) {
 			DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", username));
@@ -58,34 +60,35 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
 		}		
 	}
 
-	lm_pw = pdb_get_lanman_passwd(sampass);
-	nt_pw = pdb_get_nt_passwd(sampass);
 	if (lm_pw) {
-		memcpy(lm_hash.hash, lm_pw, sizeof(lm_hash.hash));
+		memcpy(_lm_hash.hash, lm_pw, sizeof(_lm_hash.hash));
+		lm_hash = &_lm_hash;
 	}
 	if (nt_pw) {
-		memcpy(nt_hash.hash, nt_pw, sizeof(nt_hash.hash));
+		memcpy(_nt_hash.hash, nt_pw, sizeof(_nt_hash.hash));
+		nt_hash = &_nt_hash;
 	}
-	if (user_info->lm_interactive_pwd.data && sizeof(client_lm_hash.hash) == user_info->lm_interactive_pwd.length) {
-		memcpy(client_lm_hash.hash, user_info->lm_interactive_pwd.data, sizeof(lm_hash.hash));
-		got_lm = true;
+	if (user_info->lm_interactive_pwd.data && sizeof(_client_lm_hash.hash) == user_info->lm_interactive_pwd.length) {
+		memcpy(_client_lm_hash.hash, user_info->lm_interactive_pwd.data, sizeof(_lm_hash.hash));
+		client_lm_hash = &_client_lm_hash;
 	}
-	if (user_info->nt_interactive_pwd.data && sizeof(client_nt_hash.hash) == user_info->nt_interactive_pwd.length) {
-		memcpy(client_nt_hash.hash, user_info->nt_interactive_pwd.data, sizeof(nt_hash.hash));
-		got_nt = true;
+	if (user_info->nt_interactive_pwd.data && sizeof(_client_nt_hash.hash) == user_info->nt_interactive_pwd.length) {
+		memcpy(_client_nt_hash.hash, user_info->nt_interactive_pwd.data, sizeof(_nt_hash.hash));
+		client_nt_hash = &_client_nt_hash;
 	}
-	if (got_lm || got_nt) {
-		*user_sess_key = data_blob(mem_ctx, 16);
+
+	if (client_lm_hash || client_nt_hash) {
+		*user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
 		if (!user_sess_key->data) {
 			return NT_STATUS_NO_MEMORY;
 		}
 		SMBsesskeygen_ntv1(nt_pw, user_sess_key->data);
 		return hash_password_check(mem_ctx, lp_lanman_auth(),
-					   got_lm ? &client_lm_hash : NULL, 
-					   got_nt ? &client_nt_hash : NULL,
+					   client_lm_hash,
+					   client_nt_hash,
 					   username, 
-					   lm_pw ? &lm_hash: NULL, 
-					   nt_pw ? &nt_hash : NULL);
+					   lm_hash,
+					   nt_hash);
 	} else {
 		return ntlm_password_check(mem_ctx, lp_lanman_auth(),
 					   lp_ntlm_auth(),
@@ -95,8 +98,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
 					   username, 
 					   user_info->smb_name,
 					   user_info->client_domain,
-					   lm_pw ? &lm_hash: NULL, 
-					   nt_pw ? &nt_hash : NULL,
+					   lm_hash,
+					   nt_hash,
 					   user_sess_key, lm_sess_key);
 	}
 }
@@ -278,6 +281,75 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx,
 	return NT_STATUS_OK;
 }
 
+/**
+ * Check whether the given password is one of the last two
+ * password history entries. If so, the bad pwcount should
+ * not be incremented even thought the actual password check
+ * failed.
+ */
+static bool need_to_increment_bad_pw_count(
+	const struct auth_context *auth_context,
+	struct samu* sampass,
+	const auth_usersupplied_info *user_info)
+{
+	uint8_t i;
+	const uint8_t *pwhistory;
+	uint32_t pwhistory_len;
+	uint32_t policy_pwhistory_len;
+	uint32_t acct_ctrl;
+	const char *username;
+	TALLOC_CTX *mem_ctx = talloc_stackframe();
+	bool result = true;
+
+	pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY,
+			       &policy_pwhistory_len);
+	if (policy_pwhistory_len == 0) {
+		goto done;
+	}
+
+	pwhistory = pdb_get_pw_history(sampass, &pwhistory_len);
+	if (!pwhistory || pwhistory_len == 0) {
+		goto done;
+	}
+
+	acct_ctrl = pdb_get_acct_ctrl(sampass);
+	username = pdb_get_username(sampass);
+
+	for (i=1; i < MIN(MIN(3, policy_pwhistory_len), pwhistory_len); i++) {
+		static const uint8_t zero16[SALTED_MD5_HASH_LEN];
+		const uint8_t *salt;
+		const uint8_t *nt_pw;
+		NTSTATUS status;
+		DATA_BLOB user_sess_key = data_blob_null;
+		DATA_BLOB lm_sess_key = data_blob_null;
+
+		salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN];
+		nt_pw = salt + PW_HISTORY_SALT_LEN;
+
+		if (memcmp(zero16, nt_pw, NT_HASH_LEN) == 0) {
+			/* skip zero password hash */
+			continue;
+		}
+
+		if (memcmp(zero16, salt, PW_HISTORY_SALT_LEN) != 0) {
+			/* skip nonzero salt (old format entry) */
+			continue;
+		}
+
+		status = sam_password_ok(auth_context, mem_ctx,
+					 username, acct_ctrl, NULL, nt_pw,
+					 user_info, &user_sess_key, &lm_sess_key);
+		if (NT_STATUS_IS_OK(status)) {
+			result = false;
+			break;
+		}
+	}
+
+done:
+	TALLOC_FREE(mem_ctx);
+	return result;
+}
+
 /****************************************************************************
 check if a username/password is OK assuming the password is a 24 byte
 SMB hash supplied in the user_info structure
@@ -297,6 +369,9 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 	DATA_BLOB user_sess_key = data_blob_null;
 	DATA_BLOB lm_sess_key = data_blob_null;
 	bool updated_autolock = False, updated_badpw = False;
+	const char *username;
+	const uint8_t *nt_pw;
+	const uint8_t *lm_pw;
 
 	if (!user_info || !auth_context) {
 		return NT_STATUS_UNSUCCESSFUL;
@@ -305,7 +380,8 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 	/* the returned struct gets kept on the server_info, by means
 	   of a steal further down */
 
-	if ( !(sampass = samu_new( mem_ctx )) ) {
+	sampass = samu_new(mem_ctx);
+	if (sampass == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
 
@@ -322,16 +398,21 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 		return NT_STATUS_NO_SUCH_USER;
 	}
 
+	username = pdb_get_username(sampass);
+	nt_pw = pdb_get_nt_passwd(sampass);
+	lm_pw = pdb_get_lanman_passwd(sampass);
+
 	/* see if autolock flag needs to be updated */
 	if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL)
 		pdb_update_autolock_flag(sampass, &updated_autolock);
 	/* Quit if the account was locked out. */
 	if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) {
-		DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", pdb_get_username(sampass)));
+		DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", username));
 		return NT_STATUS_ACCOUNT_LOCKED_OUT;
 	}
 
-	nt_status = sam_password_ok(auth_context, mem_ctx, sampass, 
+	nt_status = sam_password_ok(auth_context, mem_ctx,
+				    username, pdb_get_acct_ctrl(sampass), lm_pw, nt_pw,
 				    user_info, &user_sess_key, &lm_sess_key);
 
 	/* Notify passdb backend of login success/failure. If not 
@@ -340,10 +421,19 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 	update_login_attempts_status = pdb_update_login_attempts(sampass, NT_STATUS_IS_OK(nt_status));
 
 	if (!NT_STATUS_IS_OK(nt_status)) {
+		bool increment_bad_pw_count = false;
+
 		if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) && 
-		    pdb_get_acct_ctrl(sampass) &ACB_NORMAL &&
+		    pdb_get_acct_ctrl(sampass) & ACB_NORMAL &&
 		    NT_STATUS_IS_OK(update_login_attempts_status)) 
-		{  
+		{
+			increment_bad_pw_count =
+				need_to_increment_bad_pw_count(auth_context,
+							       sampass,
+							       user_info);
+		}
+
+		if (increment_bad_pw_count) {
 			pdb_increment_bad_password_count(sampass);
 			updated_badpw = True;
 		} else {
@@ -351,18 +441,21 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 						      &updated_badpw);
 		}
 		if (updated_autolock || updated_badpw){
+			NTSTATUS status;
+
 			become_root();
-			if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass)))
-				DEBUG(1, ("Failed to modify entry.\n"));
+			status = pdb_update_sam_account(sampass);
 			unbecome_root();
+
+			if (!NT_STATUS_IS_OK(status)) {
+				DEBUG(1, ("Failed to modify entry: %s\n",
+					  nt_errstr(status)));
+			}
 		}
-		data_blob_free(&user_sess_key);
-		data_blob_free(&lm_sess_key);
-		TALLOC_FREE(sampass);
-		return nt_status;
+		goto done;
 	}
 
-	if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) && 
+	if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) &&
 	    (pdb_get_bad_password_count(sampass) > 0)){
 		pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
 		pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
@@ -370,30 +463,32 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 	}
 
 	if (updated_autolock || updated_badpw){
+		NTSTATUS status;
+
 		become_root();
-		if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass)))
-			DEBUG(1, ("Failed to modify entry.\n"));
+		status = pdb_update_sam_account(sampass);
 		unbecome_root();
- 	}
+
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(1, ("Failed to modify entry: %s\n",
+				  nt_errstr(status)));
+		}
+	}
 
 	nt_status = sam_account_ok(mem_ctx, sampass, user_info);
 
 	if (!NT_STATUS_IS_OK(nt_status)) {
-		TALLOC_FREE(sampass);
-		data_blob_free(&user_sess_key);
-		data_blob_free(&lm_sess_key);
-		return nt_status;
+		goto done;
 	}
 
 	become_root();
 	nt_status = make_server_info_sam(server_info, sampass);
 	unbecome_root();
+	sampass = NULL;
 
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
-		data_blob_free(&user_sess_key);
-		data_blob_free(&lm_sess_key);
-		return nt_status;
+		goto done;
 	}
 
 	(*server_info)->user_session_key =
@@ -408,6 +503,10 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 
 	(*server_info)->nss_token |= user_info->was_mapped;
 
+done:
+	TALLOC_FREE(sampass);
+	data_blob_free(&user_sess_key);
+	data_blob_free(&lm_sess_key);
 	return nt_status;
 }
 
diff --git a/source3/include/proto.h b/source3/include/proto.h
index b3512d9..b363358 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6099,6 +6099,9 @@ NTSTATUS pass_oem_change(char *user,
 			 uchar password_encrypted_with_nt_hash[516],
 			 const uchar old_nt_hash_encrypted[16],
 			 uint32 *reject_reason);
+bool password_in_history(uint8_t nt_pw[NT_HASH_LEN],
+			 uint32_t pw_history_len,
+			 const uint8_t *pw_history);
 NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, bool as_root, uint32 *samr_reject_reason);
 
 /* The following definitions come from smbd/close.c  */
diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c
index 30775e4..74ed018 100644
--- a/source3/passdb/pdb_get_set.c
+++ b/source3/passdb/pdb_get_set.c
@@ -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, &current_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, &current_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);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list