$OpenBSD: patch-source3_rpc_server_samr_srv_samr_nt_c,v 1.1 2014/04/10 00:50:58 brad Exp $

Password lockout not enforced for SAMR password changes.
CVE-2013-4496

--- source3/rpc_server/samr/srv_samr_nt.c.orig	Wed Apr  9 17:39:42 2014
+++ source3/rpc_server/samr/srv_samr_nt.c	Wed Apr  9 17:39:30 2014
@@ -1706,114 +1706,19 @@ NTSTATUS _samr_LookupNames(struct pipes_struct *p,
 }
 
 /****************************************************************
- _samr_ChangePasswordUser
+ _samr_ChangePasswordUser.
+
+ So old it is just not worth implementing
+ because it does not supply a plaintext and so we can't do password
+ complexity checking and cannot update other services that use a
+ plaintext password via passwd chat/pam password change/ldap password
+ sync.
 ****************************************************************/
 
 NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
 				  struct samr_ChangePasswordUser *r)
 {
-	NTSTATUS status;
-	bool ret = false;
-	struct samr_user_info *uinfo;
-	struct samu *pwd;
-	struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
-	struct samr_Password lm_pwd, nt_pwd;
-
-	uinfo = policy_handle_find(p, r->in.user_handle,
-				   SAMR_USER_ACCESS_SET_PASSWORD, NULL,
-				   struct samr_user_info, &status);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
-
-	DEBUG(5,("_samr_ChangePasswordUser: sid:%s\n",
-		  sid_string_dbg(&uinfo->sid)));
-
-	if (!(pwd = samu_new(NULL))) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	become_root();
-	ret = pdb_getsampwsid(pwd, &uinfo->sid);
-	unbecome_root();
-
-	if (!ret) {
-		TALLOC_FREE(pwd);
-		return NT_STATUS_WRONG_PASSWORD;
-	}
-
-	{
-		const uint8_t *lm_pass, *nt_pass;
-
-		lm_pass = pdb_get_lanman_passwd(pwd);
-		nt_pass = pdb_get_nt_passwd(pwd);
-
-		if (!lm_pass || !nt_pass) {
-			status = NT_STATUS_WRONG_PASSWORD;
-			goto out;
-		}
-
-		memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash));
-		memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash));
-	}
-
-	/* basic sanity checking on parameters.  Do this before any database ops */
-	if (!r->in.lm_present || !r->in.nt_present ||
-	    !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
-	    !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
-		/* we should really handle a change with lm not
-		   present */
-		status = NT_STATUS_INVALID_PARAMETER_MIX;
-		goto out;
-	}
-
-	/* decrypt and check the new lm hash */
-	D_P16(lm_pwd.hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
-	D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
-	if (memcmp(checkHash.hash, lm_pwd.hash, 16) != 0) {
-		status = NT_STATUS_WRONG_PASSWORD;
-		goto out;
-	}
-
-	/* decrypt and check the new nt hash */
-	D_P16(nt_pwd.hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
-	D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
-	if (memcmp(checkHash.hash, nt_pwd.hash, 16) != 0) {
-		status = NT_STATUS_WRONG_PASSWORD;
-		goto out;
-	}
-
-	/* The NT Cross is not required by Win2k3 R2, but if present
-	   check the nt cross hash */
-	if (r->in.cross1_present && r->in.nt_cross) {
-		D_P16(lm_pwd.hash, r->in.nt_cross->hash, checkHash.hash);
-		if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
-			status = NT_STATUS_WRONG_PASSWORD;
-			goto out;
-		}
-	}
-
-	/* The LM Cross is not required by Win2k3 R2, but if present
-	   check the lm cross hash */
-	if (r->in.cross2_present && r->in.lm_cross) {
-		D_P16(nt_pwd.hash, r->in.lm_cross->hash, checkHash.hash);
-		if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
-			status = NT_STATUS_WRONG_PASSWORD;
-			goto out;
-		}
-	}
-
-	if (!pdb_set_nt_passwd(pwd, new_ntPwdHash.hash, PDB_CHANGED) ||
-	    !pdb_set_lanman_passwd(pwd, new_lmPwdHash.hash, PDB_CHANGED)) {
-		status = NT_STATUS_ACCESS_DENIED;
-		goto out;
-	}
-
-	status = pdb_update_sam_account(pwd);
- out:
-	TALLOC_FREE(pwd);
-
-	return status;
+	return NT_STATUS_NOT_IMPLEMENTED;
 }
 
 /*******************************************************************
