|
|
6729ff |
From c129261c506c6b941630fd7f4bc72820eb272761 Mon Sep 17 00:00:00 2001
|
|
|
6729ff |
From: Andrew Bartlett <abartlet@samba.org>
|
|
|
6729ff |
Date: Fri, 1 Nov 2013 14:55:44 +1300
|
|
|
6729ff |
Subject: [PATCH 1/4] CVE-2013-4496:s3-samr: Block attempts to crack passwords
|
|
|
6729ff |
via repeated password changes
|
|
|
6729ff |
|
|
|
6729ff |
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245
|
|
|
6729ff |
|
|
|
6729ff |
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
|
|
6729ff |
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
|
6729ff |
Signed-off-by: Jeremy Allison <jra@samba.org>
|
|
|
6729ff |
Reviewed-by: Stefan Metzmacher <metze@samba.org>
|
|
|
6729ff |
Reviewed-by: Jeremy Allison <jra@samba.org>
|
|
|
6729ff |
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
6729ff |
---
|
|
|
6729ff |
source3/rpc_server/samr/srv_samr_chgpasswd.c | 55 ++++++++++++++++
|
|
|
6729ff |
source3/rpc_server/samr/srv_samr_nt.c | 90 +++++++++++++++++++++-----
|
|
|
6729ff |
2 files changed, 129 insertions(+), 16 deletions(-)
|
|
|
6729ff |
|
|
|
6729ff |
diff --git a/source3/rpc_server/samr/srv_samr_chgpasswd.c b/source3/rpc_server/samr/srv_samr_chgpasswd.c
|
|
|
6729ff |
index db1f459..1c9c33a 100644
|
|
|
6729ff |
--- a/source3/rpc_server/samr/srv_samr_chgpasswd.c
|
|
|
6729ff |
+++ b/source3/rpc_server/samr/srv_samr_chgpasswd.c
|
|
|
6729ff |
@@ -1106,6 +1106,8 @@ NTSTATUS pass_oem_change(char *user, const char *rhost,
|
|
|
6729ff |
struct samu *sampass = NULL;
|
|
|
6729ff |
NTSTATUS nt_status;
|
|
|
6729ff |
bool ret = false;
|
|
|
6729ff |
+ bool updated_badpw = false;
|
|
|
6729ff |
+ NTSTATUS update_login_attempts_status;
|
|
|
6729ff |
|
|
|
6729ff |
if (!(sampass = samu_new(NULL))) {
|
|
|
6729ff |
return NT_STATUS_NO_MEMORY;
|
|
|
6729ff |
@@ -1121,6 +1123,13 @@ NTSTATUS pass_oem_change(char *user, const char *rhost,
|
|
|
6729ff |
return NT_STATUS_NO_SUCH_USER;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
+ /* Quit if the account was locked out. */
|
|
|
6729ff |
+ if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) {
|
|
|
6729ff |
+ DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", user));
|
|
|
6729ff |
+ TALLOC_FREE(sampass);
|
|
|
6729ff |
+ return NT_STATUS_ACCOUNT_LOCKED_OUT;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
nt_status = check_oem_password(user,
|
|
|
6729ff |
password_encrypted_with_lm_hash,
|
|
|
6729ff |
old_lm_hash_encrypted,
|
|
|
6729ff |
@@ -1129,6 +1138,52 @@ NTSTATUS pass_oem_change(char *user, const char *rhost,
|
|
|
6729ff |
sampass,
|
|
|
6729ff |
&new_passwd);
|
|
|
6729ff |
|
|
|
6729ff |
+ /*
|
|
|
6729ff |
+ * Notify passdb backend of login success/failure. If not
|
|
|
6729ff |
+ * NT_STATUS_OK the backend doesn't like the login
|
|
|
6729ff |
+ */
|
|
|
6729ff |
+ update_login_attempts_status = pdb_update_login_attempts(sampass,
|
|
|
6729ff |
+ NT_STATUS_IS_OK(nt_status));
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (!NT_STATUS_IS_OK(nt_status)) {
|
|
|
6729ff |
+ bool increment_bad_pw_count = false;
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) &&
|
|
|
6729ff |
+ (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) &&
|
|
|
6729ff |
+ NT_STATUS_IS_OK(update_login_attempts_status))
|
|
|
6729ff |
+ {
|
|
|
6729ff |
+ increment_bad_pw_count = true;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (increment_bad_pw_count) {
|
|
|
6729ff |
+ pdb_increment_bad_password_count(sampass);
|
|
|
6729ff |
+ updated_badpw = true;
|
|
|
6729ff |
+ } else {
|
|
|
6729ff |
+ pdb_update_bad_password_count(sampass,
|
|
|
6729ff |
+ &updated_badpw);
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+ } else {
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) &&
|
|
|
6729ff |
+ (pdb_get_bad_password_count(sampass) > 0)){
|
|
|
6729ff |
+ pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
|
|
|
6729ff |
+ pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
|
|
|
6729ff |
+ updated_badpw = true;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (updated_badpw) {
|
|
|
6729ff |
+ NTSTATUS update_status;
|
|
|
6729ff |
+ become_root();
|
|
|
6729ff |
+ update_status = pdb_update_sam_account(sampass);
|
|
|
6729ff |
+ unbecome_root();
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (!NT_STATUS_IS_OK(update_status)) {
|
|
|
6729ff |
+ DEBUG(1, ("Failed to modify entry: %s\n",
|
|
|
6729ff |
+ nt_errstr(update_status)));
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
if (!NT_STATUS_IS_OK(nt_status)) {
|
|
|
6729ff |
TALLOC_FREE(sampass);
|
|
|
6729ff |
return nt_status;
|
|
|
6729ff |
diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
|
|
|
6729ff |
index b366eda..98e8bea 100644
|
|
|
6729ff |
--- a/source3/rpc_server/samr/srv_samr_nt.c
|
|
|
6729ff |
+++ b/source3/rpc_server/samr/srv_samr_nt.c
|
|
|
6729ff |
@@ -1722,9 +1722,11 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
|
|
|
6729ff |
NTSTATUS status;
|
|
|
6729ff |
bool ret = false;
|
|
|
6729ff |
struct samr_user_info *uinfo;
|
|
|
6729ff |
- struct samu *pwd;
|
|
|
6729ff |
+ struct samu *pwd = NULL;
|
|
|
6729ff |
struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
|
|
|
6729ff |
struct samr_Password lm_pwd, nt_pwd;
|
|
|
6729ff |
+ bool updated_badpw = false;
|
|
|
6729ff |
+ NTSTATUS update_login_attempts_status;
|
|
|
6729ff |
|
|
|
6729ff |
uinfo = policy_handle_find(p, r->in.user_handle,
|
|
|
6729ff |
SAMR_USER_ACCESS_SET_PASSWORD, NULL,
|
|
|
6729ff |
@@ -1736,6 +1738,15 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
|
|
|
6729ff |
DEBUG(5,("_samr_ChangePasswordUser: sid:%s\n",
|
|
|
6729ff |
sid_string_dbg(&uinfo->sid)));
|
|
|
6729ff |
|
|
|
6729ff |
+ /* basic sanity checking on parameters. Do this before any database ops */
|
|
|
6729ff |
+ if (!r->in.lm_present || !r->in.nt_present ||
|
|
|
6729ff |
+ !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
|
|
|
6729ff |
+ !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
|
|
|
6729ff |
+ /* we should really handle a change with lm not
|
|
|
6729ff |
+ present */
|
|
|
6729ff |
+ return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
if (!(pwd = samu_new(NULL))) {
|
|
|
6729ff |
return NT_STATUS_NO_MEMORY;
|
|
|
6729ff |
}
|
|
|
6729ff |
@@ -1749,6 +1760,14 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
|
|
|
6729ff |
return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
+ /* Quit if the account was locked out. */
|
|
|
6729ff |
+ if (pdb_get_acct_ctrl(pwd) & ACB_AUTOLOCK) {
|
|
|
6729ff |
+ DEBUG(3, ("Account for user %s was locked out.\n",
|
|
|
6729ff |
+ pdb_get_username(pwd)));
|
|
|
6729ff |
+ status = NT_STATUS_ACCOUNT_LOCKED_OUT;
|
|
|
6729ff |
+ goto out;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
{
|
|
|
6729ff |
const uint8_t *lm_pass, *nt_pass;
|
|
|
6729ff |
|
|
|
6729ff |
@@ -1757,29 +1776,19 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
|
|
|
6729ff |
|
|
|
6729ff |
if (!lm_pass || !nt_pass) {
|
|
|
6729ff |
status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
+ goto update_login;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash));
|
|
|
6729ff |
memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash));
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
- /* basic sanity checking on parameters. Do this before any database ops */
|
|
|
6729ff |
- if (!r->in.lm_present || !r->in.nt_present ||
|
|
|
6729ff |
- !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
|
|
|
6729ff |
- !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
|
|
|
6729ff |
- /* we should really handle a change with lm not
|
|
|
6729ff |
- present */
|
|
|
6729ff |
- status = NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
/* decrypt and check the new lm hash */
|
|
|
6729ff |
D_P16(lm_pwd.hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
|
|
|
6729ff |
D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
|
|
|
6729ff |
if (memcmp(checkHash.hash, lm_pwd.hash, 16) != 0) {
|
|
|
6729ff |
status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
+ goto update_login;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
/* decrypt and check the new nt hash */
|
|
|
6729ff |
@@ -1787,7 +1796,7 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
|
|
|
6729ff |
D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
|
|
|
6729ff |
if (memcmp(checkHash.hash, nt_pwd.hash, 16) != 0) {
|
|
|
6729ff |
status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
+ goto update_login;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
/* The NT Cross is not required by Win2k3 R2, but if present
|
|
|
6729ff |
@@ -1796,7 +1805,7 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
|
|
|
6729ff |
D_P16(lm_pwd.hash, r->in.nt_cross->hash, checkHash.hash);
|
|
|
6729ff |
if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
|
|
|
6729ff |
status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
+ goto update_login;
|
|
|
6729ff |
}
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
@@ -1806,7 +1815,7 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
|
|
|
6729ff |
D_P16(nt_pwd.hash, r->in.lm_cross->hash, checkHash.hash);
|
|
|
6729ff |
if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
|
|
|
6729ff |
status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
+ goto update_login;
|
|
|
6729ff |
}
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
@@ -1817,6 +1826,55 @@ NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
status = pdb_update_sam_account(pwd);
|
|
|
6729ff |
+
|
|
|
6729ff |
+update_login:
|
|
|
6729ff |
+
|
|
|
6729ff |
+ /*
|
|
|
6729ff |
+ * Notify passdb backend of login success/failure. If not
|
|
|
6729ff |
+ * NT_STATUS_OK the backend doesn't like the login
|
|
|
6729ff |
+ */
|
|
|
6729ff |
+ update_login_attempts_status = pdb_update_login_attempts(pwd,
|
|
|
6729ff |
+ NT_STATUS_IS_OK(status));
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
+ bool increment_bad_pw_count = false;
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (NT_STATUS_EQUAL(status,NT_STATUS_WRONG_PASSWORD) &&
|
|
|
6729ff |
+ (pdb_get_acct_ctrl(pwd) & ACB_NORMAL) &&
|
|
|
6729ff |
+ NT_STATUS_IS_OK(update_login_attempts_status))
|
|
|
6729ff |
+ {
|
|
|
6729ff |
+ increment_bad_pw_count = true;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (increment_bad_pw_count) {
|
|
|
6729ff |
+ pdb_increment_bad_password_count(pwd);
|
|
|
6729ff |
+ updated_badpw = true;
|
|
|
6729ff |
+ } else {
|
|
|
6729ff |
+ pdb_update_bad_password_count(pwd,
|
|
|
6729ff |
+ &updated_badpw);
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+ } else {
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if ((pdb_get_acct_ctrl(pwd) & ACB_NORMAL) &&
|
|
|
6729ff |
+ (pdb_get_bad_password_count(pwd) > 0)){
|
|
|
6729ff |
+ pdb_set_bad_password_count(pwd, 0, PDB_CHANGED);
|
|
|
6729ff |
+ pdb_set_bad_password_time(pwd, 0, PDB_CHANGED);
|
|
|
6729ff |
+ updated_badpw = true;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (updated_badpw) {
|
|
|
6729ff |
+ NTSTATUS update_status;
|
|
|
6729ff |
+ become_root();
|
|
|
6729ff |
+ update_status = pdb_update_sam_account(pwd);
|
|
|
6729ff |
+ unbecome_root();
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (!NT_STATUS_IS_OK(update_status)) {
|
|
|
6729ff |
+ DEBUG(1, ("Failed to modify entry: %s\n",
|
|
|
6729ff |
+ nt_errstr(update_status)));
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
out:
|
|
|
6729ff |
TALLOC_FREE(pwd);
|
|
|
6729ff |
|
|
|
6729ff |
--
|
|
|
6729ff |
1.7.9.5
|
|
|
6729ff |
|
|
|
6729ff |
|
|
|
6729ff |
From fab5ee090e2e4765441b82e17a6cbb98523f6943 Mon Sep 17 00:00:00 2001
|
|
|
6729ff |
From: Stefan Metzmacher <metze@samba.org>
|
|
|
6729ff |
Date: Tue, 5 Nov 2013 14:04:20 +0100
|
|
|
6729ff |
Subject: [PATCH 2/4] CVE-2013-4496:s3:auth: fix memory leak in the
|
|
|
6729ff |
ACCOUNT_LOCKED_OUT case.
|
|
|
6729ff |
|
|
|
6729ff |
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245
|
|
|
6729ff |
|
|
|
6729ff |
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
|
6729ff |
Reviewed-by: Jeremy Allison <jra@samba.org>
|
|
|
6729ff |
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
|
|
6729ff |
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
6729ff |
---
|
|
|
6729ff |
source3/auth/check_samsec.c | 1 +
|
|
|
6729ff |
1 file changed, 1 insertion(+)
|
|
|
6729ff |
|
|
|
6729ff |
diff --git a/source3/auth/check_samsec.c b/source3/auth/check_samsec.c
|
|
|
6729ff |
index 7ed8cc2..94f30b1 100644
|
|
|
6729ff |
--- a/source3/auth/check_samsec.c
|
|
|
6729ff |
+++ b/source3/auth/check_samsec.c
|
|
|
6729ff |
@@ -408,6 +408,7 @@ NTSTATUS check_sam_security(const DATA_BLOB *challenge,
|
|
|
6729ff |
/* Quit if the account was locked out. */
|
|
|
6729ff |
if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) {
|
|
|
6729ff |
DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", username));
|
|
|
6729ff |
+ TALLOC_FREE(sampass);
|
|
|
6729ff |
return NT_STATUS_ACCOUNT_LOCKED_OUT;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
--
|
|
|
6729ff |
1.7.9.5
|
|
|
6729ff |
|
|
|
6729ff |
|
|
|
6729ff |
From bf3443c12f2a67481eb2e45ca41b906c438d06da Mon Sep 17 00:00:00 2001
|
|
|
6729ff |
From: Andrew Bartlett <abartlet@samba.org>
|
|
|
6729ff |
Date: Tue, 5 Nov 2013 16:16:46 +1300
|
|
|
6729ff |
Subject: [PATCH 3/4] CVE-2013-4496:samr: Remove ChangePasswordUser
|
|
|
6729ff |
|
|
|
6729ff |
This old password change mechanism does not provide the plaintext to
|
|
|
6729ff |
validate against password complexity, and it is not used by modern
|
|
|
6729ff |
clients.
|
|
|
6729ff |
|
|
|
6729ff |
The missing features in both implementations (by design) were:
|
|
|
6729ff |
|
|
|
6729ff |
- the password complexity checks (no plaintext)
|
|
|
6729ff |
- the minimum password length (no plaintext)
|
|
|
6729ff |
|
|
|
6729ff |
Additionally, the source3 version did not check:
|
|
|
6729ff |
|
|
|
6729ff |
- the minimum password age
|
|
|
6729ff |
- pdb_get_pass_can_change() which checks the security
|
|
|
6729ff |
descriptor for the 'user cannot change password' setting.
|
|
|
6729ff |
- the password history
|
|
|
6729ff |
- the output of the 'passwd program' if 'unix passwd sync = yes'.
|
|
|
6729ff |
|
|
|
6729ff |
Finally, the mechanism was almost useless, as it was incorrectly
|
|
|
6729ff |
only made available to administrative users with permission
|
|
|
6729ff |
to reset the password. It is removed here so that it is not
|
|
|
6729ff |
mistakenly reinstated in the future.
|
|
|
6729ff |
|
|
|
6729ff |
Andrew Bartlett
|
|
|
6729ff |
|
|
|
6729ff |
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245
|
|
|
6729ff |
|
|
|
6729ff |
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
|
|
6729ff |
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
6729ff |
Reviewed-by: Stefan Metzmacher <metze@samba.org>
|
|
|
6729ff |
---
|
|
|
6729ff |
source3/rpc_server/samr/srv_samr_nt.c | 169 +-------------------
|
|
|
6729ff |
source3/smbd/lanman.c | 254 -------------------------------
|
|
|
6729ff |
source4/rpc_server/samr/samr_password.c | 145 +-----------------
|
|
|
6729ff |
source4/torture/rpc/samr.c | 6 +
|
|
|
6729ff |
4 files changed, 20 insertions(+), 554 deletions(-)
|
|
|
6729ff |
|
|
|
6729ff |
diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
|
|
|
6729ff |
index 98e8bea..99f03ec 100644
|
|
|
6729ff |
--- a/source3/rpc_server/samr/srv_samr_nt.c
|
|
|
6729ff |
+++ b/source3/rpc_server/samr/srv_samr_nt.c
|
|
|
6729ff |
@@ -1713,172 +1713,19 @@ NTSTATUS _samr_LookupNames(struct pipes_struct *p,
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
/****************************************************************
|
|
|
6729ff |
- _samr_ChangePasswordUser
|
|
|
6729ff |
+ _samr_ChangePasswordUser.
|
|
|
6729ff |
+
|
|
|
6729ff |
+ So old it is just not worth implementing
|
|
|
6729ff |
+ because it does not supply a plaintext and so we can't do password
|
|
|
6729ff |
+ complexity checking and cannot update other services that use a
|
|
|
6729ff |
+ plaintext password via passwd chat/pam password change/ldap password
|
|
|
6729ff |
+ sync.
|
|
|
6729ff |
****************************************************************/
|
|
|
6729ff |
|
|
|
6729ff |
NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p,
|
|
|
6729ff |
struct samr_ChangePasswordUser *r)
|
|
|
6729ff |
{
|
|
|
6729ff |
- NTSTATUS status;
|
|
|
6729ff |
- bool ret = false;
|
|
|
6729ff |
- struct samr_user_info *uinfo;
|
|
|
6729ff |
- struct samu *pwd = NULL;
|
|
|
6729ff |
- struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
|
|
|
6729ff |
- struct samr_Password lm_pwd, nt_pwd;
|
|
|
6729ff |
- bool updated_badpw = false;
|
|
|
6729ff |
- NTSTATUS update_login_attempts_status;
|
|
|
6729ff |
-
|
|
|
6729ff |
- uinfo = policy_handle_find(p, r->in.user_handle,
|
|
|
6729ff |
- SAMR_USER_ACCESS_SET_PASSWORD, NULL,
|
|
|
6729ff |
- struct samr_user_info, &status);
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- return status;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- DEBUG(5,("_samr_ChangePasswordUser: sid:%s\n",
|
|
|
6729ff |
- sid_string_dbg(&uinfo->sid)));
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* basic sanity checking on parameters. Do this before any database ops */
|
|
|
6729ff |
- if (!r->in.lm_present || !r->in.nt_present ||
|
|
|
6729ff |
- !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
|
|
|
6729ff |
- !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
|
|
|
6729ff |
- /* we should really handle a change with lm not
|
|
|
6729ff |
- present */
|
|
|
6729ff |
- return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (!(pwd = samu_new(NULL))) {
|
|
|
6729ff |
- return NT_STATUS_NO_MEMORY;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- become_root();
|
|
|
6729ff |
- ret = pdb_getsampwsid(pwd, &uinfo->sid);
|
|
|
6729ff |
- unbecome_root();
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (!ret) {
|
|
|
6729ff |
- TALLOC_FREE(pwd);
|
|
|
6729ff |
- return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* Quit if the account was locked out. */
|
|
|
6729ff |
- if (pdb_get_acct_ctrl(pwd) & ACB_AUTOLOCK) {
|
|
|
6729ff |
- DEBUG(3, ("Account for user %s was locked out.\n",
|
|
|
6729ff |
- pdb_get_username(pwd)));
|
|
|
6729ff |
- status = NT_STATUS_ACCOUNT_LOCKED_OUT;
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- {
|
|
|
6729ff |
- const uint8_t *lm_pass, *nt_pass;
|
|
|
6729ff |
-
|
|
|
6729ff |
- lm_pass = pdb_get_lanman_passwd(pwd);
|
|
|
6729ff |
- nt_pass = pdb_get_nt_passwd(pwd);
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (!lm_pass || !nt_pass) {
|
|
|
6729ff |
- status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto update_login;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash));
|
|
|
6729ff |
- memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash));
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* decrypt and check the new lm hash */
|
|
|
6729ff |
- D_P16(lm_pwd.hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
|
|
|
6729ff |
- D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
|
|
|
6729ff |
- if (memcmp(checkHash.hash, lm_pwd.hash, 16) != 0) {
|
|
|
6729ff |
- status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto update_login;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* decrypt and check the new nt hash */
|
|
|
6729ff |
- D_P16(nt_pwd.hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
|
|
|
6729ff |
- D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
|
|
|
6729ff |
- if (memcmp(checkHash.hash, nt_pwd.hash, 16) != 0) {
|
|
|
6729ff |
- status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto update_login;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* The NT Cross is not required by Win2k3 R2, but if present
|
|
|
6729ff |
- check the nt cross hash */
|
|
|
6729ff |
- if (r->in.cross1_present && r->in.nt_cross) {
|
|
|
6729ff |
- D_P16(lm_pwd.hash, r->in.nt_cross->hash, checkHash.hash);
|
|
|
6729ff |
- if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
|
|
|
6729ff |
- status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto update_login;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* The LM Cross is not required by Win2k3 R2, but if present
|
|
|
6729ff |
- check the lm cross hash */
|
|
|
6729ff |
- if (r->in.cross2_present && r->in.lm_cross) {
|
|
|
6729ff |
- D_P16(nt_pwd.hash, r->in.lm_cross->hash, checkHash.hash);
|
|
|
6729ff |
- if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
|
|
|
6729ff |
- status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- goto update_login;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (!pdb_set_nt_passwd(pwd, new_ntPwdHash.hash, PDB_CHANGED) ||
|
|
|
6729ff |
- !pdb_set_lanman_passwd(pwd, new_lmPwdHash.hash, PDB_CHANGED)) {
|
|
|
6729ff |
- status = NT_STATUS_ACCESS_DENIED;
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- status = pdb_update_sam_account(pwd);
|
|
|
6729ff |
-
|
|
|
6729ff |
-update_login:
|
|
|
6729ff |
-
|
|
|
6729ff |
- /*
|
|
|
6729ff |
- * Notify passdb backend of login success/failure. If not
|
|
|
6729ff |
- * NT_STATUS_OK the backend doesn't like the login
|
|
|
6729ff |
- */
|
|
|
6729ff |
- update_login_attempts_status = pdb_update_login_attempts(pwd,
|
|
|
6729ff |
- NT_STATUS_IS_OK(status));
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- bool increment_bad_pw_count = false;
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (NT_STATUS_EQUAL(status,NT_STATUS_WRONG_PASSWORD) &&
|
|
|
6729ff |
- (pdb_get_acct_ctrl(pwd) & ACB_NORMAL) &&
|
|
|
6729ff |
- NT_STATUS_IS_OK(update_login_attempts_status))
|
|
|
6729ff |
- {
|
|
|
6729ff |
- increment_bad_pw_count = true;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (increment_bad_pw_count) {
|
|
|
6729ff |
- pdb_increment_bad_password_count(pwd);
|
|
|
6729ff |
- updated_badpw = true;
|
|
|
6729ff |
- } else {
|
|
|
6729ff |
- pdb_update_bad_password_count(pwd,
|
|
|
6729ff |
- &updated_badpw);
|
|
|
6729ff |
- }
|
|
|
6729ff |
- } else {
|
|
|
6729ff |
-
|
|
|
6729ff |
- if ((pdb_get_acct_ctrl(pwd) & ACB_NORMAL) &&
|
|
|
6729ff |
- (pdb_get_bad_password_count(pwd) > 0)){
|
|
|
6729ff |
- pdb_set_bad_password_count(pwd, 0, PDB_CHANGED);
|
|
|
6729ff |
- pdb_set_bad_password_time(pwd, 0, PDB_CHANGED);
|
|
|
6729ff |
- updated_badpw = true;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (updated_badpw) {
|
|
|
6729ff |
- NTSTATUS update_status;
|
|
|
6729ff |
- become_root();
|
|
|
6729ff |
- update_status = pdb_update_sam_account(pwd);
|
|
|
6729ff |
- unbecome_root();
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(update_status)) {
|
|
|
6729ff |
- DEBUG(1, ("Failed to modify entry: %s\n",
|
|
|
6729ff |
- nt_errstr(update_status)));
|
|
|
6729ff |
- }
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- out:
|
|
|
6729ff |
- TALLOC_FREE(pwd);
|
|
|
6729ff |
-
|
|
|
6729ff |
- return status;
|
|
|
6729ff |
+ return NT_STATUS_NOT_IMPLEMENTED;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
/*******************************************************************
|
|
|
6729ff |
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
|
|
|
6729ff |
index e6b9530..1b734a7 100644
|
|
|
6729ff |
--- a/source3/smbd/lanman.c
|
|
|
6729ff |
+++ b/source3/smbd/lanman.c
|
|
|
6729ff |
@@ -2948,259 +2948,6 @@ static bool api_NetRemoteTOD(struct smbd_server_connection *sconn,
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
/****************************************************************************
|
|
|
6729ff |
- Set the user password.
|
|
|
6729ff |
-*****************************************************************************/
|
|
|
6729ff |
-
|
|
|
6729ff |
-static bool api_SetUserPassword(struct smbd_server_connection *sconn,
|
|
|
6729ff |
- connection_struct *conn,uint64_t vuid,
|
|
|
6729ff |
- char *param, int tpscnt,
|
|
|
6729ff |
- char *data, int tdscnt,
|
|
|
6729ff |
- int mdrcnt,int mprcnt,
|
|
|
6729ff |
- char **rdata,char **rparam,
|
|
|
6729ff |
- int *rdata_len,int *rparam_len)
|
|
|
6729ff |
-{
|
|
|
6729ff |
- char *np = get_safe_str_ptr(param,tpscnt,param,2);
|
|
|
6729ff |
- char *p = NULL;
|
|
|
6729ff |
- fstring user;
|
|
|
6729ff |
- fstring pass1,pass2;
|
|
|
6729ff |
- TALLOC_CTX *mem_ctx = talloc_tos();
|
|
|
6729ff |
- NTSTATUS status, result;
|
|
|
6729ff |
- struct rpc_pipe_client *cli = NULL;
|
|
|
6729ff |
- struct policy_handle connect_handle, domain_handle, user_handle;
|
|
|
6729ff |
- struct lsa_String domain_name;
|
|
|
6729ff |
- struct dom_sid2 *domain_sid;
|
|
|
6729ff |
- struct lsa_String names;
|
|
|
6729ff |
- struct samr_Ids rids;
|
|
|
6729ff |
- struct samr_Ids types;
|
|
|
6729ff |
- struct samr_Password old_lm_hash;
|
|
|
6729ff |
- struct samr_Password new_lm_hash;
|
|
|
6729ff |
- int errcode = NERR_badpass;
|
|
|
6729ff |
- uint32_t rid;
|
|
|
6729ff |
- int encrypted;
|
|
|
6729ff |
- int min_pwd_length;
|
|
|
6729ff |
- struct dcerpc_binding_handle *b = NULL;
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* Skip 2 strings. */
|
|
|
6729ff |
- p = skip_string(param,tpscnt,np);
|
|
|
6729ff |
- p = skip_string(param,tpscnt,p);
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (!np || !p) {
|
|
|
6729ff |
- return False;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* Do we have a string ? */
|
|
|
6729ff |
- if (skip_string(param,tpscnt,p) == NULL) {
|
|
|
6729ff |
- return False;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- pull_ascii_fstring(user,p);
|
|
|
6729ff |
-
|
|
|
6729ff |
- p = skip_string(param,tpscnt,p);
|
|
|
6729ff |
- if (!p) {
|
|
|
6729ff |
- return False;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- memset(pass1,'\0',sizeof(pass1));
|
|
|
6729ff |
- memset(pass2,'\0',sizeof(pass2));
|
|
|
6729ff |
- /*
|
|
|
6729ff |
- * We use 31 here not 32 as we're checking
|
|
|
6729ff |
- * the last byte we want to access is safe.
|
|
|
6729ff |
- */
|
|
|
6729ff |
- if (!is_offset_safe(param,tpscnt,p,31)) {
|
|
|
6729ff |
- return False;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- memcpy(pass1,p,16);
|
|
|
6729ff |
- memcpy(pass2,p+16,16);
|
|
|
6729ff |
-
|
|
|
6729ff |
- encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1);
|
|
|
6729ff |
- if (encrypted == -1) {
|
|
|
6729ff |
- errcode = W_ERROR_V(WERR_INVALID_PARAM);
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1);
|
|
|
6729ff |
- if (min_pwd_length == -1) {
|
|
|
6729ff |
- errcode = W_ERROR_V(WERR_INVALID_PARAM);
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- *rparam_len = 4;
|
|
|
6729ff |
- *rparam = smb_realloc_limit(*rparam,*rparam_len);
|
|
|
6729ff |
- if (!*rparam) {
|
|
|
6729ff |
- return False;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- *rdata_len = 0;
|
|
|
6729ff |
-
|
|
|
6729ff |
- DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
|
|
|
6729ff |
- user, encrypted, min_pwd_length));
|
|
|
6729ff |
-
|
|
|
6729ff |
- ZERO_STRUCT(connect_handle);
|
|
|
6729ff |
- ZERO_STRUCT(domain_handle);
|
|
|
6729ff |
- ZERO_STRUCT(user_handle);
|
|
|
6729ff |
-
|
|
|
6729ff |
- status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id,
|
|
|
6729ff |
- conn->session_info,
|
|
|
6729ff |
- conn->sconn->remote_address,
|
|
|
6729ff |
- conn->sconn->msg_ctx,
|
|
|
6729ff |
- &cli;;
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
|
|
|
6729ff |
- nt_errstr(status)));
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(status));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- b = cli->binding_handle;
|
|
|
6729ff |
-
|
|
|
6729ff |
- status = dcerpc_samr_Connect2(b, mem_ctx,
|
|
|
6729ff |
- lp_netbios_name(),
|
|
|
6729ff |
- SAMR_ACCESS_CONNECT_TO_SERVER |
|
|
|
6729ff |
- SAMR_ACCESS_ENUM_DOMAINS |
|
|
|
6729ff |
- SAMR_ACCESS_LOOKUP_DOMAIN,
|
|
|
6729ff |
- &connect_handle,
|
|
|
6729ff |
- &result);
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(status));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(result)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(result));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- init_lsa_String(&domain_name, get_global_sam_name());
|
|
|
6729ff |
-
|
|
|
6729ff |
- status = dcerpc_samr_LookupDomain(b, mem_ctx,
|
|
|
6729ff |
- &connect_handle,
|
|
|
6729ff |
- &domain_name,
|
|
|
6729ff |
- &domain_sid,
|
|
|
6729ff |
- &result);
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(status));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(result)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(result));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- status = dcerpc_samr_OpenDomain(b, mem_ctx,
|
|
|
6729ff |
- &connect_handle,
|
|
|
6729ff |
- SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
|
|
|
6729ff |
- domain_sid,
|
|
|
6729ff |
- &domain_handle,
|
|
|
6729ff |
- &result);
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(status));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(result)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(result));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- init_lsa_String(&names, user);
|
|
|
6729ff |
-
|
|
|
6729ff |
- status = dcerpc_samr_LookupNames(b, mem_ctx,
|
|
|
6729ff |
- &domain_handle,
|
|
|
6729ff |
- 1,
|
|
|
6729ff |
- &names,
|
|
|
6729ff |
- &rids,
|
|
|
6729ff |
- &types,
|
|
|
6729ff |
- &result);
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(status));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(result)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(result));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (rids.count != 1) {
|
|
|
6729ff |
- errcode = W_ERROR_V(WERR_NO_SUCH_USER);
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (rids.count != types.count) {
|
|
|
6729ff |
- errcode = W_ERROR_V(WERR_INVALID_PARAM);
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (types.ids[0] != SID_NAME_USER) {
|
|
|
6729ff |
- errcode = W_ERROR_V(WERR_INVALID_PARAM);
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- rid = rids.ids[0];
|
|
|
6729ff |
-
|
|
|
6729ff |
- status = dcerpc_samr_OpenUser(b, mem_ctx,
|
|
|
6729ff |
- &domain_handle,
|
|
|
6729ff |
- SAMR_USER_ACCESS_CHANGE_PASSWORD,
|
|
|
6729ff |
- rid,
|
|
|
6729ff |
- &user_handle,
|
|
|
6729ff |
- &result);
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(status));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(result)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(result));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (encrypted == 0) {
|
|
|
6729ff |
- E_deshash(pass1, old_lm_hash.hash);
|
|
|
6729ff |
- E_deshash(pass2, new_lm_hash.hash);
|
|
|
6729ff |
- } else {
|
|
|
6729ff |
- ZERO_STRUCT(old_lm_hash);
|
|
|
6729ff |
- ZERO_STRUCT(new_lm_hash);
|
|
|
6729ff |
- memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16));
|
|
|
6729ff |
- memcpy(new_lm_hash.hash, pass2, MIN(strlen(pass2), 16));
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- status = dcerpc_samr_ChangePasswordUser(b, mem_ctx,
|
|
|
6729ff |
- &user_handle,
|
|
|
6729ff |
- true, /* lm_present */
|
|
|
6729ff |
- &old_lm_hash,
|
|
|
6729ff |
- &new_lm_hash,
|
|
|
6729ff |
- false, /* nt_present */
|
|
|
6729ff |
- NULL, /* old_nt_crypted */
|
|
|
6729ff |
- NULL, /* new_nt_crypted */
|
|
|
6729ff |
- false, /* cross1_present */
|
|
|
6729ff |
- NULL, /* nt_cross */
|
|
|
6729ff |
- false, /* cross2_present */
|
|
|
6729ff |
- NULL, /* lm_cross */
|
|
|
6729ff |
- &result);
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(status));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(result)) {
|
|
|
6729ff |
- errcode = W_ERROR_V(ntstatus_to_werror(result));
|
|
|
6729ff |
- goto out;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- errcode = NERR_Success;
|
|
|
6729ff |
- out:
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (b && is_valid_policy_hnd(&user_handle)) {
|
|
|
6729ff |
- dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (b && is_valid_policy_hnd(&domain_handle)) {
|
|
|
6729ff |
- dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result);
|
|
|
6729ff |
- }
|
|
|
6729ff |
- if (b && is_valid_policy_hnd(&connect_handle)) {
|
|
|
6729ff |
- dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result);
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- memset((char *)pass1,'\0',sizeof(fstring));
|
|
|
6729ff |
- memset((char *)pass2,'\0',sizeof(fstring));
|
|
|
6729ff |
-
|
|
|
6729ff |
- SSVAL(*rparam,0,errcode);
|
|
|
6729ff |
- SSVAL(*rparam,2,0); /* converter word */
|
|
|
6729ff |
- return(True);
|
|
|
6729ff |
-}
|
|
|
6729ff |
-
|
|
|
6729ff |
-/****************************************************************************
|
|
|
6729ff |
Set the user password (SamOEM version - gets plaintext).
|
|
|
6729ff |
****************************************************************************/
|
|
|
6729ff |
|
|
|
6729ff |
@@ -5797,7 +5544,6 @@ static const struct {
|
|
|
6729ff |
{"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
|
|
|
6729ff |
{"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
|
|
|
6729ff |
{"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
|
|
|
6729ff |
- {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
|
|
|
6729ff |
{"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
|
|
|
6729ff |
{"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
|
|
|
6729ff |
{"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
|
|
|
6729ff |
diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c
|
|
|
6729ff |
index 2d9c48a..9d6c921 100644
|
|
|
6729ff |
--- a/source4/rpc_server/samr/samr_password.c
|
|
|
6729ff |
+++ b/source4/rpc_server/samr/samr_password.c
|
|
|
6729ff |
@@ -33,150 +33,17 @@
|
|
|
6729ff |
|
|
|
6729ff |
/*
|
|
|
6729ff |
samr_ChangePasswordUser
|
|
|
6729ff |
+
|
|
|
6729ff |
+ So old it is just not worth implementing
|
|
|
6729ff |
+ because it does not supply a plaintext and so we can't do password
|
|
|
6729ff |
+ complexity checking and cannot update all the other password hashes.
|
|
|
6729ff |
+
|
|
|
6729ff |
*/
|
|
|
6729ff |
NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call,
|
|
|
6729ff |
TALLOC_CTX *mem_ctx,
|
|
|
6729ff |
struct samr_ChangePasswordUser *r)
|
|
|
6729ff |
{
|
|
|
6729ff |
- struct dcesrv_handle *h;
|
|
|
6729ff |
- struct samr_account_state *a_state;
|
|
|
6729ff |
- struct ldb_context *sam_ctx;
|
|
|
6729ff |
- struct ldb_message **res;
|
|
|
6729ff |
- int ret;
|
|
|
6729ff |
- struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
|
|
|
6729ff |
- struct samr_Password *lm_pwd, *nt_pwd;
|
|
|
6729ff |
- NTSTATUS status = NT_STATUS_OK;
|
|
|
6729ff |
- const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL };
|
|
|
6729ff |
-
|
|
|
6729ff |
- DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
|
|
|
6729ff |
-
|
|
|
6729ff |
- a_state = h->data;
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* basic sanity checking on parameters. Do this before any database ops */
|
|
|
6729ff |
- if (!r->in.lm_present || !r->in.nt_present ||
|
|
|
6729ff |
- !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
|
|
|
6729ff |
- !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
|
|
|
6729ff |
- /* we should really handle a change with lm not
|
|
|
6729ff |
- present */
|
|
|
6729ff |
- return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* Connect to a SAMDB with system privileges for fetching the old pw
|
|
|
6729ff |
- * hashes. */
|
|
|
6729ff |
- sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
|
|
|
6729ff |
- dce_call->conn->dce_ctx->lp_ctx,
|
|
|
6729ff |
- system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
|
|
|
6729ff |
- if (sam_ctx == NULL) {
|
|
|
6729ff |
- return NT_STATUS_INVALID_SYSTEM_SERVICE;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* fetch the old hashes */
|
|
|
6729ff |
- ret = gendb_search_dn(sam_ctx, mem_ctx,
|
|
|
6729ff |
- a_state->account_dn, &res, attrs);
|
|
|
6729ff |
- if (ret != 1) {
|
|
|
6729ff |
- return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- status = samdb_result_passwords(mem_ctx,
|
|
|
6729ff |
- dce_call->conn->dce_ctx->lp_ctx,
|
|
|
6729ff |
- res[0], &lm_pwd, &nt_pwd);
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status) || !nt_pwd) {
|
|
|
6729ff |
- return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* decrypt and check the new lm hash */
|
|
|
6729ff |
- if (lm_pwd) {
|
|
|
6729ff |
- D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
|
|
|
6729ff |
- D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* decrypt and check the new nt hash */
|
|
|
6729ff |
- D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
|
|
|
6729ff |
- D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* The NT Cross is not required by Win2k3 R2, but if present
|
|
|
6729ff |
- check the nt cross hash */
|
|
|
6729ff |
- if (r->in.cross1_present && r->in.nt_cross && lm_pwd) {
|
|
|
6729ff |
- D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* The LM Cross is not required by Win2k3 R2, but if present
|
|
|
6729ff |
- check the lm cross hash */
|
|
|
6729ff |
- if (r->in.cross2_present && r->in.lm_cross && lm_pwd) {
|
|
|
6729ff |
- D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* Start a SAM with user privileges for the password change */
|
|
|
6729ff |
- sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
|
|
|
6729ff |
- dce_call->conn->dce_ctx->lp_ctx,
|
|
|
6729ff |
- dce_call->conn->auth_state.session_info, 0);
|
|
|
6729ff |
- if (sam_ctx == NULL) {
|
|
|
6729ff |
- return NT_STATUS_INVALID_SYSTEM_SERVICE;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* Start transaction */
|
|
|
6729ff |
- ret = ldb_transaction_start(sam_ctx);
|
|
|
6729ff |
- if (ret != LDB_SUCCESS) {
|
|
|
6729ff |
- DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
|
|
|
6729ff |
- return NT_STATUS_TRANSACTION_ABORTED;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* Performs the password modification. We pass the old hashes read out
|
|
|
6729ff |
- * from the database since they were already checked against the user-
|
|
|
6729ff |
- * provided ones. */
|
|
|
6729ff |
- status = samdb_set_password(sam_ctx, mem_ctx,
|
|
|
6729ff |
- a_state->account_dn,
|
|
|
6729ff |
- a_state->domain_state->domain_dn,
|
|
|
6729ff |
- NULL, &new_lmPwdHash, &new_ntPwdHash,
|
|
|
6729ff |
- lm_pwd, nt_pwd, /* this is a user password change */
|
|
|
6729ff |
- NULL,
|
|
|
6729ff |
- NULL);
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
- return status;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* decrypt and check the new lm hash */
|
|
|
6729ff |
- if (lm_pwd) {
|
|
|
6729ff |
- if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
|
|
|
6729ff |
- ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
- return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {
|
|
|
6729ff |
- ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
- return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* The NT Cross is not required by Win2k3 R2, but if present
|
|
|
6729ff |
- check the nt cross hash */
|
|
|
6729ff |
- if (r->in.cross1_present && r->in.nt_cross && lm_pwd) {
|
|
|
6729ff |
- if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
|
|
|
6729ff |
- ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
- return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* The LM Cross is not required by Win2k3 R2, but if present
|
|
|
6729ff |
- check the lm cross hash */
|
|
|
6729ff |
- if (r->in.cross2_present && r->in.lm_cross && lm_pwd) {
|
|
|
6729ff |
- if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
|
|
|
6729ff |
- ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
- return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- }
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* And this confirms it in a transaction commit */
|
|
|
6729ff |
- ret = ldb_transaction_commit(sam_ctx);
|
|
|
6729ff |
- if (ret != LDB_SUCCESS) {
|
|
|
6729ff |
- DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
|
|
|
6729ff |
- ldb_dn_get_linearized(a_state->account_dn),
|
|
|
6729ff |
- ldb_errstring(sam_ctx)));
|
|
|
6729ff |
- return NT_STATUS_TRANSACTION_ABORTED;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- return NT_STATUS_OK;
|
|
|
6729ff |
+ return NT_STATUS_NOT_IMPLEMENTED;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
/*
|
|
|
6729ff |
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c
|
|
|
6729ff |
index a0a5f1a..cdfa2b8 100644
|
|
|
6729ff |
--- a/source4/torture/rpc/samr.c
|
|
|
6729ff |
+++ b/source4/torture/rpc/samr.c
|
|
|
6729ff |
@@ -1759,6 +1759,12 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
|
|
|
6729ff |
torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
|
|
|
6729ff |
__location__, __FUNCTION__,
|
|
|
6729ff |
oldpass, newpass, nt_errstr(r.out.result));
|
|
|
6729ff |
+
|
|
|
6729ff |
+ /* Do not proceed if this call has been removed */
|
|
|
6729ff |
+ if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
|
|
|
6729ff |
+ return true;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
|
|
|
6729ff |
torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
|
|
|
6729ff |
"ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
|
|
|
6729ff |
--
|
|
|
6729ff |
1.7.9.5
|
|
|
6729ff |
|
|
|
6729ff |
|
|
|
6729ff |
From b0281ad59d3ba8b32787ce112fb4a83d935c60d1 Mon Sep 17 00:00:00 2001
|
|
|
6729ff |
From: Andrew Bartlett <abartlet@samba.org>
|
|
|
6729ff |
Date: Thu, 28 Nov 2013 06:50:01 +1300
|
|
|
6729ff |
Subject: [PATCH 4/4] CVE-2013-4496:Revert remainder of
|
|
|
6729ff |
ce895609b04380bfc41e4f8fddc84bd2f9324340
|
|
|
6729ff |
|
|
|
6729ff |
Part of this was removed when ChangePasswordUser was unimplemented,
|
|
|
6729ff |
but remove the remainder of this flawed commit. Fully check the
|
|
|
6729ff |
password first, as extract_pw_from_buffer() already does a partial
|
|
|
6729ff |
check of the password because it needs a correct old password to
|
|
|
6729ff |
correctly decrypt the length.
|
|
|
6729ff |
|
|
|
6729ff |
Andrew Bartlett
|
|
|
6729ff |
|
|
|
6729ff |
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10245
|
|
|
6729ff |
|
|
|
6729ff |
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
|
|
|
6729ff |
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
6729ff |
Reviewed-by: Stefan Metzmacher <metze@samba.org>
|
|
|
6729ff |
---
|
|
|
6729ff |
source4/rpc_server/samr/samr_password.c | 69 ++++++++++++++++---------------
|
|
|
6729ff |
1 file changed, 35 insertions(+), 34 deletions(-)
|
|
|
6729ff |
|
|
|
6729ff |
diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c
|
|
|
6729ff |
index 9d6c921..685a8e7 100644
|
|
|
6729ff |
--- a/source4/rpc_server/samr/samr_password.c
|
|
|
6729ff |
+++ b/source4/rpc_server/samr/samr_password.c
|
|
|
6729ff |
@@ -142,6 +142,9 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
|
|
|
6729ff |
|
|
|
6729ff |
E_deshash(new_pass, new_lm_hash);
|
|
|
6729ff |
E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
|
|
|
6729ff |
+ if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
|
|
|
6729ff |
+ return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
|
|
|
6729ff |
/* Connect to a SAMDB with user privileges for the password change */
|
|
|
6729ff |
sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
|
|
|
6729ff |
@@ -173,11 +176,6 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
|
|
|
6729ff |
return status;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
- if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
|
|
|
6729ff |
- ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
- return NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
/* And this confirms it in a transaction commit */
|
|
|
6729ff |
ret = ldb_transaction_commit(sam_ctx);
|
|
|
6729ff |
if (ret != LDB_SUCCESS) {
|
|
|
6729ff |
@@ -267,33 +265,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
|
|
|
6729ff |
goto failed;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
- /* Connect to a SAMDB with user privileges for the password change */
|
|
|
6729ff |
- sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
|
|
|
6729ff |
- dce_call->conn->dce_ctx->lp_ctx,
|
|
|
6729ff |
- dce_call->conn->auth_state.session_info, 0);
|
|
|
6729ff |
- if (sam_ctx == NULL) {
|
|
|
6729ff |
- return NT_STATUS_INVALID_SYSTEM_SERVICE;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- ret = ldb_transaction_start(sam_ctx);
|
|
|
6729ff |
- if (ret != LDB_SUCCESS) {
|
|
|
6729ff |
- DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
|
|
|
6729ff |
- return NT_STATUS_TRANSACTION_ABORTED;
|
|
|
6729ff |
- }
|
|
|
6729ff |
-
|
|
|
6729ff |
- /* Performs the password modification. We pass the old hashes read out
|
|
|
6729ff |
- * from the database since they were already checked against the user-
|
|
|
6729ff |
- * provided ones. */
|
|
|
6729ff |
- status = samdb_set_password(sam_ctx, mem_ctx,
|
|
|
6729ff |
- user_dn, NULL,
|
|
|
6729ff |
- &new_password,
|
|
|
6729ff |
- NULL, NULL,
|
|
|
6729ff |
- lm_pwd, nt_pwd, /* this is a user password change */
|
|
|
6729ff |
- &reason,
|
|
|
6729ff |
- &dominfo);
|
|
|
6729ff |
-
|
|
|
6729ff |
- if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
- ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
+ if (r->in.nt_verifier == NULL) {
|
|
|
6729ff |
+ status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
goto failed;
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
@@ -302,7 +275,6 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
|
|
|
6729ff |
|
|
|
6729ff |
E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);
|
|
|
6729ff |
if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {
|
|
|
6729ff |
- ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
goto failed;
|
|
|
6729ff |
}
|
|
|
6729ff |
@@ -322,13 +294,42 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
|
|
|
6729ff |
E_deshash(new_pass, new_lm_hash);
|
|
|
6729ff |
E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
|
|
|
6729ff |
if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
|
|
|
6729ff |
- ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
status = NT_STATUS_WRONG_PASSWORD;
|
|
|
6729ff |
goto failed;
|
|
|
6729ff |
}
|
|
|
6729ff |
}
|
|
|
6729ff |
}
|
|
|
6729ff |
|
|
|
6729ff |
+ /* Connect to a SAMDB with user privileges for the password change */
|
|
|
6729ff |
+ sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
|
|
|
6729ff |
+ dce_call->conn->dce_ctx->lp_ctx,
|
|
|
6729ff |
+ dce_call->conn->auth_state.session_info, 0);
|
|
|
6729ff |
+ if (sam_ctx == NULL) {
|
|
|
6729ff |
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
+ ret = ldb_transaction_start(sam_ctx);
|
|
|
6729ff |
+ if (ret != LDB_SUCCESS) {
|
|
|
6729ff |
+ DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
|
|
|
6729ff |
+ return NT_STATUS_TRANSACTION_ABORTED;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
+ /* Performs the password modification. We pass the old hashes read out
|
|
|
6729ff |
+ * from the database since they were already checked against the user-
|
|
|
6729ff |
+ * provided ones. */
|
|
|
6729ff |
+ status = samdb_set_password(sam_ctx, mem_ctx,
|
|
|
6729ff |
+ user_dn, NULL,
|
|
|
6729ff |
+ &new_password,
|
|
|
6729ff |
+ NULL, NULL,
|
|
|
6729ff |
+ lm_pwd, nt_pwd, /* this is a user password change */
|
|
|
6729ff |
+ &reason,
|
|
|
6729ff |
+ &dominfo);
|
|
|
6729ff |
+
|
|
|
6729ff |
+ if (!NT_STATUS_IS_OK(status)) {
|
|
|
6729ff |
+ ldb_transaction_cancel(sam_ctx);
|
|
|
6729ff |
+ goto failed;
|
|
|
6729ff |
+ }
|
|
|
6729ff |
+
|
|
|
6729ff |
/* And this confirms it in a transaction commit */
|
|
|
6729ff |
ret = ldb_transaction_commit(sam_ctx);
|
|
|
6729ff |
if (ret != LDB_SUCCESS) {
|
|
|
6729ff |
--
|
|
|
6729ff |
1.7.9.5
|
|
|
6729ff |
|