diff options
author | Bartłomiej Piotrowski <bpiotrowski@alpinelinux.org> | 2014-03-13 08:01:28 +0100 |
---|---|---|
committer | Bartłomiej Piotrowski <bpiotrowski@alpinelinux.org> | 2014-03-13 08:01:28 +0100 |
commit | 76de16d250f042fac913558e3579a5b9e4a21a5c (patch) | |
tree | b1020c62416422452743088a70cbda834ca84c8b | |
parent | a48dd9fb484b74733e8b1c6827712e9770eafe16 (diff) | |
download | aports-76de16d250f042fac913558e3579a5b9e4a21a5c.tar.bz2 aports-76de16d250f042fac913558e3579a5b9e4a21a5c.tar.xz |
main/samba: security fix for CVE-2013-4496 and CVE-2013-6442
-rw-r--r-- | main/samba/APKBUILD | 12 | ||||
-rw-r--r-- | main/samba/samba-4.1.5-CVE-2013-4496-CVE-2013-6442.patch | 1149 |
2 files changed, 1157 insertions, 4 deletions
diff --git a/main/samba/APKBUILD b/main/samba/APKBUILD index bfe6ab75b..30d8166a0 100644 --- a/main/samba/APKBUILD +++ b/main/samba/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=samba pkgver=4.1.3 -pkgrel=0 +pkgrel=1 pkgdesc="Tools to access a server's filespace and printers via SMB" url="http://www.samba.org" arch="all" @@ -22,6 +22,7 @@ source="http://us1.samba.org/samba/ftp/stable/samba-$pkgver.tar.gz samba.initd samba.confd samba.logrotate + samba-4.1.5-CVE-2013-4496-CVE-2013-6442.patch " pkggroups="winbind" @@ -289,12 +290,15 @@ libs() { md5sums="a5dbfe87f4cb3d9d91e15e5df99a59a1 samba-4.1.3.tar.gz 044c756d3c33c2d610c40bcd76cfb75c samba.initd c150433426e18261e6e3eed3930e1a76 samba.confd -b7cafabfb4fa5b3ab5f2e857d8d1c733 samba.logrotate" +b7cafabfb4fa5b3ab5f2e857d8d1c733 samba.logrotate +7907376d241adef1b9c8197484aef192 samba-4.1.5-CVE-2013-4496-CVE-2013-6442.patch" sha256sums="71da208d412b8d15ee26d2a76b2247df357242177d995fe5d9320355432e24db samba-4.1.3.tar.gz 86646cb845aababd9e8655994379526f03327a2cc33b489c3a7dea83ab689c8f samba.initd 1d12f98a7727967b04eb123109b34cfffef320822dc0e8059286b6e3394c3fc0 samba.confd -4c2b7d529126b2fc4f62fb09d99e49a87632d723a2d9d289a61e37dd84145be1 samba.logrotate" +4c2b7d529126b2fc4f62fb09d99e49a87632d723a2d9d289a61e37dd84145be1 samba.logrotate +ed57a4a50d95f43b2ff2d52a3a00e812e8b5589c226cb3be9d69cd4e5a15b2d8 samba-4.1.5-CVE-2013-4496-CVE-2013-6442.patch" sha512sums="c3e08df4e23c02ab759e819809ac8b146972508bbbbfc666e47ac180dea75dde85564e839aa4935e43f9b894bdf650fd3ed36463e70e9065c6e1c745142984d5 samba-4.1.3.tar.gz 59d05252b8ebbe6ba6a419edc86b66b9541d0bac9dbe810cccb20e64f6044e2900cc6c0979e077741ed00fbbf2d51f9184c83715013299782707b44e39aa99b1 samba.initd 4faf581ecef3ec38319e3c4ab6d3995c51fd7ba83180dc5553a2ff4dfb92efadb43030c543292130c4ed0c281dc0972c6973d52d48062c5edb39bb1c4bbb6dd6 samba.confd -f88ebe59ca3a9e9b77dd5993c13ef3e73a838efb8ed858088b464a330132d662f33e25c27819e38835389dee23057a3951de11bae1eef55db8ff5e1ec6760053 samba.logrotate" +f88ebe59ca3a9e9b77dd5993c13ef3e73a838efb8ed858088b464a330132d662f33e25c27819e38835389dee23057a3951de11bae1eef55db8ff5e1ec6760053 samba.logrotate +52c835409d59dac7d153a83b1ccf86ccafe2e49d7da5f643575fb1826cb1e55ac691ff1071764c92ada0e9bb557c060fd52340dd96258a7e18b87f044329f295 samba-4.1.5-CVE-2013-4496-CVE-2013-6442.patch" diff --git a/main/samba/samba-4.1.5-CVE-2013-4496-CVE-2013-6442.patch b/main/samba/samba-4.1.5-CVE-2013-4496-CVE-2013-6442.patch new file mode 100644 index 000000000..f448a3ccc --- /dev/null +++ b/main/samba/samba-4.1.5-CVE-2013-4496-CVE-2013-6442.patch @@ -0,0 +1,1149 @@ +From c129261c506c6b941630fd7f4bc72820eb272761 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett <abartlet@samba.org> +Date: Fri, 1 Nov 2013 14:55:44 +1300 +Subject: [PATCH 1/4] CVE-2013-4496:s3-samr: Block attempts to crack passwords + via repeated password changes + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245 + +Signed-off-by: Andrew Bartlett <abartlet@samba.org> +Signed-off-by: Stefan Metzmacher <metze@samba.org> +Signed-off-by: Jeremy Allison <jra@samba.org> +Reviewed-by: Stefan Metzmacher <metze@samba.org> +Reviewed-by: Jeremy Allison <jra@samba.org> +Reviewed-by: Andreas Schneider <asn@samba.org> +--- + source3/rpc_server/samr/srv_samr_chgpasswd.c | 55 ++++++++++++++++ + source3/rpc_server/samr/srv_samr_nt.c | 90 +++++++++++++++++++++----- + 2 files changed, 129 insertions(+), 16 deletions(-) + +diff --git a/source3/rpc_server/samr/srv_samr_chgpasswd.c b/source3/rpc_server/samr/srv_samr_chgpasswd.c +index db1f459..1c9c33a 100644 +--- a/source3/rpc_server/samr/srv_samr_chgpasswd.c ++++ b/source3/rpc_server/samr/srv_samr_chgpasswd.c +@@ -1106,6 +1106,8 @@ NTSTATUS pass_oem_change(char *user, const char *rhost, + struct samu *sampass = NULL; + NTSTATUS nt_status; + bool ret = false; ++ bool updated_badpw = false; ++ NTSTATUS update_login_attempts_status; + + if (!(sampass = samu_new(NULL))) { + return NT_STATUS_NO_MEMORY; +@@ -1121,6 +1123,13 @@ NTSTATUS pass_oem_change(char *user, const char *rhost, + return NT_STATUS_NO_SUCH_USER; + } + ++ /* 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", user)); ++ TALLOC_FREE(sampass); ++ return NT_STATUS_ACCOUNT_LOCKED_OUT; ++ } ++ + nt_status = check_oem_password(user, + password_encrypted_with_lm_hash, + old_lm_hash_encrypted, +@@ -1129,6 +1138,52 @@ NTSTATUS pass_oem_change(char *user, const char *rhost, + sampass, + &new_passwd); + ++ /* ++ * 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(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) && ++ NT_STATUS_IS_OK(update_login_attempts_status)) ++ { ++ increment_bad_pw_count = true; ++ } ++ ++ if (increment_bad_pw_count) { ++ pdb_increment_bad_password_count(sampass); ++ updated_badpw = true; ++ } else { ++ pdb_update_bad_password_count(sampass, ++ &updated_badpw); ++ } ++ } else { ++ ++ 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); ++ updated_badpw = true; ++ } ++ } ++ ++ if (updated_badpw) { ++ NTSTATUS update_status; ++ become_root(); ++ update_status = pdb_update_sam_account(sampass); ++ unbecome_root(); ++ ++ if (!NT_STATUS_IS_OK(update_status)) { ++ DEBUG(1, ("Failed to modify entry: %s\n", ++ nt_errstr(update_status))); ++ } ++ } ++ + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(sampass); + return nt_status; +diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c +index b366eda..98e8bea 100644 +--- a/source3/rpc_server/samr/srv_samr_nt.c ++++ b/source3/rpc_server/samr/srv_samr_nt.c +@@ -1722,9 +1722,11 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, + NTSTATUS status; + bool ret = false; + struct samr_user_info *uinfo; +- struct samu *pwd; ++ 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, +@@ -1736,6 +1738,15 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, + 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; + } +@@ -1749,6 +1760,14 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, + 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; + +@@ -1757,29 +1776,19 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, + + if (!lm_pass || !nt_pass) { + status = NT_STATUS_WRONG_PASSWORD; +- goto out; ++ goto update_login; + } + + 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; ++ goto update_login; + } + + /* decrypt and check the new nt hash */ +@@ -1787,7 +1796,7 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, + 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; ++ goto update_login; + } + + /* The NT Cross is not required by Win2k3 R2, but if present +@@ -1796,7 +1805,7 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, + 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; ++ goto update_login; + } + } + +@@ -1806,7 +1815,7 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, + 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; ++ goto update_login; + } + } + +@@ -1817,6 +1826,55 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, + } + + 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); + +-- +1.7.9.5 + + +From fab5ee090e2e4765441b82e17a6cbb98523f6943 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher <metze@samba.org> +Date: Tue, 5 Nov 2013 14:04:20 +0100 +Subject: [PATCH 2/4] CVE-2013-4496:s3:auth: fix memory leak in the + ACCOUNT_LOCKED_OUT case. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245 + +Signed-off-by: Stefan Metzmacher <metze@samba.org> +Reviewed-by: Jeremy Allison <jra@samba.org> +Signed-off-by: Andrew Bartlett <abartlet@samba.org> +Reviewed-by: Andreas Schneider <asn@samba.org> +--- + source3/auth/check_samsec.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/source3/auth/check_samsec.c b/source3/auth/check_samsec.c +index 7ed8cc2..94f30b1 100644 +--- a/source3/auth/check_samsec.c ++++ b/source3/auth/check_samsec.c +@@ -408,6 +408,7 @@ NTSTATUS check_sam_security(const DATA_BLOB *challenge, + /* 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", username)); ++ TALLOC_FREE(sampass); + return NT_STATUS_ACCOUNT_LOCKED_OUT; + } + +-- +1.7.9.5 + + +From bf3443c12f2a67481eb2e45ca41b906c438d06da Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett <abartlet@samba.org> +Date: Tue, 5 Nov 2013 16:16:46 +1300 +Subject: [PATCH 3/4] 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. + +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 + +Signed-off-by: Andrew Bartlett <abartlet@samba.org> +Reviewed-by: Andreas Schneider <asn@samba.org> +Reviewed-by: Stefan Metzmacher <metze@samba.org> +--- + source3/rpc_server/samr/srv_samr_nt.c | 169 +------------------- + source3/smbd/lanman.c | 254 ------------------------------- + source4/rpc_server/samr/samr_password.c | 145 +----------------- + source4/torture/rpc/samr.c | 6 + + 4 files changed, 20 insertions(+), 554 deletions(-) + +diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c +index 98e8bea..99f03ec 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; + } + + /******************************************************************* +diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c +index e6b9530..1b734a7 100644 +--- a/source3/smbd/lanman.c ++++ b/source3/smbd/lanman.c +@@ -2948,259 +2948,6 @@ static bool api_NetRemoteTOD(struct smbd_server_connection *sconn, + } + + /**************************************************************************** +- Set the user password. +-*****************************************************************************/ +- +-static bool api_SetUserPassword(struct smbd_server_connection *sconn, +- connection_struct *conn,uint64_t vuid, +- char *param, int tpscnt, +- char *data, int tdscnt, +- int mdrcnt,int mprcnt, +- char **rdata,char **rparam, +- int *rdata_len,int *rparam_len) +-{ +- char *np = get_safe_str_ptr(param,tpscnt,param,2); +- char *p = NULL; +- fstring user; +- fstring pass1,pass2; +- TALLOC_CTX *mem_ctx = talloc_tos(); +- NTSTATUS status, result; +- struct rpc_pipe_client *cli = NULL; +- struct policy_handle connect_handle, domain_handle, user_handle; +- struct lsa_String domain_name; +- struct dom_sid2 *domain_sid; +- struct lsa_String names; +- struct samr_Ids rids; +- struct samr_Ids types; +- struct samr_Password old_lm_hash; +- struct samr_Password new_lm_hash; +- int errcode = NERR_badpass; +- uint32_t rid; +- int encrypted; +- int min_pwd_length; +- struct dcerpc_binding_handle *b = NULL; +- +- /* Skip 2 strings. */ +- p = skip_string(param,tpscnt,np); +- p = skip_string(param,tpscnt,p); +- +- if (!np || !p) { +- return False; +- } +- +- /* Do we have a string ? */ +- if (skip_string(param,tpscnt,p) == NULL) { +- return False; +- } +- pull_ascii_fstring(user,p); +- +- p = skip_string(param,tpscnt,p); +- if (!p) { +- return False; +- } +- +- memset(pass1,'\0',sizeof(pass1)); +- memset(pass2,'\0',sizeof(pass2)); +- /* +- * We use 31 here not 32 as we're checking +- * the last byte we want to access is safe. +- */ +- if (!is_offset_safe(param,tpscnt,p,31)) { +- return False; +- } +- memcpy(pass1,p,16); +- memcpy(pass2,p+16,16); +- +- encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1); +- if (encrypted == -1) { +- errcode = W_ERROR_V(WERR_INVALID_PARAM); +- goto out; +- } +- +- min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1); +- if (min_pwd_length == -1) { +- errcode = W_ERROR_V(WERR_INVALID_PARAM); +- goto out; +- } +- +- *rparam_len = 4; +- *rparam = smb_realloc_limit(*rparam,*rparam_len); +- if (!*rparam) { +- return False; +- } +- +- *rdata_len = 0; +- +- DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n", +- user, encrypted, min_pwd_length)); +- +- ZERO_STRUCT(connect_handle); +- ZERO_STRUCT(domain_handle); +- ZERO_STRUCT(user_handle); +- +- status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, +- conn->session_info, +- conn->sconn->remote_address, +- conn->sconn->msg_ctx, +- &cli); +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n", +- nt_errstr(status))); +- errcode = W_ERROR_V(ntstatus_to_werror(status)); +- goto out; +- } +- +- b = cli->binding_handle; +- +- status = dcerpc_samr_Connect2(b, mem_ctx, +- lp_netbios_name(), +- SAMR_ACCESS_CONNECT_TO_SERVER | +- SAMR_ACCESS_ENUM_DOMAINS | +- SAMR_ACCESS_LOOKUP_DOMAIN, +- &connect_handle, +- &result); +- if (!NT_STATUS_IS_OK(status)) { +- errcode = W_ERROR_V(ntstatus_to_werror(status)); +- goto out; +- } +- if (!NT_STATUS_IS_OK(result)) { +- errcode = W_ERROR_V(ntstatus_to_werror(result)); +- goto out; +- } +- +- init_lsa_String(&domain_name, get_global_sam_name()); +- +- status = dcerpc_samr_LookupDomain(b, mem_ctx, +- &connect_handle, +- &domain_name, +- &domain_sid, +- &result); +- if (!NT_STATUS_IS_OK(status)) { +- errcode = W_ERROR_V(ntstatus_to_werror(status)); +- goto out; +- } +- if (!NT_STATUS_IS_OK(result)) { +- errcode = W_ERROR_V(ntstatus_to_werror(result)); +- goto out; +- } +- +- status = dcerpc_samr_OpenDomain(b, mem_ctx, +- &connect_handle, +- SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, +- domain_sid, +- &domain_handle, +- &result); +- if (!NT_STATUS_IS_OK(status)) { +- errcode = W_ERROR_V(ntstatus_to_werror(status)); +- goto out; +- } +- if (!NT_STATUS_IS_OK(result)) { +- errcode = W_ERROR_V(ntstatus_to_werror(result)); +- goto out; +- } +- +- init_lsa_String(&names, user); +- +- status = dcerpc_samr_LookupNames(b, mem_ctx, +- &domain_handle, +- 1, +- &names, +- &rids, +- &types, +- &result); +- if (!NT_STATUS_IS_OK(status)) { +- errcode = W_ERROR_V(ntstatus_to_werror(status)); +- goto out; +- } +- if (!NT_STATUS_IS_OK(result)) { +- errcode = W_ERROR_V(ntstatus_to_werror(result)); +- goto out; +- } +- +- if (rids.count != 1) { +- errcode = W_ERROR_V(WERR_NO_SUCH_USER); +- goto out; +- } +- if (rids.count != types.count) { +- errcode = W_ERROR_V(WERR_INVALID_PARAM); +- goto out; +- } +- if (types.ids[0] != SID_NAME_USER) { +- errcode = W_ERROR_V(WERR_INVALID_PARAM); +- goto out; +- } +- +- rid = rids.ids[0]; +- +- status = dcerpc_samr_OpenUser(b, mem_ctx, +- &domain_handle, +- SAMR_USER_ACCESS_CHANGE_PASSWORD, +- rid, +- &user_handle, +- &result); +- if (!NT_STATUS_IS_OK(status)) { +- errcode = W_ERROR_V(ntstatus_to_werror(status)); +- goto out; +- } +- if (!NT_STATUS_IS_OK(result)) { +- errcode = W_ERROR_V(ntstatus_to_werror(result)); +- goto out; +- } +- +- if (encrypted == 0) { +- E_deshash(pass1, old_lm_hash.hash); +- E_deshash(pass2, new_lm_hash.hash); +- } else { +- ZERO_STRUCT(old_lm_hash); +- ZERO_STRUCT(new_lm_hash); +- memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16)); +- memcpy(new_lm_hash.hash, pass2, MIN(strlen(pass2), 16)); +- } +- +- status = dcerpc_samr_ChangePasswordUser(b, mem_ctx, +- &user_handle, +- true, /* lm_present */ +- &old_lm_hash, +- &new_lm_hash, +- false, /* nt_present */ +- NULL, /* old_nt_crypted */ +- NULL, /* new_nt_crypted */ +- false, /* cross1_present */ +- NULL, /* nt_cross */ +- false, /* cross2_present */ +- NULL, /* lm_cross */ +- &result); +- if (!NT_STATUS_IS_OK(status)) { +- errcode = W_ERROR_V(ntstatus_to_werror(status)); +- goto out; +- } +- if (!NT_STATUS_IS_OK(result)) { +- errcode = W_ERROR_V(ntstatus_to_werror(result)); +- goto out; +- } +- +- errcode = NERR_Success; +- out: +- +- if (b && is_valid_policy_hnd(&user_handle)) { +- dcerpc_samr_Close(b, mem_ctx, &user_handle, &result); +- } +- if (b && is_valid_policy_hnd(&domain_handle)) { +- dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result); +- } +- if (b && is_valid_policy_hnd(&connect_handle)) { +- dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result); +- } +- +- memset((char *)pass1,'\0',sizeof(fstring)); +- memset((char *)pass2,'\0',sizeof(fstring)); +- +- SSVAL(*rparam,0,errcode); +- SSVAL(*rparam,2,0); /* converter word */ +- return(True); +-} +- +-/**************************************************************************** + Set the user password (SamOEM version - gets plaintext). + ****************************************************************************/ + +@@ -5797,7 +5544,6 @@ static const struct { + {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */ + {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */ + {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms}, +- {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword}, + {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon}, + {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo}, + {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum}, +diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c +index 2d9c48a..9d6c921 100644 +--- a/source4/rpc_server/samr/samr_password.c ++++ b/source4/rpc_server/samr/samr_password.c +@@ -33,150 +33,17 @@ + + /* + 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 all the other password hashes. ++ + */ + NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct samr_ChangePasswordUser *r) + { +- struct dcesrv_handle *h; +- struct samr_account_state *a_state; +- struct ldb_context *sam_ctx; +- struct ldb_message **res; +- int ret; +- struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; +- struct samr_Password *lm_pwd, *nt_pwd; +- NTSTATUS status = NT_STATUS_OK; +- const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL }; +- +- DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER); +- +- a_state = h->data; +- +- /* 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; +- } +- +- /* Connect to a SAMDB with system privileges for fetching the old pw +- * hashes. */ +- sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, +- dce_call->conn->dce_ctx->lp_ctx, +- system_session(dce_call->conn->dce_ctx->lp_ctx), 0); +- if (sam_ctx == NULL) { +- return NT_STATUS_INVALID_SYSTEM_SERVICE; +- } +- +- /* fetch the old hashes */ +- ret = gendb_search_dn(sam_ctx, mem_ctx, +- a_state->account_dn, &res, attrs); +- if (ret != 1) { +- return NT_STATUS_WRONG_PASSWORD; +- } +- +- status = samdb_result_passwords(mem_ctx, +- dce_call->conn->dce_ctx->lp_ctx, +- res[0], &lm_pwd, &nt_pwd); +- if (!NT_STATUS_IS_OK(status) || !nt_pwd) { +- return NT_STATUS_WRONG_PASSWORD; +- } +- +- /* decrypt and check the new lm hash */ +- if (lm_pwd) { +- 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); +- } +- +- /* 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); +- +- /* 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 && lm_pwd) { +- D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash); +- } +- +- /* 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 && lm_pwd) { +- D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash); +- } +- +- /* Start a SAM with user privileges for the password change */ +- sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, +- dce_call->conn->dce_ctx->lp_ctx, +- dce_call->conn->auth_state.session_info, 0); +- if (sam_ctx == NULL) { +- return NT_STATUS_INVALID_SYSTEM_SERVICE; +- } +- +- /* Start transaction */ +- ret = ldb_transaction_start(sam_ctx); +- if (ret != LDB_SUCCESS) { +- DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); +- return NT_STATUS_TRANSACTION_ABORTED; +- } +- +- /* Performs the password modification. We pass the old hashes read out +- * from the database since they were already checked against the user- +- * provided ones. */ +- status = samdb_set_password(sam_ctx, mem_ctx, +- a_state->account_dn, +- a_state->domain_state->domain_dn, +- NULL, &new_lmPwdHash, &new_ntPwdHash, +- lm_pwd, nt_pwd, /* this is a user password change */ +- NULL, +- NULL); +- if (!NT_STATUS_IS_OK(status)) { +- ldb_transaction_cancel(sam_ctx); +- return status; +- } +- +- /* decrypt and check the new lm hash */ +- if (lm_pwd) { +- if (memcmp(checkHash.hash, lm_pwd, 16) != 0) { +- ldb_transaction_cancel(sam_ctx); +- return NT_STATUS_WRONG_PASSWORD; +- } +- } +- +- if (memcmp(checkHash.hash, nt_pwd, 16) != 0) { +- ldb_transaction_cancel(sam_ctx); +- return NT_STATUS_WRONG_PASSWORD; +- } +- +- /* 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 && lm_pwd) { +- if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) { +- ldb_transaction_cancel(sam_ctx); +- return NT_STATUS_WRONG_PASSWORD; +- } +- } +- +- /* 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 && lm_pwd) { +- if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) { +- ldb_transaction_cancel(sam_ctx); +- return NT_STATUS_WRONG_PASSWORD; +- } +- } +- +- /* And this confirms it in a transaction commit */ +- ret = ldb_transaction_commit(sam_ctx); +- if (ret != LDB_SUCCESS) { +- DEBUG(1,("Failed to commit transaction to change password on %s: %s\n", +- ldb_dn_get_linearized(a_state->account_dn), +- ldb_errstring(sam_ctx))); +- return NT_STATUS_TRANSACTION_ABORTED; +- } +- +- return NT_STATUS_OK; ++ return NT_STATUS_NOT_IMPLEMENTED; + } + + /* +diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c +index a0a5f1a..cdfa2b8 100644 +--- a/source4/torture/rpc/samr.c ++++ b/source4/torture/rpc/samr.c +@@ -1759,6 +1759,12 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b, + torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n", + __location__, __FUNCTION__, + oldpass, newpass, nt_errstr(r.out.result)); ++ ++ /* Do not proceed if this call has been removed */ ++ if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) { ++ return true; ++ } ++ + if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) { + torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD, + "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash"); +-- +1.7.9.5 + + +From b0281ad59d3ba8b32787ce112fb4a83d935c60d1 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett <abartlet@samba.org> +Date: Thu, 28 Nov 2013 06:50:01 +1300 +Subject: [PATCH 4/4] CVE-2013-4496:Revert remainder of + ce895609b04380bfc41e4f8fddc84bd2f9324340 + +Part of this was removed when ChangePasswordUser was unimplemented, +but remove the remainder of this flawed commit. Fully check the +password first, as extract_pw_from_buffer() already does a partial +check of the password because it needs a correct old password to +correctly decrypt the length. + +Andrew Bartlett + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245 + +Signed-off-by: Andrew Bartlett <abartlet@samba.org> +Reviewed-by: Andreas Schneider <asn@samba.org> +Reviewed-by: Stefan Metzmacher <metze@samba.org> +--- + source4/rpc_server/samr/samr_password.c | 69 ++++++++++++++++--------------- + 1 file changed, 35 insertions(+), 34 deletions(-) + +diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c +index 9d6c921..685a8e7 100644 +--- a/source4/rpc_server/samr/samr_password.c ++++ b/source4/rpc_server/samr/samr_password.c +@@ -142,6 +142,9 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, + + E_deshash(new_pass, new_lm_hash); + E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash); ++ if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) { ++ return NT_STATUS_WRONG_PASSWORD; ++ } + + /* Connect to a SAMDB with user privileges for the password change */ + sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, +@@ -173,11 +176,6 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, + return status; + } + +- if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) { +- ldb_transaction_cancel(sam_ctx); +- return NT_STATUS_WRONG_PASSWORD; +- } +- + /* And this confirms it in a transaction commit */ + ret = ldb_transaction_commit(sam_ctx); + if (ret != LDB_SUCCESS) { +@@ -267,33 +265,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, + goto failed; + } + +- /* Connect to a SAMDB with user privileges for the password change */ +- sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, +- dce_call->conn->dce_ctx->lp_ctx, +- dce_call->conn->auth_state.session_info, 0); +- if (sam_ctx == NULL) { +- return NT_STATUS_INVALID_SYSTEM_SERVICE; +- } +- +- ret = ldb_transaction_start(sam_ctx); +- if (ret != LDB_SUCCESS) { +- DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); +- return NT_STATUS_TRANSACTION_ABORTED; +- } +- +- /* Performs the password modification. We pass the old hashes read out +- * from the database since they were already checked against the user- +- * provided ones. */ +- status = samdb_set_password(sam_ctx, mem_ctx, +- user_dn, NULL, +- &new_password, +- NULL, NULL, +- lm_pwd, nt_pwd, /* this is a user password change */ +- &reason, +- &dominfo); +- +- if (!NT_STATUS_IS_OK(status)) { +- ldb_transaction_cancel(sam_ctx); ++ if (r->in.nt_verifier == NULL) { ++ status = NT_STATUS_WRONG_PASSWORD; + goto failed; + } + +@@ -302,7 +275,6 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, + + E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash); + if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) { +- ldb_transaction_cancel(sam_ctx); + status = NT_STATUS_WRONG_PASSWORD; + goto failed; + } +@@ -322,13 +294,42 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, + E_deshash(new_pass, new_lm_hash); + E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash); + if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) { +- ldb_transaction_cancel(sam_ctx); + status = NT_STATUS_WRONG_PASSWORD; + goto failed; + } + } + } + ++ /* Connect to a SAMDB with user privileges for the password change */ ++ sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, ++ dce_call->conn->dce_ctx->lp_ctx, ++ dce_call->conn->auth_state.session_info, 0); ++ if (sam_ctx == NULL) { ++ return NT_STATUS_INVALID_SYSTEM_SERVICE; ++ } ++ ++ ret = ldb_transaction_start(sam_ctx); ++ if (ret != LDB_SUCCESS) { ++ DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); ++ return NT_STATUS_TRANSACTION_ABORTED; ++ } ++ ++ /* Performs the password modification. We pass the old hashes read out ++ * from the database since they were already checked against the user- ++ * provided ones. */ ++ status = samdb_set_password(sam_ctx, mem_ctx, ++ user_dn, NULL, ++ &new_password, ++ NULL, NULL, ++ lm_pwd, nt_pwd, /* this is a user password change */ ++ &reason, ++ &dominfo); ++ ++ if (!NT_STATUS_IS_OK(status)) { ++ ldb_transaction_cancel(sam_ctx); ++ goto failed; ++ } ++ + /* And this confirms it in a transaction commit */ + ret = ldb_transaction_commit(sam_ctx); + if (ret != LDB_SUCCESS) { +-- +1.7.9.5 + +From 82b1dafad17904bc224b0632486006fe88301b57 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison <jra@samba.org> +Date: Wed, 18 Dec 2013 13:56:18 -0800 +Subject: [PATCH] CVE-2013-6442: s3:smbcacls - ensure we don't lose an existing + ACL when setting owner or group owner. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=10327 +Bug 10327 - CVE-2013-6442: smbcacls --chown | --chgrp dacl regression + +Signed-off-by: Jeremy Allison <jra@samba.org> +Reviewed-by: Stefan Metzmacher <metze@samba.org> +--- + source3/utils/smbcacls.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c +index 11b7388..e3b7099 100644 +--- a/source3/utils/smbcacls.c ++++ b/source3/utils/smbcacls.c +@@ -990,7 +990,7 @@ static int owner_set(struct cli_state *cli, enum chown_mode change_mode, + return EXIT_FAILED; + } + +- sd = make_sec_desc(talloc_tos(),old->revision, old->type, ++ sd = make_sec_desc(talloc_tos(),old->revision, SEC_DESC_SELF_RELATIVE, + (change_mode == REQUEST_CHOWN) ? &sid : NULL, + (change_mode == REQUEST_CHGRP) ? &sid : NULL, + NULL, NULL, &sd_size); +-- +1.8.5.1 + |