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 <[email protected]> > Signed-off-by: Chong Lu <[email protected]> > --- > .../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 <[email protected]> > +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 <[email protected]> > +Signed-off-by: Stefan Metzmacher <[email protected]> > +Signed-off-by: Jeremy Allison <[email protected]> > +Reviewed-by: Stefan Metzmacher <[email protected]> > +Reviewed-by: Jeremy Allison <[email protected]> > +Reviewed-by: Andreas Schneider <[email protected]> > +--- > + 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 <[email protected]> > +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 <[email protected]> > +Reviewed-by: Jeremy Allison <[email protected]> > +Signed-off-by: Andrew Bartlett <[email protected]> > +Reviewed-by: Andreas Schneider <[email protected]> > +--- > + 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 <[email protected]> > +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 <[email protected]> > +Reviewed-by: Andreas Schneider <[email protected]> > +Reviewed-by: Stefan Metzmacher <[email protected]> > +--- > + 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 > [email protected] > http://lists.openembedded.org/mailman/listinfo/openembedded-devel -- Martin 'JaMa' Jansa jabber: [email protected]
signature.asc
Description: Digital signature
-- _______________________________________________ Openembedded-devel mailing list [email protected] http://lists.openembedded.org/mailman/listinfo/openembedded-devel
