* [PATCH 1/5] samba: Security Advisory - CVE-2013-4496
@ 2014-06-13 6:12 Chong Lu
2014-06-13 6:12 ` [PATCH 2/5] samba: fix parsing linemarkers in preprocessor output Chong Lu
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Chong Lu @ 2014-06-13 6:12 UTC (permalink / raw)
To: openembedded-devel
Samba 3.x before 3.6.23, 4.0.x before 4.0.16, and 4.1.x before 4.1.6
does not enforce the password-guessing protection mechanism for all
interfaces, which makes it easier for remote attackers to obtain access
via brute-force ChangePasswordUser2 (1) SAMR or (2) RAP attempts.
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4496
Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
---
.../samba/samba/samba-3.6.22-CVE-2013-4496.patch | 966 ++++++++++++++++++++
meta-oe/recipes-connectivity/samba/samba_3.6.8.bb | 1 +
2 files changed, 967 insertions(+)
create mode 100644 meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
diff --git a/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
new file mode 100644
index 0000000..c190a6c
--- /dev/null
+++ b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
@@ -0,0 +1,966 @@
+Upstream-Status: Backport
+
+From 25066eb31d6608075b5993b0d19b3e0843cdadeb 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/3] 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 0b4b25b..59905be 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 78ef1ba..3241b97 100644
+--- a/source3/rpc_server/samr/srv_samr_nt.c
++++ b/source3/rpc_server/samr/srv_samr_nt.c
+@@ -1715,9 +1715,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,
+@@ -1729,6 +1731,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;
+ }
+@@ -1742,6 +1753,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;
+
+@@ -1750,29 +1769,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 */
+@@ -1780,7 +1789,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
+@@ -1789,7 +1798,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;
+ }
+ }
+
+@@ -1799,7 +1808,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;
+ }
+ }
+
+@@ -1810,6 +1819,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 059da248cf69a3b0ef29836f49367b938fb1cbda 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/3] 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 f918dc0..e2c42d6 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 27f982ef33a1238ae48d7a38d608dd23ebde61ae 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/3] 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 | 126 +--------------
+ source4/torture/rpc/samr.c | 12 +-
+ 4 files changed, 24 insertions(+), 537 deletions(-)
+
+diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
+index 3241b97..2519a3f 100644
+--- a/source3/rpc_server/samr/srv_samr_nt.c
++++ b/source3/rpc_server/samr/srv_samr_nt.c
+@@ -1706,172 +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 = 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 aef12df..3b4ec65 100644
+--- a/source3/smbd/lanman.c
++++ b/source3/smbd/lanman.c
+@@ -2947,259 +2947,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,uint16 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->client_id,
+- 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,
+- global_myname(),
+- 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, pass1, 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).
+ ****************************************************************************/
+
+@@ -5790,7 +5537,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 ee13a11..e618740 100644
+--- a/source4/rpc_server/samr/samr_password.c
++++ b/source4/rpc_server/samr/samr_password.c
+@@ -32,131 +32,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);
+- if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
+- return NT_STATUS_WRONG_PASSWORD;
+- }
+- }
+-
+- /* 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, 16) != 0) {
+- 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) {
+- D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
+- if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
+- 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) {
+- D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
+- if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
+- return NT_STATUS_WRONG_PASSWORD;
+- }
+- }
+-
+- /* 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;
+- }
+-
+- /* 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 7d9a1e2..adfc5d4 100644
+--- a/source4/torture/rpc/samr.c
++++ b/source4/torture/rpc/samr.c
+@@ -1728,8 +1728,16 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
+
+ torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+ "ChangePasswordUser failed");
+- 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");
++
++ /* 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");
++ }
+
+ /* Unbreak the LM hash */
+ hash1.hash[0]--;
+--
+1.7.9.5
+
diff --git a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
index 20b609d..f80e41e 100644
--- a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
+++ b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
@@ -30,6 +30,7 @@ SRC_URI += "\
file://configure-disable-getaddrinfo-cross.patch;patchdir=.. \
file://configure-disable-core_pattern-cross-check.patch;patchdir=.. \
file://configure-libunwind.patch;patchdir=.. \
+ file://samba-3.6.22-CVE-2013-4496.patch;patchdir=.. \
"
SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be"
SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de"
--
1.7.9.5
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/5] samba: fix parsing linemarkers in preprocessor output
2014-06-13 6:12 [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Chong Lu
@ 2014-06-13 6:12 ` Chong Lu
2014-06-13 6:12 ` [PATCH 3/5] samba: fix two CVEs CVE-2013-0213 CVE-2013-0214 Chong Lu
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Chong Lu @ 2014-06-13 6:12 UTC (permalink / raw)
To: openembedded-devel
When PIDL calls out to C preprocessor to expand IDL files
and parse the output, it filters out linemarkers and line control
information as described in http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
and http://gcc.gnu.org/onlinedocs/cpp/Line-Control.html#Line-Control
With gcc 4.8 stdc-predef.h is included automatically and linemarker for the
file has extended flags that PIDL couldn't parse ('system header that needs to
be extern "C" protected for C++')
Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
---
...arsing-linemarkers-in-preprocessor-output.patch | 68 ++++++++++++++++++++
meta-oe/recipes-connectivity/samba/samba_3.6.8.bb | 1 +
2 files changed, 69 insertions(+)
create mode 100644 meta-oe/recipes-connectivity/samba/samba/0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch
diff --git a/meta-oe/recipes-connectivity/samba/samba/0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch b/meta-oe/recipes-connectivity/samba/samba/0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch
new file mode 100644
index 0000000..586867d
--- /dev/null
+++ b/meta-oe/recipes-connectivity/samba/samba/0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch
@@ -0,0 +1,68 @@
+Upstream-Status: Backport
+
+From b07ade6e6fcc8b844cf1fb8b6038617281c4c2d0 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <ab@samba.org>
+Date: Wed, 6 Feb 2013 10:17:57 +0200
+Subject: [PATCH] PIDL: fix parsing linemarkers in preprocessor output
+
+Commit b07ade6e6fcc8b844cf1fb8b6038617281c4c2d0 v3-6-stable
+
+When PIDL calls out to C preprocessor to expand IDL files
+and parse the output, it filters out linemarkers and line control
+information as described in http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
+and http://gcc.gnu.org/onlinedocs/cpp/Line-Control.html#Line-Control
+
+With gcc 4.8 stdc-predef.h is included automatically and linemarker for the
+file has extended flags that PIDL couldn't parse ('system header that needs to
+be extern "C" protected for C++')
+
+Thanks to Jakub Jelinek <jakub@redhat.com> for explanation of the linemarker format.
+
+Fixes https://bugzilla.redhat.com/show_bug.cgi?id=906517
+
+Reviewed-by: Andreas Schneider <asn@samba.org>
+(cherry picked from commit 6ba7ab5c14801aecae96373d5a9db7ab82957526)
+
+Signed-off-by: Andreas Schneider <asn@samba.org>
+
+Fix bug #9636 - pidl can't parse new linemarkers in preprocessor output.
+(cherry picked from commit 643571470f2e4cd2f58bd60ac7189abb826d33cc)
+(cherry picked from commit b5a8afd6550e9091d169d3010751913bb483fc4b)
+---
+ pidl/idl.yp | 4 +++-
+ pidl/lib/Parse/Pidl/IDL.pm | 4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/pidl/idl.yp b/pidl/idl.yp
+index b5c5185..c8a65f6 100644
+--- a/pidl/idl.yp
++++ b/pidl/idl.yp
+@@ -610,7 +610,9 @@ again:
+
+ for ($parser->YYData->{INPUT}) {
+ if (/^\#/) {
+- if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
++ # Linemarker format is described at
++ # http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
++ if (s/^\# (\d+) \"(.*?)\"(( \d+){1,4}|)//) {
+ $parser->YYData->{LINE} = $1-1;
+ $parser->YYData->{FILE} = $2;
+ goto again;
+diff --git a/pidl/lib/Parse/Pidl/IDL.pm b/pidl/lib/Parse/Pidl/IDL.pm
+index d4820ff..6927c89 100644
+--- a/pidl/lib/Parse/Pidl/IDL.pm
++++ b/pidl/lib/Parse/Pidl/IDL.pm
+@@ -2576,7 +2576,9 @@ again:
+
+ for ($parser->YYData->{INPUT}) {
+ if (/^\#/) {
+- if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
++ # Linemarker format is described at
++ # http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
++ if (s/^\# (\d+) \"(.*?)\"(( \d+){1,4}|)//) {
+ $parser->YYData->{LINE} = $1-1;
+ $parser->YYData->{FILE} = $2;
+ goto again;
+--
+1.7.5.4
+
diff --git a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
index f80e41e..c3e834d 100644
--- a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
+++ b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
@@ -31,6 +31,7 @@ SRC_URI += "\
file://configure-disable-core_pattern-cross-check.patch;patchdir=.. \
file://configure-libunwind.patch;patchdir=.. \
file://samba-3.6.22-CVE-2013-4496.patch;patchdir=.. \
+ file://0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch;patchdir=.. \
"
SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be"
SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de"
--
1.7.9.5
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/5] samba: fix two CVEs CVE-2013-0213 CVE-2013-0214
2014-06-13 6:12 [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Chong Lu
2014-06-13 6:12 ` [PATCH 2/5] samba: fix parsing linemarkers in preprocessor output Chong Lu
@ 2014-06-13 6:12 ` Chong Lu
2014-06-13 6:12 ` [PATCH 4/5] samba: Security Advisory - CVE-2013-4124 Chong Lu
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Chong Lu @ 2014-06-13 6:12 UTC (permalink / raw)
To: openembedded-devel
Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
---
.../samba-3.6.11-CVE-2013-0213-CVE-2013-0214.patch | 160 ++++++++++++++++++++
meta-oe/recipes-connectivity/samba/samba_3.6.8.bb | 1 +
2 files changed, 161 insertions(+)
create mode 100644 meta-oe/recipes-connectivity/samba/samba/samba-3.6.11-CVE-2013-0213-CVE-2013-0214.patch
diff --git a/meta-oe/recipes-connectivity/samba/samba/samba-3.6.11-CVE-2013-0213-CVE-2013-0214.patch b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.11-CVE-2013-0213-CVE-2013-0214.patch
new file mode 100644
index 0000000..cccb341
--- /dev/null
+++ b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.11-CVE-2013-0213-CVE-2013-0214.patch
@@ -0,0 +1,160 @@
+Upstream-Status: Backport
+
+From 71225948a249f079120282740fcc39fd6faa880e Mon Sep 17 00:00:00 2001
+From: Kai Blin <kai@samba.org>
+Date: Fri, 18 Jan 2013 23:11:07 +0100
+Subject: [PATCH 1/2] swat: Use X-Frame-Options header to avoid clickjacking
+
+Jann Horn reported a potential clickjacking vulnerability in SWAT where
+the SWAT page could be embedded into an attacker's page using a frame or
+iframe and then used to trick the user to change Samba settings.
+
+Avoid this by telling the browser to refuse the frame embedding via the
+X-Frame-Options: DENY header.
+
+Signed-off-by: Kai Blin <kai@samba.org>
+
+Fix bug #9576 - CVE-2013-0213: Clickjacking issue in SWAT.
+---
+ source3/web/swat.c | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/source3/web/swat.c b/source3/web/swat.c
+index 1f6eb6c..ed80c38 100644
+--- a/source3/web/swat.c
++++ b/source3/web/swat.c
+@@ -266,7 +266,8 @@ static void print_header(void)
+ if (!cgi_waspost()) {
+ printf("Expires: 0\r\n");
+ }
+- printf("Content-type: text/html\r\n\r\n");
++ printf("Content-type: text/html\r\n");
++ printf("X-Frame-Options: DENY\r\n\r\n");
+
+ if (!include_html("include/header.html")) {
+ printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
+--
+1.7.7
+
+
+From 91f4275873ebeda8f57684f09df67162ae80515a Mon Sep 17 00:00:00 2001
+From: Kai Blin <kai@samba.org>
+Date: Mon, 28 Jan 2013 21:41:07 +0100
+Subject: [PATCH 2/2] swat: Use additional nonce on XSRF protection
+
+If the user had a weak password on the root account of a machine running
+SWAT, there still was a chance of being targetted by an XSRF on a
+malicious web site targetting the SWAT setup.
+
+Use a random nonce stored in secrets.tdb to close this possible attack
+window. Thanks to Jann Horn for reporting this issue.
+
+Signed-off-by: Kai Blin <kai@samba.org>
+
+Fix bug #9577: CVE-2013-0214: Potential XSRF in SWAT.
+---
+ source3/web/cgi.c | 40 ++++++++++++++++++++++++++--------------
+ source3/web/swat.c | 2 ++
+ source3/web/swat_proto.h | 1 +
+ 3 files changed, 29 insertions(+), 14 deletions(-)
+
+diff --git a/source3/web/cgi.c b/source3/web/cgi.c
+index ef1b856..861bc84 100644
+--- a/source3/web/cgi.c
++++ b/source3/web/cgi.c
+@@ -48,6 +48,7 @@ static const char *baseurl;
+ static char *pathinfo;
+ static char *C_user;
+ static char *C_pass;
++static char *C_nonce;
+ static bool inetd_server;
+ static bool got_request;
+
+@@ -329,20 +330,7 @@ static void cgi_web_auth(void)
+ C_user = SMB_STRDUP(user);
+
+ if (!setuid(0)) {
+- C_pass = secrets_fetch_generic("root", "SWAT");
+- if (C_pass == NULL) {
+- char *tmp_pass = NULL;
+- tmp_pass = generate_random_password(talloc_tos(),
+- 16, 16);
+- if (tmp_pass == NULL) {
+- printf("%sFailed to create random nonce for "
+- "SWAT session\n<br>%s\n", head, tail);
+- exit(0);
+- }
+- secrets_store_generic("root", "SWAT", tmp_pass);
+- C_pass = SMB_STRDUP(tmp_pass);
+- TALLOC_FREE(tmp_pass);
+- }
++ C_pass = SMB_STRDUP(cgi_nonce());
+ }
+ setuid(pwd->pw_uid);
+ if (geteuid() != pwd->pw_uid || getuid() != pwd->pw_uid) {
+@@ -459,6 +447,30 @@ char *cgi_user_pass(void)
+ }
+
+ /***************************************************************************
++return a ptr to the nonce
++ ***************************************************************************/
++char *cgi_nonce(void)
++{
++ const char *head = "Content-Type: text/html\r\n\r\n<HTML><BODY><H1>SWAT installation Error</H1>\n";
++ const char *tail = "</BODY></HTML>\r\n";
++ C_nonce = secrets_fetch_generic("root", "SWAT");
++ if (C_nonce == NULL) {
++ char *tmp_pass = NULL;
++ tmp_pass = generate_random_password(talloc_tos(),
++ 16, 16);
++ if (tmp_pass == NULL) {
++ printf("%sFailed to create random nonce for "
++ "SWAT session\n<br>%s\n", head, tail);
++ exit(0);
++ }
++ secrets_store_generic("root", "SWAT", tmp_pass);
++ C_nonce = SMB_STRDUP(tmp_pass);
++ TALLOC_FREE(tmp_pass);
++ }
++ return(C_nonce);
++}
++
++/***************************************************************************
+ handle a file download
+ ***************************************************************************/
+ static void cgi_download(char *file)
+diff --git a/source3/web/swat.c b/source3/web/swat.c
+index ed80c38..f8933d2 100644
+--- a/source3/web/swat.c
++++ b/source3/web/swat.c
+@@ -154,6 +154,7 @@ void get_xsrf_token(const char *username, const char *pass,
+ MD5_CTX md5_ctx;
+ uint8_t token[16];
+ int i;
++ char *nonce = cgi_nonce();
+
+ token_str[0] = '\0';
+ ZERO_STRUCT(md5_ctx);
+@@ -167,6 +168,7 @@ void get_xsrf_token(const char *username, const char *pass,
+ if (pass != NULL) {
+ MD5Update(&md5_ctx, (uint8_t *)pass, strlen(pass));
+ }
++ MD5Update(&md5_ctx, (uint8_t *)nonce, strlen(nonce));
+
+ MD5Final(token, &md5_ctx);
+
+diff --git a/source3/web/swat_proto.h b/source3/web/swat_proto.h
+index 424a3af..fe51b1f 100644
+--- a/source3/web/swat_proto.h
++++ b/source3/web/swat_proto.h
+@@ -32,6 +32,7 @@ const char *cgi_variable_nonull(const char *name);
+ bool am_root(void);
+ char *cgi_user_name(void);
+ char *cgi_user_pass(void);
++char *cgi_nonce(void);
+ void cgi_setup(const char *rootdir, int auth_required);
+ const char *cgi_baseurl(void);
+ const char *cgi_pathinfo(void);
+--
+1.7.7
+
diff --git a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
index c3e834d..a5e7dcd 100644
--- a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
+++ b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
@@ -32,6 +32,7 @@ SRC_URI += "\
file://configure-libunwind.patch;patchdir=.. \
file://samba-3.6.22-CVE-2013-4496.patch;patchdir=.. \
file://0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch;patchdir=.. \
+ file://samba-3.6.11-CVE-2013-0213-CVE-2013-0214.patch;patchdir=.. \
"
SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be"
SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de"
--
1.7.9.5
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/5] samba: Security Advisory - CVE-2013-4124
2014-06-13 6:12 [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Chong Lu
2014-06-13 6:12 ` [PATCH 2/5] samba: fix parsing linemarkers in preprocessor output Chong Lu
2014-06-13 6:12 ` [PATCH 3/5] samba: fix two CVEs CVE-2013-0213 CVE-2013-0214 Chong Lu
@ 2014-06-13 6:12 ` Chong Lu
2014-06-13 6:12 ` [PATCH 5/5] samba: Security Advisory - CVE-2013-4475 Chong Lu
2014-06-13 11:11 ` [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Martin Jansa
4 siblings, 0 replies; 8+ messages in thread
From: Chong Lu @ 2014-06-13 6:12 UTC (permalink / raw)
To: openembedded-devel
Integer overflow in the read_nttrans_ea_list function in nttrans.c in
smbd in Samba 3.x before 3.5.22, 3.6.x before 3.6.17, and 4.x before
4.0.8 allows remote attackers to cause a denial of service (memory
consumption) via a malformed packet.
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4124
Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
---
.../samba/samba/samba-3.6.16-CVE-2013-4124.patch | 43 ++++++++++++++++++++
meta-oe/recipes-connectivity/samba/samba_3.6.8.bb | 1 +
2 files changed, 44 insertions(+)
create mode 100644 meta-oe/recipes-connectivity/samba/samba/samba-3.6.16-CVE-2013-4124.patch
diff --git a/meta-oe/recipes-connectivity/samba/samba/samba-3.6.16-CVE-2013-4124.patch b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.16-CVE-2013-4124.patch
new file mode 100644
index 0000000..54b8edf
--- /dev/null
+++ b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.16-CVE-2013-4124.patch
@@ -0,0 +1,43 @@
+Upstream-Status: Backport
+
+From efdbcabbe97a594572d71d714d258a5854c5d8ce Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Wed, 10 Jul 2013 17:10:17 -0700
+Subject: [PATCH] Fix bug #10010 - Missing integer wrap protection in EA list
+ reading can cause server to loop with DOS.
+
+Ensure we never wrap whilst adding client provided input.
+CVE-2013-4124
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+---
+ source3/smbd/nttrans.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
+index ea9d417..5fc3a09 100644
+--- a/source3/smbd/nttrans.c
++++ b/source3/smbd/nttrans.c
+@@ -989,7 +989,19 @@ struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t
+ if (next_offset == 0) {
+ break;
+ }
++
++ /* Integer wrap protection for the increment. */
++ if (offset + next_offset < offset) {
++ break;
++ }
++
+ offset += next_offset;
++
++ /* Integer wrap protection for while loop. */
++ if (offset + 4 < offset) {
++ break;
++ }
++
+ }
+
+ return ea_list_head;
+--
+1.7.10.4
+
diff --git a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
index a5e7dcd..331796c 100644
--- a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
+++ b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
@@ -33,6 +33,7 @@ SRC_URI += "\
file://samba-3.6.22-CVE-2013-4496.patch;patchdir=.. \
file://0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch;patchdir=.. \
file://samba-3.6.11-CVE-2013-0213-CVE-2013-0214.patch;patchdir=.. \
+ file://samba-3.6.16-CVE-2013-4124.patch;patchdir=.. \
"
SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be"
SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de"
--
1.7.9.5
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/5] samba: Security Advisory - CVE-2013-4475
2014-06-13 6:12 [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Chong Lu
` (2 preceding siblings ...)
2014-06-13 6:12 ` [PATCH 4/5] samba: Security Advisory - CVE-2013-4124 Chong Lu
@ 2014-06-13 6:12 ` Chong Lu
2014-06-13 11:11 ` [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Martin Jansa
4 siblings, 0 replies; 8+ messages in thread
From: Chong Lu @ 2014-06-13 6:12 UTC (permalink / raw)
To: openembedded-devel
Samba 3.x before 3.6.20, 4.0.x before 4.0.11, and 4.1.x before 4.1.1,
when vfs_streams_depot or vfs_streams_xattr is enabled, allows remote
attackers to bypass intended file restrictions by leveraging ACL
differences between a file and an associated alternate data stream
(ADS).
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4475
Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
---
.../samba/samba/samba-3.6.19-CVE-2013-4475.patch | 102 ++++++++++++++++++++
meta-oe/recipes-connectivity/samba/samba_3.6.8.bb | 1 +
2 files changed, 103 insertions(+)
create mode 100644 meta-oe/recipes-connectivity/samba/samba/samba-3.6.19-CVE-2013-4475.patch
diff --git a/meta-oe/recipes-connectivity/samba/samba/samba-3.6.19-CVE-2013-4475.patch b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.19-CVE-2013-4475.patch
new file mode 100644
index 0000000..a435c08
--- /dev/null
+++ b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.19-CVE-2013-4475.patch
@@ -0,0 +1,102 @@
+Upstream-Status: Backport
+
+From 928910f01f951657ea4629a6d573ac00646d16f8 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Thu, 31 Oct 2013 13:48:42 -0700
+Subject: [PATCH] Fix bug #10229 - No access check verification on stream
+ files.
+
+https://bugzilla.samba.org/show_bug.cgi?id=10229
+
+We need to check if the requested access mask
+could be used to open the underlying file (if
+it existed), as we're passing in zero for the
+access mask to the base filename.
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+---
+ source3/smbd/open.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 61 insertions(+)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index 447de80..441b8cd 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -152,6 +152,48 @@ NTSTATUS smbd_check_open_rights(struct connection_struct *conn,
+ }
+
+ /****************************************************************************
++ Ensure when opening a base file for a stream open that we have permissions
++ to do so given the access mask on the base file.
++****************************************************************************/
++
++static NTSTATUS check_base_file_access(struct connection_struct *conn,
++ struct smb_filename *smb_fname,
++ uint32_t access_mask)
++{
++ uint32_t access_granted = 0;
++ NTSTATUS status;
++
++ status = smbd_calculate_access_mask(conn, smb_fname,
++ false,
++ access_mask,
++ &access_mask);
++ if (!NT_STATUS_IS_OK(status)) {
++ DEBUG(10, ("smbd_calculate_access_mask "
++ "on file %s returned %s\n",
++ smb_fname_str_dbg(smb_fname),
++ nt_errstr(status)));
++ return status;
++ }
++
++ if (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) {
++ uint32_t dosattrs;
++ if (!CAN_WRITE(conn)) {
++ return NT_STATUS_ACCESS_DENIED;
++ }
++ dosattrs = dos_mode(conn, smb_fname);
++ if (IS_DOS_READONLY(dosattrs)) {
++ return NT_STATUS_ACCESS_DENIED;
++ }
++ }
++
++
++ return smbd_check_open_rights(conn,
++ smb_fname,
++ access_mask,
++ &access_granted);
++}
++
++/****************************************************************************
+ fd support routines - attempt to do a dos_open.
+ ****************************************************************************/
+
+@@ -3227,6 +3269,25 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
+ if (SMB_VFS_STAT(conn, smb_fname_base) == -1) {
+ DEBUG(10, ("Unable to stat stream: %s\n",
+ smb_fname_str_dbg(smb_fname_base)));
++ } else {
++ /*
++ * https://bugzilla.samba.org/show_bug.cgi?id=10229
++ * We need to check if the requested access mask
++ * could be used to open the underlying file (if
++ * it existed), as we're passing in zero for the
++ * access mask to the base filename.
++ */
++ status = check_base_file_access(conn,
++ smb_fname_base,
++ access_mask);
++
++ if (!NT_STATUS_IS_OK(status)) {
++ DEBUG(10, ("Permission check "
++ "for base %s failed: "
++ "%s\n", smb_fname->base_name,
++ nt_errstr(status)));
++ goto fail;
++ }
+ }
+
+ /* Open the base file. */
+--
+1.8.4.1
+
diff --git a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
index 331796c..cf13a0f 100644
--- a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
+++ b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
@@ -34,6 +34,7 @@ SRC_URI += "\
file://0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch;patchdir=.. \
file://samba-3.6.11-CVE-2013-0213-CVE-2013-0214.patch;patchdir=.. \
file://samba-3.6.16-CVE-2013-4124.patch;patchdir=.. \
+ file://samba-3.6.19-CVE-2013-4475.patch;patchdir=.. \
"
SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be"
SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de"
--
1.7.9.5
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/5] samba: Security Advisory - CVE-2013-4496
2014-06-13 6:12 [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Chong Lu
` (3 preceding siblings ...)
2014-06-13 6:12 ` [PATCH 5/5] samba: Security Advisory - CVE-2013-4475 Chong Lu
@ 2014-06-13 11:11 ` Martin Jansa
2014-06-23 11:05 ` Martin Jansa
4 siblings, 1 reply; 8+ messages in thread
From: Martin Jansa @ 2014-06-13 11:11 UTC (permalink / raw)
To: openembedded-devel
[-- Attachment #1: Type: text/plain, Size: 35933 bytes --]
On Fri, Jun 13, 2014 at 02:12:54PM +0800, Chong Lu wrote:
> Samba 3.x before 3.6.23, 4.0.x before 4.0.16, and 4.1.x before 4.1.6
> does not enforce the password-guessing protection mechanism for all
> interfaces, which makes it easier for remote attackers to obtain access
> via brute-force ChangePasswordUser2 (1) SAMR or (2) RAP attempts.
>
> http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4496
As you care about samba, would you mind sending fix for autodetecting
talloc?
see
http://lists.openembedded.org/pipermail/openembedded-core/2014-June/093414.html
>
> Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
> Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
> ---
> .../samba/samba/samba-3.6.22-CVE-2013-4496.patch | 966 ++++++++++++++++++++
> meta-oe/recipes-connectivity/samba/samba_3.6.8.bb | 1 +
> 2 files changed, 967 insertions(+)
> create mode 100644 meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
>
> diff --git a/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
> new file mode 100644
> index 0000000..c190a6c
> --- /dev/null
> +++ b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
> @@ -0,0 +1,966 @@
> +Upstream-Status: Backport
> +
> +From 25066eb31d6608075b5993b0d19b3e0843cdadeb 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/3] 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 0b4b25b..59905be 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 78ef1ba..3241b97 100644
> +--- a/source3/rpc_server/samr/srv_samr_nt.c
> ++++ b/source3/rpc_server/samr/srv_samr_nt.c
> +@@ -1715,9 +1715,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,
> +@@ -1729,6 +1731,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;
> + }
> +@@ -1742,6 +1753,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;
> +
> +@@ -1750,29 +1769,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 */
> +@@ -1780,7 +1789,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
> +@@ -1789,7 +1798,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;
> + }
> + }
> +
> +@@ -1799,7 +1808,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;
> + }
> + }
> +
> +@@ -1810,6 +1819,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 059da248cf69a3b0ef29836f49367b938fb1cbda 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/3] 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 f918dc0..e2c42d6 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 27f982ef33a1238ae48d7a38d608dd23ebde61ae 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/3] 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 | 126 +--------------
> + source4/torture/rpc/samr.c | 12 +-
> + 4 files changed, 24 insertions(+), 537 deletions(-)
> +
> +diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
> +index 3241b97..2519a3f 100644
> +--- a/source3/rpc_server/samr/srv_samr_nt.c
> ++++ b/source3/rpc_server/samr/srv_samr_nt.c
> +@@ -1706,172 +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 = 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 aef12df..3b4ec65 100644
> +--- a/source3/smbd/lanman.c
> ++++ b/source3/smbd/lanman.c
> +@@ -2947,259 +2947,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,uint16 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->client_id,
> +- 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,
> +- global_myname(),
> +- 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, pass1, 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).
> + ****************************************************************************/
> +
> +@@ -5790,7 +5537,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 ee13a11..e618740 100644
> +--- a/source4/rpc_server/samr/samr_password.c
> ++++ b/source4/rpc_server/samr/samr_password.c
> +@@ -32,131 +32,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);
> +- if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
> +- return NT_STATUS_WRONG_PASSWORD;
> +- }
> +- }
> +-
> +- /* 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, 16) != 0) {
> +- 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) {
> +- D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
> +- if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
> +- 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) {
> +- D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
> +- if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
> +- return NT_STATUS_WRONG_PASSWORD;
> +- }
> +- }
> +-
> +- /* 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;
> +- }
> +-
> +- /* 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 7d9a1e2..adfc5d4 100644
> +--- a/source4/torture/rpc/samr.c
> ++++ b/source4/torture/rpc/samr.c
> +@@ -1728,8 +1728,16 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
> +
> + torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
> + "ChangePasswordUser failed");
> +- 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");
> ++
> ++ /* 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");
> ++ }
> +
> + /* Unbreak the LM hash */
> + hash1.hash[0]--;
> +--
> +1.7.9.5
> +
> diff --git a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
> index 20b609d..f80e41e 100644
> --- a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
> +++ b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
> @@ -30,6 +30,7 @@ SRC_URI += "\
> file://configure-disable-getaddrinfo-cross.patch;patchdir=.. \
> file://configure-disable-core_pattern-cross-check.patch;patchdir=.. \
> file://configure-libunwind.patch;patchdir=.. \
> + file://samba-3.6.22-CVE-2013-4496.patch;patchdir=.. \
> "
> SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be"
> SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de"
> --
> 1.7.9.5
>
> --
> _______________________________________________
> Openembedded-devel mailing list
> Openembedded-devel@lists.openembedded.org
> http://lists.openembedded.org/mailman/listinfo/openembedded-devel
--
Martin 'JaMa' Jansa jabber: Martin.Jansa@gmail.com
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 188 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/5] samba: Security Advisory - CVE-2013-4496
2014-06-13 11:11 ` [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Martin Jansa
@ 2014-06-23 11:05 ` Martin Jansa
2014-06-25 2:18 ` Chong Lu
0 siblings, 1 reply; 8+ messages in thread
From: Martin Jansa @ 2014-06-23 11:05 UTC (permalink / raw)
To: openembedded-devel
[-- Attachment #1: Type: text/plain, Size: 38200 bytes --]
On Fri, Jun 13, 2014 at 01:11:28PM +0200, Martin Jansa wrote:
> On Fri, Jun 13, 2014 at 02:12:54PM +0800, Chong Lu wrote:
> > Samba 3.x before 3.6.23, 4.0.x before 4.0.16, and 4.1.x before 4.1.6
> > does not enforce the password-guessing protection mechanism for all
> > interfaces, which makes it easier for remote attackers to obtain access
> > via brute-force ChangePasswordUser2 (1) SAMR or (2) RAP attempts.
> >
> > http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4496
>
> As you care about samba, would you mind sending fix for autodetecting
> talloc?
>
> see
> http://lists.openembedded.org/pipermail/openembedded-core/2014-June/093414.html
I've merged this changes (as I don't want to block security fixes), but
please fix autodetecting talloc.
> > Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
> > Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
> > ---
> > .../samba/samba/samba-3.6.22-CVE-2013-4496.patch | 966 ++++++++++++++++++++
> > meta-oe/recipes-connectivity/samba/samba_3.6.8.bb | 1 +
> > 2 files changed, 967 insertions(+)
> > create mode 100644 meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
> >
> > diff --git a/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
> > new file mode 100644
> > index 0000000..c190a6c
> > --- /dev/null
> > +++ b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
> > @@ -0,0 +1,966 @@
> > +Upstream-Status: Backport
> > +
> > +From 25066eb31d6608075b5993b0d19b3e0843cdadeb 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/3] 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 0b4b25b..59905be 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 78ef1ba..3241b97 100644
> > +--- a/source3/rpc_server/samr/srv_samr_nt.c
> > ++++ b/source3/rpc_server/samr/srv_samr_nt.c
> > +@@ -1715,9 +1715,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,
> > +@@ -1729,6 +1731,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;
> > + }
> > +@@ -1742,6 +1753,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;
> > +
> > +@@ -1750,29 +1769,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 */
> > +@@ -1780,7 +1789,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
> > +@@ -1789,7 +1798,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;
> > + }
> > + }
> > +
> > +@@ -1799,7 +1808,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;
> > + }
> > + }
> > +
> > +@@ -1810,6 +1819,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 059da248cf69a3b0ef29836f49367b938fb1cbda 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/3] 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 f918dc0..e2c42d6 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 27f982ef33a1238ae48d7a38d608dd23ebde61ae 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/3] 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 | 126 +--------------
> > + source4/torture/rpc/samr.c | 12 +-
> > + 4 files changed, 24 insertions(+), 537 deletions(-)
> > +
> > +diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
> > +index 3241b97..2519a3f 100644
> > +--- a/source3/rpc_server/samr/srv_samr_nt.c
> > ++++ b/source3/rpc_server/samr/srv_samr_nt.c
> > +@@ -1706,172 +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 = 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 aef12df..3b4ec65 100644
> > +--- a/source3/smbd/lanman.c
> > ++++ b/source3/smbd/lanman.c
> > +@@ -2947,259 +2947,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,uint16 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->client_id,
> > +- 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,
> > +- global_myname(),
> > +- 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, pass1, 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).
> > + ****************************************************************************/
> > +
> > +@@ -5790,7 +5537,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 ee13a11..e618740 100644
> > +--- a/source4/rpc_server/samr/samr_password.c
> > ++++ b/source4/rpc_server/samr/samr_password.c
> > +@@ -32,131 +32,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);
> > +- if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
> > +- return NT_STATUS_WRONG_PASSWORD;
> > +- }
> > +- }
> > +-
> > +- /* 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, 16) != 0) {
> > +- 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) {
> > +- D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
> > +- if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
> > +- 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) {
> > +- D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
> > +- if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
> > +- return NT_STATUS_WRONG_PASSWORD;
> > +- }
> > +- }
> > +-
> > +- /* 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;
> > +- }
> > +-
> > +- /* 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 7d9a1e2..adfc5d4 100644
> > +--- a/source4/torture/rpc/samr.c
> > ++++ b/source4/torture/rpc/samr.c
> > +@@ -1728,8 +1728,16 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
> > +
> > + torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
> > + "ChangePasswordUser failed");
> > +- 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");
> > ++
> > ++ /* 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");
> > ++ }
> > +
> > + /* Unbreak the LM hash */
> > + hash1.hash[0]--;
> > +--
> > +1.7.9.5
> > +
> > diff --git a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
> > index 20b609d..f80e41e 100644
> > --- a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
> > +++ b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
> > @@ -30,6 +30,7 @@ SRC_URI += "\
> > file://configure-disable-getaddrinfo-cross.patch;patchdir=.. \
> > file://configure-disable-core_pattern-cross-check.patch;patchdir=.. \
> > file://configure-libunwind.patch;patchdir=.. \
> > + file://samba-3.6.22-CVE-2013-4496.patch;patchdir=.. \
> > "
> > SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be"
> > SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de"
> > --
> > 1.7.9.5
> >
> > --
> > _______________________________________________
> > Openembedded-devel mailing list
> > Openembedded-devel@lists.openembedded.org
> > http://lists.openembedded.org/mailman/listinfo/openembedded-devel
>
> --
> Martin 'JaMa' Jansa jabber: Martin.Jansa@gmail.com
--
Martin 'JaMa' Jansa jabber: Martin.Jansa@gmail.com
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 188 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/5] samba: Security Advisory - CVE-2013-4496
2014-06-23 11:05 ` Martin Jansa
@ 2014-06-25 2:18 ` Chong Lu
0 siblings, 0 replies; 8+ messages in thread
From: Chong Lu @ 2014-06-25 2:18 UTC (permalink / raw)
To: openembedded-devel
On 06/23/2014 07:05 PM, Martin Jansa wrote:
> On Fri, Jun 13, 2014 at 01:11:28PM +0200, Martin Jansa wrote:
>> On Fri, Jun 13, 2014 at 02:12:54PM +0800, Chong Lu wrote:
>>> Samba 3.x before 3.6.23, 4.0.x before 4.0.16, and 4.1.x before 4.1.6
>>> does not enforce the password-guessing protection mechanism for all
>>> interfaces, which makes it easier for remote attackers to obtain access
>>> via brute-force ChangePasswordUser2 (1) SAMR or (2) RAP attempts.
>>>
>>> http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4496
>> As you care about samba, would you mind sending fix for autodetecting
>> talloc?
>>
>> see
>> http://lists.openembedded.org/pipermail/openembedded-core/2014-June/093414.html
> I've merged this changes (as I don't want to block security fixes), but
> please fix autodetecting talloc.
OK, I will send a patch to fix this issue.
Best Regards
Chong
>>> Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
>>> Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
>>> ---
>>> .../samba/samba/samba-3.6.22-CVE-2013-4496.patch | 966 ++++++++++++++++++++
>>> meta-oe/recipes-connectivity/samba/samba_3.6.8.bb | 1 +
>>> 2 files changed, 967 insertions(+)
>>> create mode 100644 meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
>>>
>>> diff --git a/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
>>> new file mode 100644
>>> index 0000000..c190a6c
>>> --- /dev/null
>>> +++ b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch
>>> @@ -0,0 +1,966 @@
>>> +Upstream-Status: Backport
>>> +
>>> +From 25066eb31d6608075b5993b0d19b3e0843cdadeb 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/3] 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 0b4b25b..59905be 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 78ef1ba..3241b97 100644
>>> +--- a/source3/rpc_server/samr/srv_samr_nt.c
>>> ++++ b/source3/rpc_server/samr/srv_samr_nt.c
>>> +@@ -1715,9 +1715,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,
>>> +@@ -1729,6 +1731,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;
>>> + }
>>> +@@ -1742,6 +1753,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;
>>> +
>>> +@@ -1750,29 +1769,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 */
>>> +@@ -1780,7 +1789,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
>>> +@@ -1789,7 +1798,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;
>>> + }
>>> + }
>>> +
>>> +@@ -1799,7 +1808,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;
>>> + }
>>> + }
>>> +
>>> +@@ -1810,6 +1819,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 059da248cf69a3b0ef29836f49367b938fb1cbda 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/3] 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 f918dc0..e2c42d6 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 27f982ef33a1238ae48d7a38d608dd23ebde61ae 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/3] 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 | 126 +--------------
>>> + source4/torture/rpc/samr.c | 12 +-
>>> + 4 files changed, 24 insertions(+), 537 deletions(-)
>>> +
>>> +diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
>>> +index 3241b97..2519a3f 100644
>>> +--- a/source3/rpc_server/samr/srv_samr_nt.c
>>> ++++ b/source3/rpc_server/samr/srv_samr_nt.c
>>> +@@ -1706,172 +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 = 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 aef12df..3b4ec65 100644
>>> +--- a/source3/smbd/lanman.c
>>> ++++ b/source3/smbd/lanman.c
>>> +@@ -2947,259 +2947,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,uint16 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->client_id,
>>> +- 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,
>>> +- global_myname(),
>>> +- 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, pass1, 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).
>>> + ****************************************************************************/
>>> +
>>> +@@ -5790,7 +5537,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 ee13a11..e618740 100644
>>> +--- a/source4/rpc_server/samr/samr_password.c
>>> ++++ b/source4/rpc_server/samr/samr_password.c
>>> +@@ -32,131 +32,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);
>>> +- if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
>>> +- return NT_STATUS_WRONG_PASSWORD;
>>> +- }
>>> +- }
>>> +-
>>> +- /* 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, 16) != 0) {
>>> +- 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) {
>>> +- D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
>>> +- if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
>>> +- 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) {
>>> +- D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
>>> +- if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
>>> +- return NT_STATUS_WRONG_PASSWORD;
>>> +- }
>>> +- }
>>> +-
>>> +- /* 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;
>>> +- }
>>> +-
>>> +- /* 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 7d9a1e2..adfc5d4 100644
>>> +--- a/source4/torture/rpc/samr.c
>>> ++++ b/source4/torture/rpc/samr.c
>>> +@@ -1728,8 +1728,16 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
>>> +
>>> + torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
>>> + "ChangePasswordUser failed");
>>> +- 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");
>>> ++
>>> ++ /* 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");
>>> ++ }
>>> +
>>> + /* Unbreak the LM hash */
>>> + hash1.hash[0]--;
>>> +--
>>> +1.7.9.5
>>> +
>>> diff --git a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
>>> index 20b609d..f80e41e 100644
>>> --- a/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
>>> +++ b/meta-oe/recipes-connectivity/samba/samba_3.6.8.bb
>>> @@ -30,6 +30,7 @@ SRC_URI += "\
>>> file://configure-disable-getaddrinfo-cross.patch;patchdir=.. \
>>> file://configure-disable-core_pattern-cross-check.patch;patchdir=.. \
>>> file://configure-libunwind.patch;patchdir=.. \
>>> + file://samba-3.6.22-CVE-2013-4496.patch;patchdir=.. \
>>> "
>>> SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be"
>>> SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de"
>>> --
>>> 1.7.9.5
>>>
>>> --
>>> _______________________________________________
>>> Openembedded-devel mailing list
>>> Openembedded-devel@lists.openembedded.org
>>> http://lists.openembedded.org/mailman/listinfo/openembedded-devel
>> --
>> Martin 'JaMa' Jansa jabber: Martin.Jansa@gmail.com
>
>
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2014-06-25 2:19 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-13 6:12 [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Chong Lu
2014-06-13 6:12 ` [PATCH 2/5] samba: fix parsing linemarkers in preprocessor output Chong Lu
2014-06-13 6:12 ` [PATCH 3/5] samba: fix two CVEs CVE-2013-0213 CVE-2013-0214 Chong Lu
2014-06-13 6:12 ` [PATCH 4/5] samba: Security Advisory - CVE-2013-4124 Chong Lu
2014-06-13 6:12 ` [PATCH 5/5] samba: Security Advisory - CVE-2013-4475 Chong Lu
2014-06-13 11:11 ` [PATCH 1/5] samba: Security Advisory - CVE-2013-4496 Martin Jansa
2014-06-23 11:05 ` Martin Jansa
2014-06-25 2:18 ` Chong Lu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.