diff options
| author | Chong.Lu@windriver.com <Chong.Lu@windriver.com> | 2014-06-13 14:12:54 +0800 |
|---|---|---|
| committer | Martin Jansa <Martin.Jansa@gmail.com> | 2014-06-21 19:22:24 +0200 |
| commit | 3d5d8c6d0f21de60dc84610a4d47da2d8c062901 (patch) | |
| tree | e549f5d8e529f58bbdd6e440b7dddb1651fba583 /meta-oe/recipes-connectivity/samba | |
| parent | 33a45cf6529243764bc383ee6c8ece00c7792e8b (diff) | |
| download | meta-openembedded-3d5d8c6d0f21de60dc84610a4d47da2d8c062901.tar.gz | |
samba: Security Advisory - CVE-2013-4496
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>
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
Diffstat (limited to 'meta-oe/recipes-connectivity/samba')
| -rw-r--r-- | meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch | 966 | ||||
| -rw-r--r-- | meta-oe/recipes-connectivity/samba/samba_3.6.8.bb | 1 |
2 files changed, 967 insertions, 0 deletions
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 0000000000..c190a6c507 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba/samba-3.6.22-CVE-2013-4496.patch | |||
| @@ -0,0 +1,966 @@ | |||
| 1 | Upstream-Status: Backport | ||
| 2 | |||
| 3 | From 25066eb31d6608075b5993b0d19b3e0843cdadeb Mon Sep 17 00:00:00 2001 | ||
| 4 | From: Andrew Bartlett <abartlet@samba.org> | ||
| 5 | Date: Fri, 1 Nov 2013 14:55:44 +1300 | ||
| 6 | Subject: [PATCH 1/3] CVE-2013-4496:s3-samr: Block attempts to crack passwords | ||
| 7 | via repeated password changes | ||
| 8 | |||
| 9 | Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245 | ||
| 10 | |||
| 11 | Signed-off-by: Andrew Bartlett <abartlet@samba.org> | ||
| 12 | Signed-off-by: Stefan Metzmacher <metze@samba.org> | ||
| 13 | Signed-off-by: Jeremy Allison <jra@samba.org> | ||
| 14 | Reviewed-by: Stefan Metzmacher <metze@samba.org> | ||
| 15 | Reviewed-by: Jeremy Allison <jra@samba.org> | ||
| 16 | Reviewed-by: Andreas Schneider <asn@samba.org> | ||
| 17 | --- | ||
| 18 | source3/rpc_server/samr/srv_samr_chgpasswd.c | 55 ++++++++++++++++ | ||
| 19 | source3/rpc_server/samr/srv_samr_nt.c | 90 +++++++++++++++++++++----- | ||
| 20 | 2 files changed, 129 insertions(+), 16 deletions(-) | ||
| 21 | |||
| 22 | diff --git a/source3/rpc_server/samr/srv_samr_chgpasswd.c b/source3/rpc_server/samr/srv_samr_chgpasswd.c | ||
| 23 | index 0b4b25b..59905be 100644 | ||
| 24 | --- a/source3/rpc_server/samr/srv_samr_chgpasswd.c | ||
| 25 | +++ b/source3/rpc_server/samr/srv_samr_chgpasswd.c | ||
| 26 | @@ -1106,6 +1106,8 @@ NTSTATUS pass_oem_change(char *user, const char *rhost, | ||
| 27 | struct samu *sampass = NULL; | ||
| 28 | NTSTATUS nt_status; | ||
| 29 | bool ret = false; | ||
| 30 | + bool updated_badpw = false; | ||
| 31 | + NTSTATUS update_login_attempts_status; | ||
| 32 | |||
| 33 | if (!(sampass = samu_new(NULL))) { | ||
| 34 | return NT_STATUS_NO_MEMORY; | ||
| 35 | @@ -1121,6 +1123,13 @@ NTSTATUS pass_oem_change(char *user, const char *rhost, | ||
| 36 | return NT_STATUS_NO_SUCH_USER; | ||
| 37 | } | ||
| 38 | |||
| 39 | + /* Quit if the account was locked out. */ | ||
| 40 | + if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) { | ||
| 41 | + DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", user)); | ||
| 42 | + TALLOC_FREE(sampass); | ||
| 43 | + return NT_STATUS_ACCOUNT_LOCKED_OUT; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | nt_status = check_oem_password(user, | ||
| 47 | password_encrypted_with_lm_hash, | ||
| 48 | old_lm_hash_encrypted, | ||
| 49 | @@ -1129,6 +1138,52 @@ NTSTATUS pass_oem_change(char *user, const char *rhost, | ||
| 50 | sampass, | ||
| 51 | &new_passwd); | ||
| 52 | |||
| 53 | + /* | ||
| 54 | + * Notify passdb backend of login success/failure. If not | ||
| 55 | + * NT_STATUS_OK the backend doesn't like the login | ||
| 56 | + */ | ||
| 57 | + update_login_attempts_status = pdb_update_login_attempts(sampass, | ||
| 58 | + NT_STATUS_IS_OK(nt_status)); | ||
| 59 | + | ||
| 60 | + if (!NT_STATUS_IS_OK(nt_status)) { | ||
| 61 | + bool increment_bad_pw_count = false; | ||
| 62 | + | ||
| 63 | + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) && | ||
| 64 | + (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) && | ||
| 65 | + NT_STATUS_IS_OK(update_login_attempts_status)) | ||
| 66 | + { | ||
| 67 | + increment_bad_pw_count = true; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + if (increment_bad_pw_count) { | ||
| 71 | + pdb_increment_bad_password_count(sampass); | ||
| 72 | + updated_badpw = true; | ||
| 73 | + } else { | ||
| 74 | + pdb_update_bad_password_count(sampass, | ||
| 75 | + &updated_badpw); | ||
| 76 | + } | ||
| 77 | + } else { | ||
| 78 | + | ||
| 79 | + if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) && | ||
| 80 | + (pdb_get_bad_password_count(sampass) > 0)){ | ||
| 81 | + pdb_set_bad_password_count(sampass, 0, PDB_CHANGED); | ||
| 82 | + pdb_set_bad_password_time(sampass, 0, PDB_CHANGED); | ||
| 83 | + updated_badpw = true; | ||
| 84 | + } | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + if (updated_badpw) { | ||
| 88 | + NTSTATUS update_status; | ||
| 89 | + become_root(); | ||
| 90 | + update_status = pdb_update_sam_account(sampass); | ||
| 91 | + unbecome_root(); | ||
| 92 | + | ||
| 93 | + if (!NT_STATUS_IS_OK(update_status)) { | ||
| 94 | + DEBUG(1, ("Failed to modify entry: %s\n", | ||
| 95 | + nt_errstr(update_status))); | ||
| 96 | + } | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | if (!NT_STATUS_IS_OK(nt_status)) { | ||
| 100 | TALLOC_FREE(sampass); | ||
| 101 | return nt_status; | ||
| 102 | diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c | ||
| 103 | index 78ef1ba..3241b97 100644 | ||
| 104 | --- a/source3/rpc_server/samr/srv_samr_nt.c | ||
| 105 | +++ b/source3/rpc_server/samr/srv_samr_nt.c | ||
| 106 | @@ -1715,9 +1715,11 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, | ||
| 107 | NTSTATUS status; | ||
| 108 | bool ret = false; | ||
| 109 | struct samr_user_info *uinfo; | ||
| 110 | - struct samu *pwd; | ||
| 111 | + struct samu *pwd = NULL; | ||
| 112 | struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; | ||
| 113 | struct samr_Password lm_pwd, nt_pwd; | ||
| 114 | + bool updated_badpw = false; | ||
| 115 | + NTSTATUS update_login_attempts_status; | ||
| 116 | |||
| 117 | uinfo = policy_handle_find(p, r->in.user_handle, | ||
| 118 | SAMR_USER_ACCESS_SET_PASSWORD, NULL, | ||
| 119 | @@ -1729,6 +1731,15 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, | ||
| 120 | DEBUG(5,("_samr_ChangePasswordUser: sid:%s\n", | ||
| 121 | sid_string_dbg(&uinfo->sid))); | ||
| 122 | |||
| 123 | + /* basic sanity checking on parameters. Do this before any database ops */ | ||
| 124 | + if (!r->in.lm_present || !r->in.nt_present || | ||
| 125 | + !r->in.old_lm_crypted || !r->in.new_lm_crypted || | ||
| 126 | + !r->in.old_nt_crypted || !r->in.new_nt_crypted) { | ||
| 127 | + /* we should really handle a change with lm not | ||
| 128 | + present */ | ||
| 129 | + return NT_STATUS_INVALID_PARAMETER_MIX; | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | if (!(pwd = samu_new(NULL))) { | ||
| 133 | return NT_STATUS_NO_MEMORY; | ||
| 134 | } | ||
| 135 | @@ -1742,6 +1753,14 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, | ||
| 136 | return NT_STATUS_WRONG_PASSWORD; | ||
| 137 | } | ||
| 138 | |||
| 139 | + /* Quit if the account was locked out. */ | ||
| 140 | + if (pdb_get_acct_ctrl(pwd) & ACB_AUTOLOCK) { | ||
| 141 | + DEBUG(3, ("Account for user %s was locked out.\n", | ||
| 142 | + pdb_get_username(pwd))); | ||
| 143 | + status = NT_STATUS_ACCOUNT_LOCKED_OUT; | ||
| 144 | + goto out; | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | { | ||
| 148 | const uint8_t *lm_pass, *nt_pass; | ||
| 149 | |||
| 150 | @@ -1750,29 +1769,19 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, | ||
| 151 | |||
| 152 | if (!lm_pass || !nt_pass) { | ||
| 153 | status = NT_STATUS_WRONG_PASSWORD; | ||
| 154 | - goto out; | ||
| 155 | + goto update_login; | ||
| 156 | } | ||
| 157 | |||
| 158 | memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash)); | ||
| 159 | memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash)); | ||
| 160 | } | ||
| 161 | |||
| 162 | - /* basic sanity checking on parameters. Do this before any database ops */ | ||
| 163 | - if (!r->in.lm_present || !r->in.nt_present || | ||
| 164 | - !r->in.old_lm_crypted || !r->in.new_lm_crypted || | ||
| 165 | - !r->in.old_nt_crypted || !r->in.new_nt_crypted) { | ||
| 166 | - /* we should really handle a change with lm not | ||
| 167 | - present */ | ||
| 168 | - status = NT_STATUS_INVALID_PARAMETER_MIX; | ||
| 169 | - goto out; | ||
| 170 | - } | ||
| 171 | - | ||
| 172 | /* decrypt and check the new lm hash */ | ||
| 173 | D_P16(lm_pwd.hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash); | ||
| 174 | D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash); | ||
| 175 | if (memcmp(checkHash.hash, lm_pwd.hash, 16) != 0) { | ||
| 176 | status = NT_STATUS_WRONG_PASSWORD; | ||
| 177 | - goto out; | ||
| 178 | + goto update_login; | ||
| 179 | } | ||
| 180 | |||
| 181 | /* decrypt and check the new nt hash */ | ||
| 182 | @@ -1780,7 +1789,7 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, | ||
| 183 | D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash); | ||
| 184 | if (memcmp(checkHash.hash, nt_pwd.hash, 16) != 0) { | ||
| 185 | status = NT_STATUS_WRONG_PASSWORD; | ||
| 186 | - goto out; | ||
| 187 | + goto update_login; | ||
| 188 | } | ||
| 189 | |||
| 190 | /* The NT Cross is not required by Win2k3 R2, but if present | ||
| 191 | @@ -1789,7 +1798,7 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, | ||
| 192 | D_P16(lm_pwd.hash, r->in.nt_cross->hash, checkHash.hash); | ||
| 193 | if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) { | ||
| 194 | status = NT_STATUS_WRONG_PASSWORD; | ||
| 195 | - goto out; | ||
| 196 | + goto update_login; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | @@ -1799,7 +1808,7 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, | ||
| 201 | D_P16(nt_pwd.hash, r->in.lm_cross->hash, checkHash.hash); | ||
| 202 | if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) { | ||
| 203 | status = NT_STATUS_WRONG_PASSWORD; | ||
| 204 | - goto out; | ||
| 205 | + goto update_login; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | @@ -1810,6 +1819,55 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, | ||
| 210 | } | ||
| 211 | |||
| 212 | status = pdb_update_sam_account(pwd); | ||
| 213 | + | ||
| 214 | +update_login: | ||
| 215 | + | ||
| 216 | + /* | ||
| 217 | + * Notify passdb backend of login success/failure. If not | ||
| 218 | + * NT_STATUS_OK the backend doesn't like the login | ||
| 219 | + */ | ||
| 220 | + update_login_attempts_status = pdb_update_login_attempts(pwd, | ||
| 221 | + NT_STATUS_IS_OK(status)); | ||
| 222 | + | ||
| 223 | + if (!NT_STATUS_IS_OK(status)) { | ||
| 224 | + bool increment_bad_pw_count = false; | ||
| 225 | + | ||
| 226 | + if (NT_STATUS_EQUAL(status,NT_STATUS_WRONG_PASSWORD) && | ||
| 227 | + (pdb_get_acct_ctrl(pwd) & ACB_NORMAL) && | ||
| 228 | + NT_STATUS_IS_OK(update_login_attempts_status)) | ||
| 229 | + { | ||
| 230 | + increment_bad_pw_count = true; | ||
| 231 | + } | ||
| 232 | + | ||
| 233 | + if (increment_bad_pw_count) { | ||
| 234 | + pdb_increment_bad_password_count(pwd); | ||
| 235 | + updated_badpw = true; | ||
| 236 | + } else { | ||
| 237 | + pdb_update_bad_password_count(pwd, | ||
| 238 | + &updated_badpw); | ||
| 239 | + } | ||
| 240 | + } else { | ||
| 241 | + | ||
| 242 | + if ((pdb_get_acct_ctrl(pwd) & ACB_NORMAL) && | ||
| 243 | + (pdb_get_bad_password_count(pwd) > 0)){ | ||
| 244 | + pdb_set_bad_password_count(pwd, 0, PDB_CHANGED); | ||
| 245 | + pdb_set_bad_password_time(pwd, 0, PDB_CHANGED); | ||
| 246 | + updated_badpw = true; | ||
| 247 | + } | ||
| 248 | + } | ||
| 249 | + | ||
| 250 | + if (updated_badpw) { | ||
| 251 | + NTSTATUS update_status; | ||
| 252 | + become_root(); | ||
| 253 | + update_status = pdb_update_sam_account(pwd); | ||
| 254 | + unbecome_root(); | ||
| 255 | + | ||
| 256 | + if (!NT_STATUS_IS_OK(update_status)) { | ||
| 257 | + DEBUG(1, ("Failed to modify entry: %s\n", | ||
| 258 | + nt_errstr(update_status))); | ||
| 259 | + } | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | out: | ||
| 263 | TALLOC_FREE(pwd); | ||
| 264 | |||
| 265 | -- | ||
| 266 | 1.7.9.5 | ||
| 267 | |||
| 268 | |||
| 269 | From 059da248cf69a3b0ef29836f49367b938fb1cbda Mon Sep 17 00:00:00 2001 | ||
| 270 | From: Stefan Metzmacher <metze@samba.org> | ||
| 271 | Date: Tue, 5 Nov 2013 14:04:20 +0100 | ||
| 272 | Subject: [PATCH 2/3] CVE-2013-4496:s3:auth: fix memory leak in the | ||
| 273 | ACCOUNT_LOCKED_OUT case. | ||
| 274 | |||
| 275 | Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245 | ||
| 276 | |||
| 277 | Signed-off-by: Stefan Metzmacher <metze@samba.org> | ||
| 278 | Reviewed-by: Jeremy Allison <jra@samba.org> | ||
| 279 | Signed-off-by: Andrew Bartlett <abartlet@samba.org> | ||
| 280 | Reviewed-by: Andreas Schneider <asn@samba.org> | ||
| 281 | --- | ||
| 282 | source3/auth/check_samsec.c | 1 + | ||
| 283 | 1 file changed, 1 insertion(+) | ||
| 284 | |||
| 285 | diff --git a/source3/auth/check_samsec.c b/source3/auth/check_samsec.c | ||
| 286 | index f918dc0..e2c42d6 100644 | ||
| 287 | --- a/source3/auth/check_samsec.c | ||
| 288 | +++ b/source3/auth/check_samsec.c | ||
| 289 | @@ -408,6 +408,7 @@ NTSTATUS check_sam_security(const DATA_BLOB *challenge, | ||
| 290 | /* Quit if the account was locked out. */ | ||
| 291 | if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) { | ||
| 292 | DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", username)); | ||
| 293 | + TALLOC_FREE(sampass); | ||
| 294 | return NT_STATUS_ACCOUNT_LOCKED_OUT; | ||
| 295 | } | ||
| 296 | |||
| 297 | -- | ||
| 298 | 1.7.9.5 | ||
| 299 | |||
| 300 | |||
| 301 | From 27f982ef33a1238ae48d7a38d608dd23ebde61ae Mon Sep 17 00:00:00 2001 | ||
| 302 | From: Andrew Bartlett <abartlet@samba.org> | ||
| 303 | Date: Tue, 5 Nov 2013 16:16:46 +1300 | ||
| 304 | Subject: [PATCH 3/3] CVE-2013-4496:samr: Remove ChangePasswordUser | ||
| 305 | |||
| 306 | This old password change mechanism does not provide the plaintext to | ||
| 307 | validate against password complexity, and it is not used by modern | ||
| 308 | clients. | ||
| 309 | |||
| 310 | The missing features in both implementations (by design) were: | ||
| 311 | |||
| 312 | - the password complexity checks (no plaintext) | ||
| 313 | - the minimum password length (no plaintext) | ||
| 314 | |||
| 315 | Additionally, the source3 version did not check: | ||
| 316 | |||
| 317 | - the minimum password age | ||
| 318 | - pdb_get_pass_can_change() which checks the security | ||
| 319 | descriptor for the 'user cannot change password' setting. | ||
| 320 | - the password history | ||
| 321 | - the output of the 'passwd program' if 'unix passwd sync = yes'. | ||
| 322 | |||
| 323 | Finally, the mechanism was almost useless, as it was incorrectly | ||
| 324 | only made available to administrative users with permission | ||
| 325 | to reset the password. It is removed here so that it is not | ||
| 326 | mistakenly reinstated in the future. | ||
| 327 | |||
| 328 | Andrew Bartlett | ||
| 329 | |||
| 330 | Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245 | ||
| 331 | |||
| 332 | Signed-off-by: Andrew Bartlett <abartlet@samba.org> | ||
| 333 | Reviewed-by: Andreas Schneider <asn@samba.org> | ||
| 334 | Reviewed-by: Stefan Metzmacher <metze@samba.org> | ||
| 335 | --- | ||
| 336 | source3/rpc_server/samr/srv_samr_nt.c | 169 +------------------- | ||
| 337 | source3/smbd/lanman.c | 254 ------------------------------- | ||
| 338 | source4/rpc_server/samr/samr_password.c | 126 +-------------- | ||
| 339 | source4/torture/rpc/samr.c | 12 +- | ||
| 340 | 4 files changed, 24 insertions(+), 537 deletions(-) | ||
| 341 | |||
| 342 | diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c | ||
| 343 | index 3241b97..2519a3f 100644 | ||
| 344 | --- a/source3/rpc_server/samr/srv_samr_nt.c | ||
| 345 | +++ b/source3/rpc_server/samr/srv_samr_nt.c | ||
| 346 | @@ -1706,172 +1706,19 @@ NTSTATUS _samr_LookupNames(struct pipes_struct *p, | ||
| 347 | } | ||
| 348 | |||
| 349 | /**************************************************************** | ||
| 350 | - _samr_ChangePasswordUser | ||
| 351 | + _samr_ChangePasswordUser. | ||
| 352 | + | ||
| 353 | + So old it is just not worth implementing | ||
| 354 | + because it does not supply a plaintext and so we can't do password | ||
| 355 | + complexity checking and cannot update other services that use a | ||
| 356 | + plaintext password via passwd chat/pam password change/ldap password | ||
| 357 | + sync. | ||
| 358 | ****************************************************************/ | ||
| 359 | |||
| 360 | NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, | ||
| 361 | struct samr_ChangePasswordUser *r) | ||
| 362 | { | ||
| 363 | - NTSTATUS status; | ||
| 364 | - bool ret = false; | ||
| 365 | - struct samr_user_info *uinfo; | ||
| 366 | - struct samu *pwd = NULL; | ||
| 367 | - struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; | ||
| 368 | - struct samr_Password lm_pwd, nt_pwd; | ||
| 369 | - bool updated_badpw = false; | ||
| 370 | - NTSTATUS update_login_attempts_status; | ||
| 371 | - | ||
| 372 | - uinfo = policy_handle_find(p, r->in.user_handle, | ||
| 373 | - SAMR_USER_ACCESS_SET_PASSWORD, NULL, | ||
| 374 | - struct samr_user_info, &status); | ||
| 375 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 376 | - return status; | ||
| 377 | - } | ||
| 378 | - | ||
| 379 | - DEBUG(5,("_samr_ChangePasswordUser: sid:%s\n", | ||
| 380 | - sid_string_dbg(&uinfo->sid))); | ||
| 381 | - | ||
| 382 | - /* basic sanity checking on parameters. Do this before any database ops */ | ||
| 383 | - if (!r->in.lm_present || !r->in.nt_present || | ||
| 384 | - !r->in.old_lm_crypted || !r->in.new_lm_crypted || | ||
| 385 | - !r->in.old_nt_crypted || !r->in.new_nt_crypted) { | ||
| 386 | - /* we should really handle a change with lm not | ||
| 387 | - present */ | ||
| 388 | - return NT_STATUS_INVALID_PARAMETER_MIX; | ||
| 389 | - } | ||
| 390 | - | ||
| 391 | - if (!(pwd = samu_new(NULL))) { | ||
| 392 | - return NT_STATUS_NO_MEMORY; | ||
| 393 | - } | ||
| 394 | - | ||
| 395 | - become_root(); | ||
| 396 | - ret = pdb_getsampwsid(pwd, &uinfo->sid); | ||
| 397 | - unbecome_root(); | ||
| 398 | - | ||
| 399 | - if (!ret) { | ||
| 400 | - TALLOC_FREE(pwd); | ||
| 401 | - return NT_STATUS_WRONG_PASSWORD; | ||
| 402 | - } | ||
| 403 | - | ||
| 404 | - /* Quit if the account was locked out. */ | ||
| 405 | - if (pdb_get_acct_ctrl(pwd) & ACB_AUTOLOCK) { | ||
| 406 | - DEBUG(3, ("Account for user %s was locked out.\n", | ||
| 407 | - pdb_get_username(pwd))); | ||
| 408 | - status = NT_STATUS_ACCOUNT_LOCKED_OUT; | ||
| 409 | - goto out; | ||
| 410 | - } | ||
| 411 | - | ||
| 412 | - { | ||
| 413 | - const uint8_t *lm_pass, *nt_pass; | ||
| 414 | - | ||
| 415 | - lm_pass = pdb_get_lanman_passwd(pwd); | ||
| 416 | - nt_pass = pdb_get_nt_passwd(pwd); | ||
| 417 | - | ||
| 418 | - if (!lm_pass || !nt_pass) { | ||
| 419 | - status = NT_STATUS_WRONG_PASSWORD; | ||
| 420 | - goto update_login; | ||
| 421 | - } | ||
| 422 | - | ||
| 423 | - memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash)); | ||
| 424 | - memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash)); | ||
| 425 | - } | ||
| 426 | - | ||
| 427 | - /* decrypt and check the new lm hash */ | ||
| 428 | - D_P16(lm_pwd.hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash); | ||
| 429 | - D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash); | ||
| 430 | - if (memcmp(checkHash.hash, lm_pwd.hash, 16) != 0) { | ||
| 431 | - status = NT_STATUS_WRONG_PASSWORD; | ||
| 432 | - goto update_login; | ||
| 433 | - } | ||
| 434 | - | ||
| 435 | - /* decrypt and check the new nt hash */ | ||
| 436 | - D_P16(nt_pwd.hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash); | ||
| 437 | - D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash); | ||
| 438 | - if (memcmp(checkHash.hash, nt_pwd.hash, 16) != 0) { | ||
| 439 | - status = NT_STATUS_WRONG_PASSWORD; | ||
| 440 | - goto update_login; | ||
| 441 | - } | ||
| 442 | - | ||
| 443 | - /* The NT Cross is not required by Win2k3 R2, but if present | ||
| 444 | - check the nt cross hash */ | ||
| 445 | - if (r->in.cross1_present && r->in.nt_cross) { | ||
| 446 | - D_P16(lm_pwd.hash, r->in.nt_cross->hash, checkHash.hash); | ||
| 447 | - if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) { | ||
| 448 | - status = NT_STATUS_WRONG_PASSWORD; | ||
| 449 | - goto update_login; | ||
| 450 | - } | ||
| 451 | - } | ||
| 452 | - | ||
| 453 | - /* The LM Cross is not required by Win2k3 R2, but if present | ||
| 454 | - check the lm cross hash */ | ||
| 455 | - if (r->in.cross2_present && r->in.lm_cross) { | ||
| 456 | - D_P16(nt_pwd.hash, r->in.lm_cross->hash, checkHash.hash); | ||
| 457 | - if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) { | ||
| 458 | - status = NT_STATUS_WRONG_PASSWORD; | ||
| 459 | - goto update_login; | ||
| 460 | - } | ||
| 461 | - } | ||
| 462 | - | ||
| 463 | - if (!pdb_set_nt_passwd(pwd, new_ntPwdHash.hash, PDB_CHANGED) || | ||
| 464 | - !pdb_set_lanman_passwd(pwd, new_lmPwdHash.hash, PDB_CHANGED)) { | ||
| 465 | - status = NT_STATUS_ACCESS_DENIED; | ||
| 466 | - goto out; | ||
| 467 | - } | ||
| 468 | - | ||
| 469 | - status = pdb_update_sam_account(pwd); | ||
| 470 | - | ||
| 471 | -update_login: | ||
| 472 | - | ||
| 473 | - /* | ||
| 474 | - * Notify passdb backend of login success/failure. If not | ||
| 475 | - * NT_STATUS_OK the backend doesn't like the login | ||
| 476 | - */ | ||
| 477 | - update_login_attempts_status = pdb_update_login_attempts(pwd, | ||
| 478 | - NT_STATUS_IS_OK(status)); | ||
| 479 | - | ||
| 480 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 481 | - bool increment_bad_pw_count = false; | ||
| 482 | - | ||
| 483 | - if (NT_STATUS_EQUAL(status,NT_STATUS_WRONG_PASSWORD) && | ||
| 484 | - (pdb_get_acct_ctrl(pwd) & ACB_NORMAL) && | ||
| 485 | - NT_STATUS_IS_OK(update_login_attempts_status)) | ||
| 486 | - { | ||
| 487 | - increment_bad_pw_count = true; | ||
| 488 | - } | ||
| 489 | - | ||
| 490 | - if (increment_bad_pw_count) { | ||
| 491 | - pdb_increment_bad_password_count(pwd); | ||
| 492 | - updated_badpw = true; | ||
| 493 | - } else { | ||
| 494 | - pdb_update_bad_password_count(pwd, | ||
| 495 | - &updated_badpw); | ||
| 496 | - } | ||
| 497 | - } else { | ||
| 498 | - | ||
| 499 | - if ((pdb_get_acct_ctrl(pwd) & ACB_NORMAL) && | ||
| 500 | - (pdb_get_bad_password_count(pwd) > 0)){ | ||
| 501 | - pdb_set_bad_password_count(pwd, 0, PDB_CHANGED); | ||
| 502 | - pdb_set_bad_password_time(pwd, 0, PDB_CHANGED); | ||
| 503 | - updated_badpw = true; | ||
| 504 | - } | ||
| 505 | - } | ||
| 506 | - | ||
| 507 | - if (updated_badpw) { | ||
| 508 | - NTSTATUS update_status; | ||
| 509 | - become_root(); | ||
| 510 | - update_status = pdb_update_sam_account(pwd); | ||
| 511 | - unbecome_root(); | ||
| 512 | - | ||
| 513 | - if (!NT_STATUS_IS_OK(update_status)) { | ||
| 514 | - DEBUG(1, ("Failed to modify entry: %s\n", | ||
| 515 | - nt_errstr(update_status))); | ||
| 516 | - } | ||
| 517 | - } | ||
| 518 | - | ||
| 519 | - out: | ||
| 520 | - TALLOC_FREE(pwd); | ||
| 521 | - | ||
| 522 | - return status; | ||
| 523 | + return NT_STATUS_NOT_IMPLEMENTED; | ||
| 524 | } | ||
| 525 | |||
| 526 | /******************************************************************* | ||
| 527 | diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c | ||
| 528 | index aef12df..3b4ec65 100644 | ||
| 529 | --- a/source3/smbd/lanman.c | ||
| 530 | +++ b/source3/smbd/lanman.c | ||
| 531 | @@ -2947,259 +2947,6 @@ static bool api_NetRemoteTOD(struct smbd_server_connection *sconn, | ||
| 532 | } | ||
| 533 | |||
| 534 | /**************************************************************************** | ||
| 535 | - Set the user password. | ||
| 536 | -*****************************************************************************/ | ||
| 537 | - | ||
| 538 | -static bool api_SetUserPassword(struct smbd_server_connection *sconn, | ||
| 539 | - connection_struct *conn,uint16 vuid, | ||
| 540 | - char *param, int tpscnt, | ||
| 541 | - char *data, int tdscnt, | ||
| 542 | - int mdrcnt,int mprcnt, | ||
| 543 | - char **rdata,char **rparam, | ||
| 544 | - int *rdata_len,int *rparam_len) | ||
| 545 | -{ | ||
| 546 | - char *np = get_safe_str_ptr(param,tpscnt,param,2); | ||
| 547 | - char *p = NULL; | ||
| 548 | - fstring user; | ||
| 549 | - fstring pass1,pass2; | ||
| 550 | - TALLOC_CTX *mem_ctx = talloc_tos(); | ||
| 551 | - NTSTATUS status, result; | ||
| 552 | - struct rpc_pipe_client *cli = NULL; | ||
| 553 | - struct policy_handle connect_handle, domain_handle, user_handle; | ||
| 554 | - struct lsa_String domain_name; | ||
| 555 | - struct dom_sid2 *domain_sid; | ||
| 556 | - struct lsa_String names; | ||
| 557 | - struct samr_Ids rids; | ||
| 558 | - struct samr_Ids types; | ||
| 559 | - struct samr_Password old_lm_hash; | ||
| 560 | - struct samr_Password new_lm_hash; | ||
| 561 | - int errcode = NERR_badpass; | ||
| 562 | - uint32_t rid; | ||
| 563 | - int encrypted; | ||
| 564 | - int min_pwd_length; | ||
| 565 | - struct dcerpc_binding_handle *b = NULL; | ||
| 566 | - | ||
| 567 | - /* Skip 2 strings. */ | ||
| 568 | - p = skip_string(param,tpscnt,np); | ||
| 569 | - p = skip_string(param,tpscnt,p); | ||
| 570 | - | ||
| 571 | - if (!np || !p) { | ||
| 572 | - return False; | ||
| 573 | - } | ||
| 574 | - | ||
| 575 | - /* Do we have a string ? */ | ||
| 576 | - if (skip_string(param,tpscnt,p) == NULL) { | ||
| 577 | - return False; | ||
| 578 | - } | ||
| 579 | - pull_ascii_fstring(user,p); | ||
| 580 | - | ||
| 581 | - p = skip_string(param,tpscnt,p); | ||
| 582 | - if (!p) { | ||
| 583 | - return False; | ||
| 584 | - } | ||
| 585 | - | ||
| 586 | - memset(pass1,'\0',sizeof(pass1)); | ||
| 587 | - memset(pass2,'\0',sizeof(pass2)); | ||
| 588 | - /* | ||
| 589 | - * We use 31 here not 32 as we're checking | ||
| 590 | - * the last byte we want to access is safe. | ||
| 591 | - */ | ||
| 592 | - if (!is_offset_safe(param,tpscnt,p,31)) { | ||
| 593 | - return False; | ||
| 594 | - } | ||
| 595 | - memcpy(pass1,p,16); | ||
| 596 | - memcpy(pass2,p+16,16); | ||
| 597 | - | ||
| 598 | - encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1); | ||
| 599 | - if (encrypted == -1) { | ||
| 600 | - errcode = W_ERROR_V(WERR_INVALID_PARAM); | ||
| 601 | - goto out; | ||
| 602 | - } | ||
| 603 | - | ||
| 604 | - min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1); | ||
| 605 | - if (min_pwd_length == -1) { | ||
| 606 | - errcode = W_ERROR_V(WERR_INVALID_PARAM); | ||
| 607 | - goto out; | ||
| 608 | - } | ||
| 609 | - | ||
| 610 | - *rparam_len = 4; | ||
| 611 | - *rparam = smb_realloc_limit(*rparam,*rparam_len); | ||
| 612 | - if (!*rparam) { | ||
| 613 | - return False; | ||
| 614 | - } | ||
| 615 | - | ||
| 616 | - *rdata_len = 0; | ||
| 617 | - | ||
| 618 | - DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n", | ||
| 619 | - user, encrypted, min_pwd_length)); | ||
| 620 | - | ||
| 621 | - ZERO_STRUCT(connect_handle); | ||
| 622 | - ZERO_STRUCT(domain_handle); | ||
| 623 | - ZERO_STRUCT(user_handle); | ||
| 624 | - | ||
| 625 | - status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, | ||
| 626 | - conn->session_info, | ||
| 627 | - &conn->sconn->client_id, | ||
| 628 | - conn->sconn->msg_ctx, | ||
| 629 | - &cli); | ||
| 630 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 631 | - DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n", | ||
| 632 | - nt_errstr(status))); | ||
| 633 | - errcode = W_ERROR_V(ntstatus_to_werror(status)); | ||
| 634 | - goto out; | ||
| 635 | - } | ||
| 636 | - | ||
| 637 | - b = cli->binding_handle; | ||
| 638 | - | ||
| 639 | - status = dcerpc_samr_Connect2(b, mem_ctx, | ||
| 640 | - global_myname(), | ||
| 641 | - SAMR_ACCESS_CONNECT_TO_SERVER | | ||
| 642 | - SAMR_ACCESS_ENUM_DOMAINS | | ||
| 643 | - SAMR_ACCESS_LOOKUP_DOMAIN, | ||
| 644 | - &connect_handle, | ||
| 645 | - &result); | ||
| 646 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 647 | - errcode = W_ERROR_V(ntstatus_to_werror(status)); | ||
| 648 | - goto out; | ||
| 649 | - } | ||
| 650 | - if (!NT_STATUS_IS_OK(result)) { | ||
| 651 | - errcode = W_ERROR_V(ntstatus_to_werror(result)); | ||
| 652 | - goto out; | ||
| 653 | - } | ||
| 654 | - | ||
| 655 | - init_lsa_String(&domain_name, get_global_sam_name()); | ||
| 656 | - | ||
| 657 | - status = dcerpc_samr_LookupDomain(b, mem_ctx, | ||
| 658 | - &connect_handle, | ||
| 659 | - &domain_name, | ||
| 660 | - &domain_sid, | ||
| 661 | - &result); | ||
| 662 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 663 | - errcode = W_ERROR_V(ntstatus_to_werror(status)); | ||
| 664 | - goto out; | ||
| 665 | - } | ||
| 666 | - if (!NT_STATUS_IS_OK(result)) { | ||
| 667 | - errcode = W_ERROR_V(ntstatus_to_werror(result)); | ||
| 668 | - goto out; | ||
| 669 | - } | ||
| 670 | - | ||
| 671 | - status = dcerpc_samr_OpenDomain(b, mem_ctx, | ||
| 672 | - &connect_handle, | ||
| 673 | - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, | ||
| 674 | - domain_sid, | ||
| 675 | - &domain_handle, | ||
| 676 | - &result); | ||
| 677 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 678 | - errcode = W_ERROR_V(ntstatus_to_werror(status)); | ||
| 679 | - goto out; | ||
| 680 | - } | ||
| 681 | - if (!NT_STATUS_IS_OK(result)) { | ||
| 682 | - errcode = W_ERROR_V(ntstatus_to_werror(result)); | ||
| 683 | - goto out; | ||
| 684 | - } | ||
| 685 | - | ||
| 686 | - init_lsa_String(&names, user); | ||
| 687 | - | ||
| 688 | - status = dcerpc_samr_LookupNames(b, mem_ctx, | ||
| 689 | - &domain_handle, | ||
| 690 | - 1, | ||
| 691 | - &names, | ||
| 692 | - &rids, | ||
| 693 | - &types, | ||
| 694 | - &result); | ||
| 695 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 696 | - errcode = W_ERROR_V(ntstatus_to_werror(status)); | ||
| 697 | - goto out; | ||
| 698 | - } | ||
| 699 | - if (!NT_STATUS_IS_OK(result)) { | ||
| 700 | - errcode = W_ERROR_V(ntstatus_to_werror(result)); | ||
| 701 | - goto out; | ||
| 702 | - } | ||
| 703 | - | ||
| 704 | - if (rids.count != 1) { | ||
| 705 | - errcode = W_ERROR_V(WERR_NO_SUCH_USER); | ||
| 706 | - goto out; | ||
| 707 | - } | ||
| 708 | - if (rids.count != types.count) { | ||
| 709 | - errcode = W_ERROR_V(WERR_INVALID_PARAM); | ||
| 710 | - goto out; | ||
| 711 | - } | ||
| 712 | - if (types.ids[0] != SID_NAME_USER) { | ||
| 713 | - errcode = W_ERROR_V(WERR_INVALID_PARAM); | ||
| 714 | - goto out; | ||
| 715 | - } | ||
| 716 | - | ||
| 717 | - rid = rids.ids[0]; | ||
| 718 | - | ||
| 719 | - status = dcerpc_samr_OpenUser(b, mem_ctx, | ||
| 720 | - &domain_handle, | ||
| 721 | - SAMR_USER_ACCESS_CHANGE_PASSWORD, | ||
| 722 | - rid, | ||
| 723 | - &user_handle, | ||
| 724 | - &result); | ||
| 725 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 726 | - errcode = W_ERROR_V(ntstatus_to_werror(status)); | ||
| 727 | - goto out; | ||
| 728 | - } | ||
| 729 | - if (!NT_STATUS_IS_OK(result)) { | ||
| 730 | - errcode = W_ERROR_V(ntstatus_to_werror(result)); | ||
| 731 | - goto out; | ||
| 732 | - } | ||
| 733 | - | ||
| 734 | - if (encrypted == 0) { | ||
| 735 | - E_deshash(pass1, old_lm_hash.hash); | ||
| 736 | - E_deshash(pass2, new_lm_hash.hash); | ||
| 737 | - } else { | ||
| 738 | - ZERO_STRUCT(old_lm_hash); | ||
| 739 | - ZERO_STRUCT(new_lm_hash); | ||
| 740 | - memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16)); | ||
| 741 | - memcpy(new_lm_hash.hash, pass1, MIN(strlen(pass2), 16)); | ||
| 742 | - } | ||
| 743 | - | ||
| 744 | - status = dcerpc_samr_ChangePasswordUser(b, mem_ctx, | ||
| 745 | - &user_handle, | ||
| 746 | - true, /* lm_present */ | ||
| 747 | - &old_lm_hash, | ||
| 748 | - &new_lm_hash, | ||
| 749 | - false, /* nt_present */ | ||
| 750 | - NULL, /* old_nt_crypted */ | ||
| 751 | - NULL, /* new_nt_crypted */ | ||
| 752 | - false, /* cross1_present */ | ||
| 753 | - NULL, /* nt_cross */ | ||
| 754 | - false, /* cross2_present */ | ||
| 755 | - NULL, /* lm_cross */ | ||
| 756 | - &result); | ||
| 757 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 758 | - errcode = W_ERROR_V(ntstatus_to_werror(status)); | ||
| 759 | - goto out; | ||
| 760 | - } | ||
| 761 | - if (!NT_STATUS_IS_OK(result)) { | ||
| 762 | - errcode = W_ERROR_V(ntstatus_to_werror(result)); | ||
| 763 | - goto out; | ||
| 764 | - } | ||
| 765 | - | ||
| 766 | - errcode = NERR_Success; | ||
| 767 | - out: | ||
| 768 | - | ||
| 769 | - if (b && is_valid_policy_hnd(&user_handle)) { | ||
| 770 | - dcerpc_samr_Close(b, mem_ctx, &user_handle, &result); | ||
| 771 | - } | ||
| 772 | - if (b && is_valid_policy_hnd(&domain_handle)) { | ||
| 773 | - dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result); | ||
| 774 | - } | ||
| 775 | - if (b && is_valid_policy_hnd(&connect_handle)) { | ||
| 776 | - dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result); | ||
| 777 | - } | ||
| 778 | - | ||
| 779 | - memset((char *)pass1,'\0',sizeof(fstring)); | ||
| 780 | - memset((char *)pass2,'\0',sizeof(fstring)); | ||
| 781 | - | ||
| 782 | - SSVAL(*rparam,0,errcode); | ||
| 783 | - SSVAL(*rparam,2,0); /* converter word */ | ||
| 784 | - return(True); | ||
| 785 | -} | ||
| 786 | - | ||
| 787 | -/**************************************************************************** | ||
| 788 | Set the user password (SamOEM version - gets plaintext). | ||
| 789 | ****************************************************************************/ | ||
| 790 | |||
| 791 | @@ -5790,7 +5537,6 @@ static const struct { | ||
| 792 | {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */ | ||
| 793 | {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */ | ||
| 794 | {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms}, | ||
| 795 | - {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword}, | ||
| 796 | {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon}, | ||
| 797 | {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo}, | ||
| 798 | {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum}, | ||
| 799 | diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c | ||
| 800 | index ee13a11..e618740 100644 | ||
| 801 | --- a/source4/rpc_server/samr/samr_password.c | ||
| 802 | +++ b/source4/rpc_server/samr/samr_password.c | ||
| 803 | @@ -32,131 +32,17 @@ | ||
| 804 | |||
| 805 | /* | ||
| 806 | samr_ChangePasswordUser | ||
| 807 | + | ||
| 808 | + So old it is just not worth implementing | ||
| 809 | + because it does not supply a plaintext and so we can't do password | ||
| 810 | + complexity checking and cannot update all the other password hashes. | ||
| 811 | + | ||
| 812 | */ | ||
| 813 | NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, | ||
| 814 | TALLOC_CTX *mem_ctx, | ||
| 815 | struct samr_ChangePasswordUser *r) | ||
| 816 | { | ||
| 817 | - struct dcesrv_handle *h; | ||
| 818 | - struct samr_account_state *a_state; | ||
| 819 | - struct ldb_context *sam_ctx; | ||
| 820 | - struct ldb_message **res; | ||
| 821 | - int ret; | ||
| 822 | - struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; | ||
| 823 | - struct samr_Password *lm_pwd, *nt_pwd; | ||
| 824 | - NTSTATUS status = NT_STATUS_OK; | ||
| 825 | - const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL }; | ||
| 826 | - | ||
| 827 | - DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER); | ||
| 828 | - | ||
| 829 | - a_state = h->data; | ||
| 830 | - | ||
| 831 | - /* basic sanity checking on parameters. Do this before any database ops */ | ||
| 832 | - if (!r->in.lm_present || !r->in.nt_present || | ||
| 833 | - !r->in.old_lm_crypted || !r->in.new_lm_crypted || | ||
| 834 | - !r->in.old_nt_crypted || !r->in.new_nt_crypted) { | ||
| 835 | - /* we should really handle a change with lm not | ||
| 836 | - present */ | ||
| 837 | - return NT_STATUS_INVALID_PARAMETER_MIX; | ||
| 838 | - } | ||
| 839 | - | ||
| 840 | - /* Connect to a SAMDB with system privileges for fetching the old pw | ||
| 841 | - * hashes. */ | ||
| 842 | - sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, | ||
| 843 | - dce_call->conn->dce_ctx->lp_ctx, | ||
| 844 | - system_session(dce_call->conn->dce_ctx->lp_ctx), 0); | ||
| 845 | - if (sam_ctx == NULL) { | ||
| 846 | - return NT_STATUS_INVALID_SYSTEM_SERVICE; | ||
| 847 | - } | ||
| 848 | - | ||
| 849 | - /* fetch the old hashes */ | ||
| 850 | - ret = gendb_search_dn(sam_ctx, mem_ctx, | ||
| 851 | - a_state->account_dn, &res, attrs); | ||
| 852 | - if (ret != 1) { | ||
| 853 | - return NT_STATUS_WRONG_PASSWORD; | ||
| 854 | - } | ||
| 855 | - | ||
| 856 | - status = samdb_result_passwords(mem_ctx, | ||
| 857 | - dce_call->conn->dce_ctx->lp_ctx, | ||
| 858 | - res[0], &lm_pwd, &nt_pwd); | ||
| 859 | - if (!NT_STATUS_IS_OK(status) || !nt_pwd) { | ||
| 860 | - return NT_STATUS_WRONG_PASSWORD; | ||
| 861 | - } | ||
| 862 | - | ||
| 863 | - /* decrypt and check the new lm hash */ | ||
| 864 | - if (lm_pwd) { | ||
| 865 | - D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash); | ||
| 866 | - D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash); | ||
| 867 | - if (memcmp(checkHash.hash, lm_pwd, 16) != 0) { | ||
| 868 | - return NT_STATUS_WRONG_PASSWORD; | ||
| 869 | - } | ||
| 870 | - } | ||
| 871 | - | ||
| 872 | - /* decrypt and check the new nt hash */ | ||
| 873 | - D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash); | ||
| 874 | - D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash); | ||
| 875 | - if (memcmp(checkHash.hash, nt_pwd, 16) != 0) { | ||
| 876 | - return NT_STATUS_WRONG_PASSWORD; | ||
| 877 | - } | ||
| 878 | - | ||
| 879 | - /* The NT Cross is not required by Win2k3 R2, but if present | ||
| 880 | - check the nt cross hash */ | ||
| 881 | - if (r->in.cross1_present && r->in.nt_cross && lm_pwd) { | ||
| 882 | - D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash); | ||
| 883 | - if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) { | ||
| 884 | - return NT_STATUS_WRONG_PASSWORD; | ||
| 885 | - } | ||
| 886 | - } | ||
| 887 | - | ||
| 888 | - /* The LM Cross is not required by Win2k3 R2, but if present | ||
| 889 | - check the lm cross hash */ | ||
| 890 | - if (r->in.cross2_present && r->in.lm_cross && lm_pwd) { | ||
| 891 | - D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash); | ||
| 892 | - if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) { | ||
| 893 | - return NT_STATUS_WRONG_PASSWORD; | ||
| 894 | - } | ||
| 895 | - } | ||
| 896 | - | ||
| 897 | - /* Start a SAM with user privileges for the password change */ | ||
| 898 | - sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, | ||
| 899 | - dce_call->conn->dce_ctx->lp_ctx, | ||
| 900 | - dce_call->conn->auth_state.session_info, 0); | ||
| 901 | - if (sam_ctx == NULL) { | ||
| 902 | - return NT_STATUS_INVALID_SYSTEM_SERVICE; | ||
| 903 | - } | ||
| 904 | - | ||
| 905 | - /* Start transaction */ | ||
| 906 | - ret = ldb_transaction_start(sam_ctx); | ||
| 907 | - if (ret != LDB_SUCCESS) { | ||
| 908 | - DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); | ||
| 909 | - return NT_STATUS_TRANSACTION_ABORTED; | ||
| 910 | - } | ||
| 911 | - | ||
| 912 | - /* Performs the password modification. We pass the old hashes read out | ||
| 913 | - * from the database since they were already checked against the user- | ||
| 914 | - * provided ones. */ | ||
| 915 | - status = samdb_set_password(sam_ctx, mem_ctx, | ||
| 916 | - a_state->account_dn, | ||
| 917 | - a_state->domain_state->domain_dn, | ||
| 918 | - NULL, &new_lmPwdHash, &new_ntPwdHash, | ||
| 919 | - lm_pwd, nt_pwd, /* this is a user password change */ | ||
| 920 | - NULL, | ||
| 921 | - NULL); | ||
| 922 | - if (!NT_STATUS_IS_OK(status)) { | ||
| 923 | - ldb_transaction_cancel(sam_ctx); | ||
| 924 | - return status; | ||
| 925 | - } | ||
| 926 | - | ||
| 927 | - /* And this confirms it in a transaction commit */ | ||
| 928 | - ret = ldb_transaction_commit(sam_ctx); | ||
| 929 | - if (ret != LDB_SUCCESS) { | ||
| 930 | - DEBUG(1,("Failed to commit transaction to change password on %s: %s\n", | ||
| 931 | - ldb_dn_get_linearized(a_state->account_dn), | ||
| 932 | - ldb_errstring(sam_ctx))); | ||
| 933 | - return NT_STATUS_TRANSACTION_ABORTED; | ||
| 934 | - } | ||
| 935 | - | ||
| 936 | - return NT_STATUS_OK; | ||
| 937 | + return NT_STATUS_NOT_IMPLEMENTED; | ||
| 938 | } | ||
| 939 | |||
| 940 | /* | ||
| 941 | diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c | ||
| 942 | index 7d9a1e2..adfc5d4 100644 | ||
| 943 | --- a/source4/torture/rpc/samr.c | ||
| 944 | +++ b/source4/torture/rpc/samr.c | ||
| 945 | @@ -1728,8 +1728,16 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b, | ||
| 946 | |||
| 947 | torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r), | ||
| 948 | "ChangePasswordUser failed"); | ||
| 949 | - torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD, | ||
| 950 | - "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash"); | ||
| 951 | + | ||
| 952 | + /* Do not proceed if this call has been removed */ | ||
| 953 | + if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) { | ||
| 954 | + return true; | ||
| 955 | + } | ||
| 956 | + | ||
| 957 | + if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) { | ||
| 958 | + torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD, | ||
| 959 | + "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash"); | ||
| 960 | + } | ||
| 961 | |||
| 962 | /* Unbreak the LM hash */ | ||
| 963 | hash1.hash[0]--; | ||
| 964 | -- | ||
| 965 | 1.7.9.5 | ||
| 966 | |||
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 20b609de5f..f80e41ed01 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 += "\ | |||
| 30 | file://configure-disable-getaddrinfo-cross.patch;patchdir=.. \ | 30 | file://configure-disable-getaddrinfo-cross.patch;patchdir=.. \ |
| 31 | file://configure-disable-core_pattern-cross-check.patch;patchdir=.. \ | 31 | file://configure-disable-core_pattern-cross-check.patch;patchdir=.. \ |
| 32 | file://configure-libunwind.patch;patchdir=.. \ | 32 | file://configure-libunwind.patch;patchdir=.. \ |
| 33 | file://samba-3.6.22-CVE-2013-4496.patch;patchdir=.. \ | ||
| 33 | " | 34 | " |
| 34 | SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be" | 35 | SRC_URI[md5sum] = "fbb245863eeef2fffe172df779a217be" |
| 35 | SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de" | 36 | SRC_URI[sha256sum] = "4f5a171a8d902c6b4f822ed875c51eb8339196d9ccf0ecd7f6521c966b3514de" |
