[PATCH] allow passdb backend to change trusted domain object password with clear text

Alexander Bokovoy ab at samba.org
Thu Apr 6 15:46:06 UTC 2017


Hi,

attached patch switches _netr_ServerPasswordSet2 to use SetUserInfo2
info level 26. This allows us to pass through clear text password change
down to passdb backend. This is critical for AD-like configurations
(FreeIPA) where it is not enough to change NT or LM hashes for TDO, as
one needs to generate Kerberos keys as well.

I'm working on a corresponding change in FreeIPA ipasam module as well.
It currently does not provide pdb_update_sam_account() callback so end
result is still NT_STATUS_NOT_IMPLEMENTED as can be witnessed with
'nltest /sc_change_pwd:ipa.domain' but we are getting closer.

Please review.


-- 
/ Alexander Bokovoy
-------------- next part --------------
>From a768efc22933da3f7bf093739a0d1fb658e186b4 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab at samba.org>
Date: Fri, 31 Mar 2017 12:44:58 +0300
Subject: [PATCH] _netr_ServerPasswordSet2: use info level 26 to set plain text
 machine password

To support password change for machine or trusted domain accounts in Active
Directory environment we need to pass down actual plain text password
instead of NT hashes. This would allow a backend like ipasam to update
Kerberos keys as well as NT hashes.

By calling samr_SetUserInfo2 info level 26 we ensure PASSDB layer can
actually get the plain text password. If PASSDB backend implements
pdb_update_sam_account() callback, it then gets the plain text password
from samr_SetUserInfo2.

We are talking to our own SAMR service here.

Signed-off-by: Alexander Bokovoy <ab at samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 136 ++++++++++++++++++++++++++--
 1 file changed, 128 insertions(+), 8 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 6a42f34..b6b4ad4 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -33,6 +33,7 @@
 #include "../librpc/gen_ndr/ndr_lsa_c.h"
 #include "rpc_client/cli_lsarpc.h"
 #include "rpc_client/init_lsa.h"
+#include "rpc_client/init_samr.h"
 #include "rpc_server/rpc_ncacn_np.h"
 #include "../libcli/security/security.h"
 #include "../libcli/security/dom_sid.h"
@@ -1268,6 +1269,128 @@ static NTSTATUS netr_set_machine_account_password(TALLOC_CTX *mem_ctx,
 }
 
 /*************************************************************************
+ *************************************************************************/
+
+static NTSTATUS netr_set_machine_account_clear_password(TALLOC_CTX *mem_ctx,
+							struct auth_session_info *session_info,
+							struct messaging_context *msg_ctx,
+							const char *account_name,
+							DATA_BLOB *plain_text)
+{
+	NTSTATUS status;
+	NTSTATUS result = NT_STATUS_OK;
+	struct dcerpc_binding_handle *h = NULL;
+	struct tsocket_address *local;
+	struct policy_handle user_handle;
+	uint32_t acct_ctrl;
+	union samr_UserInfo *info;
+	struct samr_UserInfo26 info26;
+	int rc;
+	DATA_BLOB session_key;
+
+	ZERO_STRUCT(user_handle);
+
+	status = session_extract_session_key(session_info,
+					     &session_key,
+					     KEY_USE_16BYTES);
+	if (!NT_STATUS_IS_OK(status)) {
+		goto out;
+	}
+
+	rc = tsocket_address_inet_from_strings(mem_ctx,
+					       "ip",
+					       "127.0.0.1",
+					       0,
+					       &local);
+	if (rc < 0) {
+		status = NT_STATUS_NO_MEMORY;
+		goto out;
+	}
+
+	status = rpcint_binding_handle(mem_ctx,
+				       &ndr_table_samr,
+				       local,
+				       session_info,
+				       msg_ctx,
+				       &h);
+	if (!NT_STATUS_IS_OK(status)) {
+		goto out;
+	}
+
+	become_root();
+	status = samr_find_machine_account(mem_ctx,
+					   h,
+					   account_name,
+					   SEC_FLAG_MAXIMUM_ALLOWED,
+					   NULL,
+					   NULL,
+					   &user_handle);
+	unbecome_root();
+	if (!NT_STATUS_IS_OK(status)) {
+		goto out;
+	}
+
+	status = dcerpc_samr_QueryUserInfo2(h,
+					    mem_ctx,
+					    &user_handle,
+					    UserControlInformation,
+					    &info,
+					    &result);
+	if (!NT_STATUS_IS_OK(status)) {
+		goto out;
+	}
+	if (!NT_STATUS_IS_OK(result)) {
+		status = result;
+		goto out;
+	}
+
+	acct_ctrl = info->info16.acct_flags;
+
+	if (!(acct_ctrl & ACB_WSTRUST ||
+	      acct_ctrl & ACB_SVRTRUST ||
+	      acct_ctrl & ACB_DOMTRUST)) {
+		status = NT_STATUS_NO_SUCH_USER;
+		goto out;
+	}
+
+	if (acct_ctrl & ACB_DISABLED) {
+		status = NT_STATUS_ACCOUNT_DISABLED;
+		goto out;
+	}
+
+	ZERO_STRUCT(info26);
+
+	init_samr_CryptPasswordEx((const char*) plain_text->data,
+				  &session_key,
+				  &info26.password);
+
+	info26.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;
+	info->info26 = info26;
+
+	become_root();
+	status = dcerpc_samr_SetUserInfo2(h,
+					  mem_ctx,
+					  &user_handle,
+					  UserInternal5InformationNew,
+					  info,
+					  &result);
+	unbecome_root();
+	if (!NT_STATUS_IS_OK(status)) {
+		goto out;
+	}
+	if (!NT_STATUS_IS_OK(result)) {
+		status = result;
+		goto out;
+	}
+
+ out:
+	if (h && is_valid_policy_hnd(&user_handle)) {
+		dcerpc_samr_Close(h, mem_ctx, &user_handle, &result);
+	}
+
+	return status;
+}
+/*************************************************************************
  _netr_ServerPasswordSet
  *************************************************************************/
 
@@ -1330,7 +1453,6 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p,
 	struct netlogon_creds_CredentialState *creds = NULL;
 	DATA_BLOB plaintext;
 	struct samr_CryptPassword password_buf;
-	struct samr_Password nt_hash;
 
 	become_root();
 	status = netr_creds_server_step_check(p, p->mem_ctx,
@@ -1367,13 +1489,11 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p,
 		return NT_STATUS_WRONG_PASSWORD;
 	}
 
-	mdfour(nt_hash.hash, plaintext.data, plaintext.length);
-
-	status = netr_set_machine_account_password(p->mem_ctx,
-						   p->session_info,
-						   p->msg_ctx,
-						   creds->account_name,
-						   &nt_hash);
+	status = netr_set_machine_account_clear_password(p->mem_ctx,
+							 p->session_info,
+							 p->msg_ctx,
+							 creds->account_name,
+							 &plaintext);
 	TALLOC_FREE(creds);
 	return status;
 }
-- 
2.9.3



More information about the samba-technical mailing list