summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 5893bd4821..a599822d9e 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -32,6 +32,7 @@
#include "param/param.h"
#include "lib/messaging/irpc.h"
#include "librpc/gen_ndr/ndr_irpc.h"
+#include "../libcli/ldap/ldap_ndr.h"
#include "cldap_server/cldap_server.h"
#include "lib/tsocket/tsocket.h"
@@ -384,7 +385,11 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call
{
struct netlogon_creds_CredentialState *creds;
struct ldb_context *sam_ctx;
+ const char * const attrs[] = { "unicodePwd", NULL };
+ struct ldb_message **res;
+ struct samr_Password *oldNtHash;
NTSTATUS nt_status;
+ int ret;
nt_status = dcesrv_netr_creds_server_step_check(dce_call,
mem_ctx,
@@ -400,12 +405,28 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call
netlogon_creds_des_decrypt(creds, r->in.new_password);
+ /* fetch the old password hashes (the NT hash has to exist) */
+
+ ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
+ "(&(objectClass=user)(objectSid=%s))",
+ ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
+ if (ret != 1) {
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+
+ nt_status = samdb_result_passwords(mem_ctx,
+ dce_call->conn->dce_ctx->lp_ctx,
+ res[0], NULL, &oldNtHash);
+ if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+
/* Using the sid for the account as the key, set the password */
nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
creds->sid,
NULL, /* Don't have plaintext */
NULL, r->in.new_password,
- true, /* Password change */
+ NULL, oldNtHash, /* Password change */
NULL, NULL);
return nt_status;
}
@@ -419,8 +440,12 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
{
struct netlogon_creds_CredentialState *creds;
struct ldb_context *sam_ctx;
+ const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
+ struct ldb_message **res;
+ struct samr_Password *oldLmHash, *oldNtHash;
NTSTATUS nt_status;
DATA_BLOB new_password;
+ int ret;
struct samr_CryptPassword password_buf;
@@ -445,12 +470,28 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
return NT_STATUS_WRONG_PASSWORD;
}
+ /* fetch the old password hashes (at least one of both has to exist) */
+
+ ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
+ "(&(objectClass=user)(objectSid=%s))",
+ ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
+ if (ret != 1) {
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+
+ nt_status = samdb_result_passwords(mem_ctx,
+ dce_call->conn->dce_ctx->lp_ctx,
+ res[0], &oldLmHash, &oldNtHash);
+ if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+
/* Using the sid for the account as the key, set the password */
nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
creds->sid,
&new_password, /* we have plaintext */
NULL, NULL,
- true, /* Password change */
+ oldLmHash, oldNtHash, /* Password change */
NULL, NULL);
return nt_status;
}