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

Alexander Bokovoy ab at samba.org
Mon Apr 10 07:22:21 UTC 2017


On pe, 07 huhti 2017, Jeremy Allison wrote:
> On Fri, Apr 07, 2017 at 11:08:44PM +0300, Alexander Bokovoy wrote:
> 
> > I'll see what I can do there but this code is a copy/paste from another
> > helper we have for NT/LM hash pass-through. Guenther already asked me to
> > consider how I can going these two functions in a common piece that
> > could be called for both cases, so I'll do refactoring for this too.
> 
> Thanks. That other code might be wrong too :-).
Attached is the patch that unifies NT hash/plain text pass-through.
This is a more concise change that doesn't duplicate existing code.

I think we should handle IPv6 concerns in a separate patchset. Below is
the list of places where we hardcode 127.0.0.1 explicitly.

source3/librpc/rpc/dcerpc_ep.c:         rc = tsocket_address_inet_from_strings(tmp_ctx,
source3/librpc/rpc/dcerpc_ep.c-                                                "ip",
source3/librpc/rpc/dcerpc_ep.c-                                                "127.0.0.1",
--
source3/rpc_client/cli_winreg_int.c:    rc = tsocket_address_inet_from_strings(mem_ctx,
source3/rpc_client/cli_winreg_int.c-                                           "ip",
source3/rpc_client/cli_winreg_int.c-                                           "127.0.0.1",
--
source3/rpc_server/netlogon/srv_netlog_nt.c:    rc = tsocket_address_inet_from_strings(mem_ctx,
source3/rpc_server/netlogon/srv_netlog_nt.c-                                           "ip",
source3/rpc_server/netlogon/srv_netlog_nt.c-                                           "127.0.0.1",
--
source3/rpc_server/netlogon/srv_netlog_nt.c:    rc = tsocket_address_inet_from_strings(mem_ctx,
source3/rpc_server/netlogon/srv_netlog_nt.c-                                           "ip",
source3/rpc_server/netlogon/srv_netlog_nt.c-                                           "127.0.0.1",
--
source3/rpc_server/rpc_ncacn_np.c:              rc = tsocket_address_inet_from_strings(mem_ctx,
source3/rpc_server/rpc_ncacn_np.c-                                                     "ip",
source3/rpc_server/rpc_ncacn_np.c-                                                     "127.0.0.1",
--
source3/rpc_server/spoolss/srv_spoolss_util.c:  rc = tsocket_address_inet_from_strings(mem_ctx,
source3/rpc_server/spoolss/srv_spoolss_util.c-                                         "ip",
source3/rpc_server/spoolss/srv_spoolss_util.c-                                         "127.0.0.1",
--
source3/winbindd/winbindd_pam.c:        rc = tsocket_address_inet_from_strings(frame,
source3/winbindd/winbindd_pam.c-                                               "ip",
source3/winbindd/winbindd_pam.c-                                               "127.0.0.1",
--

I filed bug https://bugzilla.samba.org/show_bug.cgi?id=12738 to track this effort.

We also have NBNS replication (MS-WINSRA) implementation that only
supports IPv4 because NBNS only supports IPv4:

source4/libcli/wrepl/winsrepl.c:        ret = tsocket_address_inet_from_strings(state, "ipv4",
source4/libcli/wrepl/winsrepl.c-                                                our_ip, 0,
source4/libcli/wrepl/winsrepl.c-                                                &state->local_address);
--
source4/libcli/wrepl/winsrepl.c:        ret = tsocket_address_inet_from_strings(state, "ipv4",
source4/libcli/wrepl/winsrepl.c-                                                peer_ip, WINS_REPLICATION_PORT,
source4/libcli/wrepl/winsrepl.c-                                                &state->remote_address);
--

-- 
/ Alexander Bokovoy
-------------- next part --------------
>From e1ea25f5d21bcd10c3f4ec59ae53e4901908d9a3 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 | 67 +++++++++++++++++++++++------
 1 file changed, 53 insertions(+), 14 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 6a42f34..25af98e 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"
@@ -1140,14 +1141,27 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 	return status;
 }
 
+
 /*************************************************************************
  *************************************************************************/
 
+struct _samr_Credentials_t {
+	enum {
+		CRED_TYPE_NT_HASH,
+		CRED_TYPE_PLAIN_TEXT,
+	} cred_type;
+	union {
+		struct samr_Password *nt_hash;
+		const char *password;
+	} creds;
+};
+
+
 static NTSTATUS netr_set_machine_account_password(TALLOC_CTX *mem_ctx,
 						  struct auth_session_info *session_info,
 						  struct messaging_context *msg_ctx,
 						  const char *account_name,
-						  struct samr_Password *nt_hash)
+						  struct _samr_Credentials_t *cr)
 {
 	NTSTATUS status;
 	NTSTATUS result = NT_STATUS_OK;
@@ -1157,9 +1171,11 @@ static NTSTATUS netr_set_machine_account_password(TALLOC_CTX *mem_ctx,
 	uint32_t acct_ctrl;
 	union samr_UserInfo *info;
 	struct samr_UserInfo18 info18;
+	struct samr_UserInfo26 info26;
 	DATA_BLOB in,out;
 	int rc;
 	DATA_BLOB session_key;
+	enum samr_UserInfoLevel infolevel;
 
 	ZERO_STRUCT(user_handle);
 
@@ -1232,22 +1248,44 @@ static NTSTATUS netr_set_machine_account_password(TALLOC_CTX *mem_ctx,
 		goto out;
 	}
 
-	ZERO_STRUCT(info18);
+	switch(cr->cred_type) {
+		case CRED_TYPE_NT_HASH:
+			ZERO_STRUCT(info18);
 
-	in = data_blob_const(nt_hash->hash, 16);
-	out = data_blob_talloc_zero(mem_ctx, 16);
-	sess_crypt_blob(&out, &in, &session_key, true);
-	memcpy(info18.nt_pwd.hash, out.data, out.length);
+			infolevel = UserInternal1Information;
+
+			in = data_blob_const(cr->creds.nt_hash, 16);
+			out = data_blob_talloc_zero(mem_ctx, 16);
+			sess_crypt_blob(&out, &in, &session_key, true);
+			memcpy(info18.nt_pwd.hash, out.data, out.length);
+
+			info18.nt_pwd_active = true;
+
+			info->info18 = info18;
+		break;
+		case CRED_TYPE_PLAIN_TEXT:
+			ZERO_STRUCT(info26);
 
-	info18.nt_pwd_active = true;
+			infolevel = UserInternal5Information;
 
-	info->info18 = info18;
+			init_samr_CryptPasswordEx(cr->creds.password,
+						  &session_key,
+						  &info26.password);
+
+			info26.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;
+			info->info26 = info26;
+		break;
+		default:
+			status = NT_STATUS_INTERNAL_ERROR;
+			goto out;
+		break;
+	}
 
 	become_root();
 	status = dcerpc_samr_SetUserInfo2(h,
 					  mem_ctx,
 					  &user_handle,
-					  UserInternal1Information,
+					  infolevel,
 					  info,
 					  &result);
 	unbecome_root();
@@ -1277,6 +1315,7 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p,
 	NTSTATUS status = NT_STATUS_OK;
 	int i;
 	struct netlogon_creds_CredentialState *creds = NULL;
+	struct _samr_Credentials_t cr = { CRED_TYPE_NT_HASH, {0}};
 
 	DEBUG(5,("_netr_ServerPasswordSet: %d\n", __LINE__));
 
@@ -1311,11 +1350,12 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p,
 		DEBUG(100,("%02X ", r->in.new_password->hash[i]));
 	DEBUG(100,("\n"));
 
+	cr.creds.nt_hash = r->in.new_password;
 	status = netr_set_machine_account_password(p->mem_ctx,
 						   p->session_info,
 						   p->msg_ctx,
 						   creds->account_name,
-						   r->in.new_password);
+						   &cr);
 	return status;
 }
 
@@ -1330,7 +1370,7 @@ 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;
+	struct _samr_Credentials_t cr = { CRED_TYPE_PLAIN_TEXT, {0}};
 
 	become_root();
 	status = netr_creds_server_step_check(p, p->mem_ctx,
@@ -1367,13 +1407,12 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p,
 		return NT_STATUS_WRONG_PASSWORD;
 	}
 
-	mdfour(nt_hash.hash, plaintext.data, plaintext.length);
-
+	cr.creds.password = (const char*) plaintext.data;
 	status = netr_set_machine_account_password(p->mem_ctx,
 						   p->session_info,
 						   p->msg_ctx,
 						   creds->account_name,
-						   &nt_hash);
+						   &cr);
 	TALLOC_FREE(creds);
 	return status;
 }
-- 
2.9.3



More information about the samba-technical mailing list