summaryrefslogtreecommitdiffstats
path: root/source3/rpc_server/samr
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2013-11-07 16:23:12 +1300
committerStefan Metzmacher <metze@samba.org>2014-03-13 10:26:03 +0100
commit9f53b61f0674f7855a42b8e0de66f343f4592589 (patch)
treed5f0cf798bcc5927d3aa1e8077bc19f73c939c34 /source3/rpc_server/samr
parent76e5ea3a2c5f49cfc1026bd7c6b8baddb1e7dc16 (diff)
downloadsamba-9f53b61f0674f7855a42b8e0de66f343f4592589.tar.gz
samba-9f53b61f0674f7855a42b8e0de66f343f4592589.tar.xz
samba-9f53b61f0674f7855a42b8e0de66f343f4592589.zip
CVE-2013-4496:samr: Remove ChangePasswordUser
This old password change mechanism does not provide the plaintext to validate against password complexity, and it is not used by modern clients. It also has quite difficult semantics to handle regarding password lockout. The missing features in both implementations (by design) were: - the password complexity checks (no plaintext) - the minimum password length (no plaintext) Additionally, the source3 version did not check: - the minimum password age - pdb_get_pass_can_change() which checks the security descriptor for the 'user cannot change password' setting. - the password history - the output of the 'passwd program' if 'unix passwd sync = yes'. Finally, the mechanism was almost useless, as it was incorrectly only made available to administrative users with permission to reset the password. It is removed here so that it is not mistakenly reinstated in the future. Andrew Bartlett Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245 Change-Id: If2edd3183c177e5ff37c9511b0d0ad0dd9038c66 Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org> Reviewed-on: https://gerrit.samba.org/37
Diffstat (limited to 'source3/rpc_server/samr')
-rw-r--r--source3/rpc_server/samr/srv_samr_nt.c169
1 files changed, 8 insertions, 161 deletions
diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
index a7700c6bd6..48cfc7e12d 100644
--- a/source3/rpc_server/samr/srv_samr_nt.c
+++ b/source3/rpc_server/samr/srv_samr_nt.c
@@ -1713,172 +1713,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 = NULL;
- struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
- struct samr_Password lm_pwd, nt_pwd;
- bool updated_badpw = false;
- NTSTATUS update_login_attempts_status;
-
- 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)));
-
- /* 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 */
- return NT_STATUS_INVALID_PARAMETER_MIX;
- }
-
- 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;
- }
-
- /* Quit if the account was locked out. */
- if (pdb_get_acct_ctrl(pwd) & ACB_AUTOLOCK) {
- DEBUG(3, ("Account for user %s was locked out.\n",
- pdb_get_username(pwd)));
- status = NT_STATUS_ACCOUNT_LOCKED_OUT;
- goto out;
- }
-
- {
- 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 update_login;
- }
-
- memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash));
- memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash));
- }
-
- /* 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 update_login;
- }
-
- /* 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 update_login;
- }
-
- /* 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 update_login;
- }
- }
-
- /* 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 update_login;
- }
- }
-
- 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);
-
-update_login:
-
- /*
- * Notify passdb backend of login success/failure. If not
- * NT_STATUS_OK the backend doesn't like the login
- */
- update_login_attempts_status = pdb_update_login_attempts(pwd,
- NT_STATUS_IS_OK(status));
-
- if (!NT_STATUS_IS_OK(status)) {
- bool increment_bad_pw_count = false;
-
- if (NT_STATUS_EQUAL(status,NT_STATUS_WRONG_PASSWORD) &&
- (pdb_get_acct_ctrl(pwd) & ACB_NORMAL) &&
- NT_STATUS_IS_OK(update_login_attempts_status))
- {
- increment_bad_pw_count = true;
- }
-
- if (increment_bad_pw_count) {
- pdb_increment_bad_password_count(pwd);
- updated_badpw = true;
- } else {
- pdb_update_bad_password_count(pwd,
- &updated_badpw);
- }
- } else {
-
- if ((pdb_get_acct_ctrl(pwd) & ACB_NORMAL) &&
- (pdb_get_bad_password_count(pwd) > 0)){
- pdb_set_bad_password_count(pwd, 0, PDB_CHANGED);
- pdb_set_bad_password_time(pwd, 0, PDB_CHANGED);
- updated_badpw = true;
- }
- }
-
- if (updated_badpw) {
- NTSTATUS update_status;
- become_root();
- update_status = pdb_update_sam_account(pwd);
- unbecome_root();
-
- if (!NT_STATUS_IS_OK(update_status)) {
- DEBUG(1, ("Failed to modify entry: %s\n",
- nt_errstr(update_status)));
- }
- }
-
- out:
- TALLOC_FREE(pwd);
-
- return status;
+ return NT_STATUS_NOT_IMPLEMENTED;
}
/*******************************************************************