[PATCH] Bunch of winbindd improvements

Ralph Böhme slow at samba.org
Fri Feb 9 18:36:28 UTC 2018


Hi!

Attached is a somewhat largish patchset with a few fixes and some improvements
for winbindd in trusted domain setups.

The plan is to get all of this into 4.8, all patches have bugs assigned.

Most of the patches are from metze, some are mine and they are already
cross-reviewed, so unless someone objects I'll push them in a day or two.

With these patches winbindd should be in pretty good shape in trusted domain
setups on a member server.

metze and I are working on getting the missing pieces when running as a DC in
trusted domain setups (s4 lsa rpc server, sid filtering, ...), but that will
probably not be ready in time for 4.8.

-slow

-- 
Ralph Boehme, Samba Team       https://samba.org/
Samba Developer, SerNet GmbH   https://sernet.de/en/samba/
GPG Key Fingerprint: FAE2 C608 8A24 2520 51C5  59E4 AA1E 9B71 2639 9E46
-------------- next part --------------
From 4397b1b47e224a51dd603f8246612d91bf2d26ae Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 14:24:47 +0100
Subject: [PATCH 01/37] winbindd: fix LSA connections via DCERPC_AUTH_SCHANNEL

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13231

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd.h    | 1 -
 source3/winbindd/winbindd_cm.c | 9 ---------
 2 files changed, 10 deletions(-)

diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index b60094bafcd..43c90445e87 100644
--- a/source3/winbindd/winbindd.h
+++ b/source3/winbindd/winbindd.h
@@ -100,7 +100,6 @@ struct winbindd_cm_conn {
 
 	struct rpc_pipe_client *netlogon_pipe;
 	struct netlogon_creds_cli_context *netlogon_creds_ctx;
-	uint32_t netlogon_flags;
 	bool netlogon_force_reauth;
 };
 
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 4d3a372dd25..2aca5f374f6 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -2039,7 +2039,6 @@ void invalidate_cm_connection(struct winbindd_domain *domain)
 
 	conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
 	conn->netlogon_force_reauth = false;
-	conn->netlogon_flags = 0;
 	TALLOC_FREE(conn->netlogon_creds_ctx);
 
 	if (conn->cli) {
@@ -2620,9 +2619,6 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
 	}
 
 	if (domain->conn.netlogon_creds_ctx != NULL) {
-		if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
-			return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
-		}
 		*ppdc = domain->conn.netlogon_creds_ctx;
 		return NT_STATUS_OK;
 	}
@@ -2636,10 +2632,6 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
 		return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
 	}
 
-	if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
-		return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
-	}
-
 	*ppdc = domain->conn.netlogon_creds_ctx;
 	return NT_STATUS_OK;
 }
@@ -3234,7 +3226,6 @@ static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
 	}
 
 	TALLOC_FREE(conn->netlogon_pipe);
-	conn->netlogon_flags = 0;
 	TALLOC_FREE(conn->netlogon_creds_ctx);
 
 	result = get_trust_credentials(domain, talloc_tos(), true, &creds);
-- 
2.13.6


From b07ca90c6bc3b4285f786f1b9e848f7a161fcd02 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 14:30:12 +0100
Subject: [PATCH 02/37] winbindd: remove useless calls to
 get_trust_credentials() before cli_rpc_pipe_open_schannel_with_creds()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13231

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_cm.c | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 2aca5f374f6..b7fd981547f 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -2758,13 +2758,6 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 		goto anonymous;
 	}
 	TALLOC_FREE(creds);
-	result = get_trust_credentials(domain, talloc_tos(), true, &creds);
-	if (!NT_STATUS_IS_OK(result)) {
-		DEBUG(10, ("cm_connect_sam: No user available for "
-			   "domain %s (error %s), trying anon\n", domain->name,
-			   nt_errstr(result)));
-		goto anonymous;
-	}
 	status = cli_rpc_pipe_open_schannel_with_creds(
 		conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
 		&conn->samr_pipe);
@@ -2908,7 +2901,6 @@ static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
 {
 	struct winbindd_cm_conn *conn;
 	struct netlogon_creds_cli_context *p_creds = NULL;
-	struct cli_credentials *creds = NULL;
 	NTSTATUS status;
 
 	DEBUG(10,("cm_connect_lsa_tcp\n"));
@@ -2936,11 +2928,6 @@ static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
 		goto done;
 	}
 
-	status = get_trust_credentials(domain, talloc_tos(), true, &creds);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto done;
-	}
-
 	status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
 						       &ndr_table_lsarpc,
 						       NCACN_IP_TCP,
@@ -3063,13 +3050,6 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	}
 
 	TALLOC_FREE(creds);
-	result = get_trust_credentials(domain, talloc_tos(), true, &creds);
-	if (!NT_STATUS_IS_OK(result)) {
-		DEBUG(10, ("cm_connect_lsa: No user available for "
-			   "domain %s (error %s), trying anon\n", domain->name,
-			   nt_errstr(result)));
-		goto anonymous;
-	}
 	result = cli_rpc_pipe_open_schannel_with_creds(
 		conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
 		&conn->lsa_pipe);
-- 
2.13.6


From 48a0d588e31ff9a37717d1f028df2e81ddbf13c9 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 14:30:48 +0100
Subject: [PATCH 03/37] winbindd: add missing can_do_ncacn_ip_tcp
 initialisation

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13232

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_util.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 4d66571703f..910e02269b5 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -275,6 +275,8 @@ static NTSTATUS add_trusted_domain(const char *domain_name,
 		}
 	}
 
+	domain->can_do_ncacn_ip_tcp = domain->active_directory;
+
 	/* Link to domain list */
 	DLIST_ADD_END(_domain_list, domain);
 
-- 
2.13.6


From 73bddf8c73b471bf4963aa1ce45bad4949349366 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 18 Jan 2018 08:38:59 +0100
Subject: [PATCH 04/37] winbindd: add routing_domain as parameter to
 add_trusted_domain

This also fixes the following CIDs:

CID 1427622:  Null pointer dereferences  (REVERSE_INULL)
CID 1427619:  Null pointer dereferences  (REVERSE_INULL)

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13233

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/winbindd/winbindd_util.c | 55 +++++++++++-----------------------------
 1 file changed, 15 insertions(+), 40 deletions(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 910e02269b5..b20976c8048 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -127,6 +127,7 @@ static NTSTATUS add_trusted_domain(const char *domain_name,
 				   uint32_t trust_flags,
 				   uint32_t trust_attribs,
 				   enum netr_SchannelType secure_channel_type,
+				   struct winbindd_domain *routing_domain,
 				   struct winbindd_domain **_d)
 {
 	struct winbindd_domain *domain = NULL;
@@ -253,6 +254,7 @@ static NTSTATUS add_trusted_domain(const char *domain_name,
 	domain->domain_type = trust_type;
 	domain->domain_trust_attribs = trust_attribs;
 	domain->secure_channel_type = secure_channel_type;
+	domain->routing_domain = routing_domain;
 	sid_copy(&domain->sid, sid);
 
 	/* Is this our primary domain ? */
@@ -343,6 +345,7 @@ bool add_trusted_domain_from_auth(uint16_t validation_level,
 				    NETR_TRUST_FLAG_OUTBOUND,
 				    0,
 				    SEC_CHAN_NULL,
+				    find_default_route_domain(),
 				    &domain);
 	if (!NT_STATUS_IS_OK(status) &&
 	    !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
@@ -352,11 +355,6 @@ bool add_trusted_domain_from_auth(uint16_t validation_level,
 		return false;
 	}
 
-	ok = set_routing_domain(domain, find_default_route_domain());
-	if (!ok) {
-		return false;
-	}
-
 	return true;
 }
 
@@ -416,7 +414,6 @@ static void trustdom_list_done(struct tevent_req *req)
 	ptrdiff_t extra_len;
 	bool within_forest = false;
 	NTSTATUS status;
-	bool ok;
 
 	/*
 	 * Only when we enumerate our primary domain
@@ -540,6 +537,7 @@ static void trustdom_list_done(struct tevent_req *req)
 					    trust_flags,
 					    trust_attribs,
 					    SEC_CHAN_NULL,
+					    find_default_route_domain(),
 					    &domain);
 		if (!NT_STATUS_IS_OK(status) &&
 		    !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
@@ -549,12 +547,6 @@ static void trustdom_list_done(struct tevent_req *req)
 			return;
 		}
 
-		ok = set_routing_domain(domain, find_default_route_domain());
-		if (!ok) {
-			DBG_ERR("set_routing_domain failed\n");
-			return;
-		}
-
 		p = q + strlen(q) + 1;
 	}
 
@@ -597,7 +589,6 @@ static void rescan_forest_root_trusts( void )
         size_t num_trusts = 0;
 	int i;
 	NTSTATUS status;
-	bool ok;
 
 	/* The only transitive trusts supported by Windows 2003 AD are
 	   (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
@@ -630,6 +621,7 @@ static void rescan_forest_root_trusts( void )
 						    dom_list[i].trust_flags,
 						    dom_list[i].trust_attribs,
 						    SEC_CHAN_NULL,
+						    find_default_route_domain(),
 						    &d);
 
 			if (!NT_STATUS_IS_OK(status) &&
@@ -639,11 +631,6 @@ static void rescan_forest_root_trusts( void )
 					nt_errstr(status));
 				return;
 			}
-			ok = set_routing_domain(d, find_default_route_domain());
-			if (!ok) {
-				DBG_ERR("set_routing_domain failed\n");
-				return;
-			}
 		}
 		if (d == NULL) {
 			continue;
@@ -679,7 +666,6 @@ static void rescan_forest_trusts( void )
         size_t num_trusts = 0;
 	int i;
 	NTSTATUS status;
-	bool ok;
 
 	/* The only transitive trusts supported by Windows 2003 AD are
 	   (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
@@ -718,6 +704,7 @@ static void rescan_forest_trusts( void )
 					flags,
 					attribs,
 					SEC_CHAN_NULL,
+					find_default_route_domain(),
 					&d);
 				if (!NT_STATUS_IS_OK(status) &&
 				    NT_STATUS_EQUAL(status,
@@ -727,12 +714,6 @@ static void rescan_forest_trusts( void )
 						nt_errstr(status));
 					return;
 				}
-				ok = set_routing_domain(
-					d, find_default_route_domain());
-				if (!ok) {
-					DBG_ERR("set_routing_domain failed\n");
-					return;
-				}
 			}
 
 			if (d == NULL) {
@@ -839,7 +820,6 @@ static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
 	struct winbindd_domain *d = NULL;
 	uint32_t trust_flags = 0;
 	NTSTATUS status;
-	bool ok;
 
 	DEBUG(5, ("wb_imsg_new_trusted_domain\n"));
 
@@ -881,6 +861,7 @@ static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
 				    trust_flags,
 				    info.trust_attributes,
 				    secure_channel_type,
+				    find_default_route_domain(),
 				    &d);
 	if (!NT_STATUS_IS_OK(status) &&
 	    !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
@@ -890,11 +871,7 @@ static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
 		TALLOC_FREE(frame);
 		return;
 	}
-	ok = set_routing_domain(d, find_default_route_domain());
-	if (!ok) {
-		TALLOC_FREE(frame);
-		return;
-	}
+
 	TALLOC_FREE(frame);
 }
 
@@ -961,6 +938,7 @@ bool init_domain_list(void)
 				    0, /* trust_flags */
 				    0, /* trust_attribs */
 				    SEC_CHAN_LOCAL,
+				    NULL,
 				    &domain);
 	if (!NT_STATUS_IS_OK(status)) {
 		DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
@@ -1013,6 +991,7 @@ bool init_domain_list(void)
 					    trust_flags,
 					    LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
 					    SEC_CHAN_BDC,
+					    NULL,
 					    &domain);
 		TALLOC_FREE(pdb_domain_info);
 		if (!NT_STATUS_IS_OK(status)) {
@@ -1084,6 +1063,7 @@ bool init_domain_list(void)
 					    trust_flags,
 					    0, /* trust_attribs */
 					    secure_channel_type,
+					    NULL,
 					    &domain);
 		if (!NT_STATUS_IS_OK(status)) {
 			DBG_ERR("Failed to add local SAM to "
@@ -1116,6 +1096,7 @@ bool init_domain_list(void)
 					    NETR_TRUST_FLAG_OUTBOUND,
 					    0, /* trust_attribs */
 					    SEC_CHAN_WKSTA,
+					    NULL,
 					    &domain);
 		if (!NT_STATUS_IS_OK(status)) {
 			DBG_ERR("Failed to add local SAM to "
@@ -1173,6 +1154,7 @@ bool init_domain_list(void)
 						    trust_flags,
 						    domains[i]->trust_attributes,
 						    sec_chan_type,
+						    NULL,
 						    &domain);
 			if (!NT_STATUS_IS_OK(status)) {
 				DBG_NOTICE("add_trusted_domain returned %s\n",
@@ -1202,7 +1184,6 @@ bool init_domain_list(void)
 			uint32_t fi;
 			enum ndr_err_code ndr_err;
 			struct winbindd_domain *routing_domain = NULL;
-			bool ok;
 
 			if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
 				continue;
@@ -1271,6 +1252,7 @@ bool init_domain_list(void)
 							    NETR_TRUST_FLAG_OUTBOUND,
 							    0,
 							    SEC_CHAN_NULL,
+							    routing_domain,
 							    &domain);
 				if (!NT_STATUS_IS_OK(status)) {
 					DBG_NOTICE("add_trusted_domain returned %s\n",
@@ -1280,14 +1262,6 @@ bool init_domain_list(void)
 				if (domain == NULL) {
 					continue;
 				}
-				ok = set_routing_domain(domain, routing_domain);
-				if (!ok) {
-					DBG_ERR("set_routing_domain on [%s] to "
-						"[%s] failed\n",
-						domain->name,
-						routing_domain->name);
-					return false;
-				}
 			}
 		}
 	} else if (IS_DC) {
@@ -1310,6 +1284,7 @@ bool init_domain_list(void)
 						    NETR_TRUST_FLAG_OUTBOUND,
 						    0,
 						    SEC_CHAN_DOMAIN,
+						    NULL,
 						    &domain);
 			if (!NT_STATUS_IS_OK(status)) {
 				DBG_NOTICE("add_trusted_domain returned %s\n",
-- 
2.13.6


From 1107cd93339595ea37369f81a0838f4411369856 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 11:58:31 +0100
Subject: [PATCH 05/37] s3:rpc_client: allow
 Netlogon{Network,Interactive}TransitiveInformation in
 rpccli_netlogon_password_logon()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13234

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/rpc_client/cli_netlogon.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index 800b995215c..7dc69c066c7 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -490,7 +490,8 @@ NTSTATUS rpccli_netlogon_password_logon(
 	/* Initialise input parameters */
 
 	switch (logon_type) {
-	case NetlogonInteractiveInformation: {
+	case NetlogonInteractiveInformation:
+	case NetlogonInteractiveTransitiveInformation: {
 
 		struct netr_PasswordInfo *password_info;
 
@@ -519,7 +520,8 @@ NTSTATUS rpccli_netlogon_password_logon(
 
 		break;
 	}
-	case NetlogonNetworkInformation: {
+	case NetlogonNetworkInformation:
+	case NetlogonNetworkTransitiveInformation: {
 		struct netr_NetworkInfo *network_info;
 		uint8_t chal[8];
 		unsigned char local_lm_response[24];
-- 
2.13.6


From 532371da311abba7ab3e00925f2d06bb1e621162 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 12:00:19 +0100
Subject: [PATCH 06/37] s3:rpc_client: allow passing
 NetlogonNetwork[Transitive]Information to rpccli_netlogon_network_logon()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13234

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/rpc_client/cli_netlogon.c | 13 ++++++++++++-
 source3/rpc_client/cli_netlogon.h |  1 +
 source3/winbindd/winbindd_pam.c   |  1 +
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index 7dc69c066c7..d8ccce72e0d 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -610,6 +610,7 @@ NTSTATUS rpccli_netlogon_network_logon(
 	const uint8_t chal[8],
 	DATA_BLOB lm_response,
 	DATA_BLOB nt_response,
+	enum netr_LogonInfoClass logon_type,
 	uint8_t *authoritative,
 	uint32_t *flags,
 	uint16_t *_validation_level,
@@ -629,6 +630,16 @@ NTSTATUS rpccli_netlogon_network_logon(
 	ZERO_STRUCT(lm);
 	ZERO_STRUCT(nt);
 
+	switch (logon_type) {
+	case NetlogonNetworkInformation:
+	case NetlogonNetworkTransitiveInformation:
+		break;
+	default:
+		DEBUG(0, ("switch value %d not supported\n",
+			logon_type));
+		return NT_STATUS_INVALID_INFO_CLASS;
+	}
+
 	logon = talloc_zero(mem_ctx, union netr_LogonLevel);
 	if (!logon) {
 		return NT_STATUS_NO_MEMORY;
@@ -674,7 +685,7 @@ NTSTATUS rpccli_netlogon_network_logon(
 
 	status = netlogon_creds_cli_LogonSamLogon(creds_ctx,
 						  binding_handle,
-						  NetlogonNetworkInformation,
+						  logon_type,
 						  logon,
 						  mem_ctx,
 						  &validation_level,
diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h
index d31bdee461f..dc04c0b0676 100644
--- a/source3/rpc_client/cli_netlogon.h
+++ b/source3/rpc_client/cli_netlogon.h
@@ -84,6 +84,7 @@ NTSTATUS rpccli_netlogon_network_logon(
 	const uint8_t chal[8],
 	DATA_BLOB lm_response,
 	DATA_BLOB nt_response,
+	enum netr_LogonInfoClass logon_type,
 	uint8_t *authoritative,
 	uint32_t *flags,
 	uint16_t *_validation_level,
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 97425e859f3..b2622a0e92e 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1520,6 +1520,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 				chal,
 				lm_response,
 				nt_response,
+				NetlogonNetworkInformation,
 				authoritative,
 				flags,
 				&validation_level,
-- 
2.13.6


From 37c1f19ca64df21ee69a0cd0e1f0f7917465680b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 12:02:05 +0100
Subject: [PATCH 07/37] winbindd: use
 Netlogon{Interactive,Network}TransitiveInformation on transitive trusts

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13234

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_pam.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index b2622a0e92e..52a24efc531 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1428,6 +1428,8 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 	int netr_attempts = 0;
 	bool retry = false;
 	NTSTATUS result;
+	enum netr_LogonInfoClass logon_type_i;
+	enum netr_LogonInfoClass logon_type_n;
 	uint16_t validation_level = UINT16_MAX;
 	union netr_Validation *validation = NULL;
 
@@ -1488,6 +1490,29 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 			}
 			return result;
 		}
+
+		logon_type_i = NetlogonInteractiveInformation;
+		logon_type_n = NetlogonNetworkInformation;
+		if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
+			logon_type_i = NetlogonInteractiveTransitiveInformation;
+			logon_type_n = NetlogonNetworkTransitiveInformation;
+		}
+
+		if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
+			logon_type_i = NetlogonInteractiveTransitiveInformation;
+			logon_type_n = NetlogonNetworkTransitiveInformation;
+		}
+
+		if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
+			logon_type_i = NetlogonInteractiveInformation;
+			logon_type_n = NetlogonNetworkInformation;
+		}
+
+		if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
+			logon_type_i = NetlogonInteractiveInformation;
+			logon_type_n = NetlogonNetworkInformation;
+		}
+
 		netr_attempts = 0;
 		if (domain->conn.netlogon_creds_ctx == NULL) {
 			DBG_NOTICE("No security credentials available for "
@@ -1503,7 +1528,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 				username,
 				password,
 				workstation,
-				NetlogonInteractiveInformation,
+				logon_type_i,
 				authoritative,
 				flags,
 				&validation_level,
@@ -1520,7 +1545,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 				chal,
 				lm_response,
 				nt_response,
-				NetlogonNetworkInformation,
+				logon_type_n,
 				authoritative,
 				flags,
 				&validation_level,
-- 
2.13.6


From 6fab781925b88ee3cfea4d1f89d31e2ff187ed78 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 12:03:11 +0100
Subject: [PATCH 08/37] winbindd: remove const from set_routing_domain()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13235

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd.h       | 2 +-
 source3/winbindd/winbindd_proto.h | 2 +-
 source3/winbindd/winbindd_util.c  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index 43c90445e87..3e4b256ef32 100644
--- a/source3/winbindd/winbindd.h
+++ b/source3/winbindd/winbindd.h
@@ -142,7 +142,7 @@ struct winbindd_domain {
 	uint32_t domain_flags;                   /* Domain flags from netlogon.h */
 	uint32_t domain_type;                    /* Domain type from netlogon.h */
 	uint32_t domain_trust_attribs;           /* Trust attribs from netlogon.h */
-	const struct winbindd_domain *routing_domain;
+	struct winbindd_domain *routing_domain;
 	bool initialized;		       /* Did we already ask for the domain mode? */
 	bool native_mode;                      /* is this a win2k domain in native mode ? */
 	bool active_directory;                 /* is this a win2k active directory ? */
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 9a52f6a4edb..49d44af97ff 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -439,7 +439,7 @@ NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
 struct winbindd_domain *domain_list(void);
 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain);
 bool set_routing_domain(struct winbindd_domain *domain,
-			const struct winbindd_domain *routing_domain);
+			struct winbindd_domain *routing_domain);
 bool add_trusted_domain_from_auth(uint16_t validation_level,
 				  struct info3_text *info3,
 				  struct info6_text *info6);
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index b20976c8048..876ee69a4b6 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -295,7 +295,7 @@ static NTSTATUS add_trusted_domain(const char *domain_name,
 }
 
 bool set_routing_domain(struct winbindd_domain *domain,
-			const struct winbindd_domain *routing_domain)
+			struct winbindd_domain *routing_domain)
 {
 	if (domain->routing_domain == NULL) {
 		domain->routing_domain = routing_domain;
-- 
2.13.6


From 70059cc7a496ff62d300ac86386f987f39d2a9bb Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 12:06:50 +0100
Subject: [PATCH 09/37] winbindd: prepare find_auth_domain() transitive trusts
 on a DC

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13235

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_pam.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 52a24efc531..a14b801cb94 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -395,8 +395,14 @@ struct winbindd_domain *find_auth_domain(uint8_t flags,
 			DEBUG(3, ("Authentication for domain [%s] refused "
 				  "as it is not a trusted domain\n",
 				  domain_name));
+			return NULL;
 		}
-		return domain;
+
+		if (domain->secure_channel_type != SEC_CHAN_NULL) {
+			return domain;
+		}
+
+		return domain->routing_domain;
 	}
 
 	if (strequal(domain_name, get_global_sam_name())) {
-- 
2.13.6


From e079b5c171cef84ce2cad37a5d82495d2ddd739a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 12:06:50 +0100
Subject: [PATCH 10/37] winbindd: prepare find_lookup_domain_from_{name,sid}()
 transitive trusts on a DC

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13235

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_util.c | 40 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 876ee69a4b6..c190ad26ddf 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -1488,15 +1488,31 @@ struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
 		return find_domain_from_sid(get_global_sam_sid());
 	}
 
-	/* A DC can't ask the local smbd for remote SIDs, here winbindd is the
-	 * one to contact the external DC's. On member servers the internal
-	 * domains are different: These are part of the local SAM. */
+	/*
+	 * On member servers the internal domains are different: These are part
+	 * of the local SAM.
+	 */
 
-	if (IS_DC || is_internal_domain(sid) || is_in_internal_domain(sid)) {
+	if (is_internal_domain(sid) || is_in_internal_domain(sid)) {
 		DEBUG(10, ("calling find_domain_from_sid\n"));
 		return find_domain_from_sid(sid);
 	}
 
+	if (IS_DC) {
+		struct winbindd_domain *domain = NULL;
+
+		domain = find_domain_from_sid_noinit(sid);
+		if (domain == NULL) {
+			return NULL;
+		}
+
+		if (domain->secure_channel_type != SEC_CHAN_NULL) {
+			return domain;
+		}
+
+		return domain->routing_domain;
+	}
+
 	/* On a member server a query for SID or name can always go to our
 	 * primary DC. */
 
@@ -1516,10 +1532,24 @@ struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
 		return find_domain_from_name_noinit( get_global_sam_name() );
 	}
 
-	if (IS_DC || strequal(domain_name, "BUILTIN") ||
+	if (strequal(domain_name, "BUILTIN") ||
 	    strequal(domain_name, get_global_sam_name()))
 		return find_domain_from_name_noinit(domain_name);
 
+	if (IS_DC) {
+		struct winbindd_domain *domain = NULL;
+
+		domain = find_domain_from_name_noinit(domain_name);
+		if (domain == NULL) {
+			return NULL;
+		}
+
+		if (domain->secure_channel_type != SEC_CHAN_NULL) {
+			return domain;
+		}
+
+		return domain->routing_domain;
+	}
 
 	return find_our_domain();
 }
-- 
2.13.6


From 0828d05445cd647376c7e3ee70dcf340e4254498 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 12:57:11 +0100
Subject: [PATCH 11/37] s3:rpc_client: pass down lsa_LookupNamesLevel to
 dcerpc_lsa_lookup_sids_generic()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13236

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/rpc_client/cli_lsarpc.c   | 10 +++++++++-
 source3/rpc_client/cli_lsarpc.h   |  1 +
 source3/winbindd/winbindd_msrpc.c |  2 ++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c
index 41c1ef482f4..65c6ca04d50 100644
--- a/source3/rpc_client/cli_lsarpc.c
+++ b/source3/rpc_client/cli_lsarpc.c
@@ -172,6 +172,7 @@ static NTSTATUS dcerpc_lsa_lookup_sids_noalloc(struct dcerpc_binding_handle *h,
 					       struct policy_handle *pol,
 					       int num_sids,
 					       const struct dom_sid *sids,
+					       enum lsa_LookupNamesLevel level,
 					       char **domains,
 					       char **names,
 					       enum lsa_SidType *types,
@@ -183,7 +184,6 @@ static NTSTATUS dcerpc_lsa_lookup_sids_noalloc(struct dcerpc_binding_handle *h,
 	struct lsa_SidArray sid_array;
 	struct lsa_RefDomainList *ref_domains = NULL;
 	struct lsa_TransNameArray lsa_names;
-	enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
 	uint32_t count = 0;
 	int i;
 
@@ -348,6 +348,7 @@ NTSTATUS dcerpc_lsa_lookup_sids_generic(struct dcerpc_binding_handle *h,
 					struct policy_handle *pol,
 					int num_sids,
 					const struct dom_sid *sids,
+					enum lsa_LookupNamesLevel level,
 					char ***pdomains,
 					char ***pnames,
 					enum lsa_SidType **ptypes,
@@ -414,6 +415,7 @@ NTSTATUS dcerpc_lsa_lookup_sids_generic(struct dcerpc_binding_handle *h,
 							pol,
 							hunk_num_sids,
 							hunk_sids,
+							level,
 							hunk_domains,
 							hunk_names,
 							hunk_types,
@@ -489,11 +491,13 @@ NTSTATUS dcerpc_lsa_lookup_sids(struct dcerpc_binding_handle *h,
 				enum lsa_SidType **ptypes,
 				NTSTATUS *result)
 {
+	enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
 	return dcerpc_lsa_lookup_sids_generic(h,
 					      mem_ctx,
 					      pol,
 					      num_sids,
 					      sids,
+					      level,
 					      pdomains,
 					      pnames,
 					      ptypes,
@@ -512,12 +516,14 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
 {
 	NTSTATUS status;
 	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+	enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
 
 	status = dcerpc_lsa_lookup_sids_generic(cli->binding_handle,
 						mem_ctx,
 						pol,
 						num_sids,
 						sids,
+						level,
 						pdomains,
 						pnames,
 						ptypes,
@@ -540,11 +546,13 @@ NTSTATUS dcerpc_lsa_lookup_sids3(struct dcerpc_binding_handle *h,
 				 enum lsa_SidType **ptypes,
 				 NTSTATUS *result)
 {
+	enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
 	return dcerpc_lsa_lookup_sids_generic(h,
 					      mem_ctx,
 					      pol,
 					      num_sids,
 					      sids,
+					      level,
 					      pdomains,
 					      pnames,
 					      ptypes,
diff --git a/source3/rpc_client/cli_lsarpc.h b/source3/rpc_client/cli_lsarpc.h
index 4f9464d5b05..f716b049e12 100644
--- a/source3/rpc_client/cli_lsarpc.h
+++ b/source3/rpc_client/cli_lsarpc.h
@@ -130,6 +130,7 @@ NTSTATUS dcerpc_lsa_lookup_sids_generic(struct dcerpc_binding_handle *h,
 					struct policy_handle *pol,
 					int num_sids,
 					const struct dom_sid *sids,
+					enum lsa_LookupNamesLevel level,
 					char ***pdomains,
 					char ***pnames,
 					enum lsa_SidType **ptypes,
diff --git a/source3/winbindd/winbindd_msrpc.c b/source3/winbindd/winbindd_msrpc.c
index 9bf4354f4e3..bc27a39c08f 100644
--- a/source3/winbindd/winbindd_msrpc.c
+++ b/source3/winbindd/winbindd_msrpc.c
@@ -999,6 +999,7 @@ NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
 	unsigned int orig_timeout;
 	bool use_lookupsids3 = false;
 	bool retried = false;
+	enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
 
  connect:
 	status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
@@ -1024,6 +1025,7 @@ NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
 						&lsa_policy,
 						num_sids,
 						sids,
+						level,
 						domains,
 						names,
 						types,
-- 
2.13.6


From 3b506b3e74b389a8470d139d2ed28563db191205 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 Jan 2018 13:02:04 +0100
Subject: [PATCH 12/37] winbindd: don't force using LSA_LOOKUP_NAMES_ALL for
 non workstation trusts.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13236

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_msrpc.c | 61 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 60 insertions(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd_msrpc.c b/source3/winbindd/winbindd_msrpc.c
index bc27a39c08f..eb400f0ebf3 100644
--- a/source3/winbindd/winbindd_msrpc.c
+++ b/source3/winbindd/winbindd_msrpc.c
@@ -983,6 +983,60 @@ static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
 	return status;
 }
 
+static enum lsa_LookupNamesLevel winbindd_lookup_level(
+	struct winbindd_domain *domain)
+{
+	enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_DOMAINS_ONLY;
+
+	if (domain->internal) {
+		level = LSA_LOOKUP_NAMES_ALL;
+	} else if (domain->secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
+		if (domain->domain_flags & NETR_TRUST_FLAG_IN_FOREST) {
+			/*
+			 * TODO:
+			 *
+			 * Depending on what we want to resolve. We need to use:
+			 * 1. LsapLookupXForestReferral(5)/LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY
+			 *    if we want to pass the request into the direction of the forest
+			 *    root domain. The forest root domain uses
+			 *    LsapLookupXForestResolve(6)/LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2
+			 *    when passing the request to trusted forests.
+			 * 2. LsapLookupGC(4)/LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY
+			 *    if we're not a GC and want to resolve a name within our own forest.
+			 *
+			 * As we don't support more than one domain in our own forest
+			 * and always try to be a GC for now, we just set
+			 * LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY.
+			 */
+			level = LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY;
+		} else if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
+			/*
+			 * This is LsapLookupXForestResolve(6)/LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2
+			 */
+			level = LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2;
+		} else {
+			/*
+			 * This is LsapLookupTDL(3)/LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY
+			 */
+			level = LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY;
+		}
+	} else if (domain->secure_channel_type == SEC_CHAN_DOMAIN) {
+		/*
+		 * This is LsapLookupTDL(3)/LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY
+		 */
+		level = LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY;
+	} else if (domain->rodc) {
+		level = LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC;
+	} else {
+		/*
+		 * This is LsapLookupPDC(2)/LSA_LOOKUP_NAMES_DOMAINS_ONLY
+		 */
+		level = LSA_LOOKUP_NAMES_DOMAINS_ONLY;
+	}
+
+	return level;
+}
+
 NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
 			      struct winbindd_domain *domain,
 			      uint32_t num_sids,
@@ -1013,6 +1067,8 @@ NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
 		use_lookupsids3 = true;
 	}
 
+	level = winbindd_lookup_level(domain);
+
 	/*
 	 * This call can take a long time
 	 * allow the server to time out.
@@ -1076,6 +1132,7 @@ static NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
 	unsigned int orig_timeout = 0;
 	bool use_lookupnames4 = false;
 	bool retried = false;
+	enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
 
  connect:
 	status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
@@ -1089,6 +1146,8 @@ static NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
 		use_lookupnames4 = true;
 	}
 
+	level = winbindd_lookup_level(domain);
+
 	/*
 	 * This call can take a long time
 	 * allow the server to time out.
@@ -1102,7 +1161,7 @@ static NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
 						 num_names,
 						 (const char **) names,
 						 domains,
-						 1,
+						 level,
 						 sids,
 						 types,
 						 use_lookupnames4,
-- 
2.13.6


From 47841d79c383052d4479da8c084ba8827755a085 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 18 Jan 2018 11:28:20 +0100
Subject: [PATCH 13/37] winbindd: move loading of trusted domains on a DC to a
 seperate function

This allows using the split out function in a subsequent commit in the
MSG_WINBIND_NEW_TRUSTED_DOMAIN message handler.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13237

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/winbindd/winbindd_util.c | 400 ++++++++++++++++++++-------------------
 1 file changed, 207 insertions(+), 193 deletions(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index c190ad26ddf..600abe6deac 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -918,6 +918,203 @@ static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
 	return true;
 }
 
+static bool add_trusted_domains_dc(void)
+{
+	struct winbindd_domain *domain =  NULL;
+	struct pdb_trusted_domain **domains = NULL;
+	uint32_t num_domains = 0;
+	uint32_t i;
+	NTSTATUS status;
+
+	if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
+		struct trustdom_info **ti = NULL;
+
+		status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
+				nt_errstr(status));
+			return false;
+		}
+
+		for (i = 0; i < num_domains; i++) {
+			status = add_trusted_domain(ti[i]->name,
+						    NULL,
+						    &ti[i]->sid,
+						    LSA_TRUST_TYPE_DOWNLEVEL,
+						    NETR_TRUST_FLAG_OUTBOUND,
+						    0,
+						    SEC_CHAN_DOMAIN,
+						    NULL,
+						    &domain);
+			if (!NT_STATUS_IS_OK(status)) {
+				DBG_NOTICE("add_trusted_domain returned %s\n",
+					   nt_errstr(status));
+				return false;
+			}
+
+			/* Even in the parent winbindd we'll need to
+			   talk to the DC, so try and see if we can
+			   contact it. Theoretically this isn't neccessary
+			   as the init_dc_connection() in init_child_recv()
+			   will do this, but we can start detecting the DC
+			   early here. */
+			set_domain_online_request(domain);
+		}
+
+		return true;
+	}
+
+	status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
+			nt_errstr(status));
+		return false;
+	}
+
+	for (i = 0; i < num_domains; i++) {
+		enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
+		uint32_t trust_flags = 0;
+
+		if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
+			sec_chan_type = SEC_CHAN_DNS_DOMAIN;
+		}
+
+		if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
+			sec_chan_type = SEC_CHAN_NULL;
+		}
+
+		if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
+			trust_flags |= NETR_TRUST_FLAG_INBOUND;
+		}
+		if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
+			trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
+		}
+		if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
+			trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
+		}
+
+		status = add_trusted_domain(domains[i]->netbios_name,
+					    domains[i]->domain_name,
+					    &domains[i]->security_identifier,
+					    domains[i]->trust_type,
+					    trust_flags,
+					    domains[i]->trust_attributes,
+					    sec_chan_type,
+					    NULL,
+					    &domain);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_NOTICE("add_trusted_domain returned %s\n",
+				   nt_errstr(status));
+			return false;
+		}
+
+		if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
+			domain->active_directory = true;
+		}
+		domain->domain_type = domains[i]->trust_type;
+		domain->domain_trust_attribs = domains[i]->trust_attributes;
+
+		if (sec_chan_type != SEC_CHAN_NULL) {
+			/* Even in the parent winbindd we'll need to
+			   talk to the DC, so try and see if we can
+			   contact it. Theoretically this isn't neccessary
+			   as the init_dc_connection() in init_child_recv()
+			   will do this, but we can start detecting the DC
+			   early here. */
+			set_domain_online_request(domain);
+		}
+	}
+
+	for (i = 0; i < num_domains; i++) {
+		struct ForestTrustInfo fti;
+		uint32_t fi;
+		enum ndr_err_code ndr_err;
+		struct winbindd_domain *routing_domain = NULL;
+
+		if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
+			continue;
+		}
+
+		if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
+			continue;
+		}
+
+		if (domains[i]->trust_forest_trust_info.length == 0) {
+			continue;
+		}
+
+		routing_domain = find_domain_from_name_noinit(
+			domains[i]->netbios_name);
+		if (routing_domain == NULL) {
+			DBG_ERR("Can't find winbindd domain [%s]\n",
+				domains[i]->netbios_name);
+			return false;
+		}
+
+		ndr_err = ndr_pull_struct_blob_all(
+			&domains[i]->trust_forest_trust_info,
+			talloc_tos(), &fti,
+			(ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
+				domains[i]->netbios_name,
+				ndr_map_error2string(ndr_err));
+			return false;
+		}
+
+		for (fi = 0; fi < fti.count; fi++) {
+			struct ForestTrustInfoRecord *rec =
+				&fti.records[fi].record;
+			struct ForestTrustDataDomainInfo *drec = NULL;
+
+			if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
+				continue;
+			}
+			drec = &rec->data.info;
+
+			if (rec->flags & LSA_NB_DISABLED_MASK) {
+				continue;
+			}
+
+			if (rec->flags & LSA_SID_DISABLED_MASK) {
+				continue;
+			}
+
+			/*
+			 * TODO:
+			 * also try to find a matching
+			 * LSA_TLN_DISABLED_MASK ???
+			 */
+
+			domain = find_domain_from_name_noinit(drec->netbios_name.string);
+			if (domain != NULL) {
+				continue;
+			}
+
+			status = add_trusted_domain(drec->netbios_name.string,
+						    drec->dns_name.string,
+						    &drec->sid,
+						    LSA_TRUST_TYPE_UPLEVEL,
+						    NETR_TRUST_FLAG_OUTBOUND,
+						    0,
+						    SEC_CHAN_NULL,
+						    routing_domain,
+						    &domain);
+			if (!NT_STATUS_IS_OK(status)) {
+				DBG_NOTICE("add_trusted_domain returned %s\n",
+					   nt_errstr(status));
+				return false;
+			}
+			if (domain == NULL) {
+				continue;
+			}
+		}
+	}
+
+	return true;
+}
+
+
 /* Look up global info for the winbind daemon */
 bool init_domain_list(void)
 {
@@ -925,6 +1122,7 @@ bool init_domain_list(void)
 	struct pdb_domain_info *pdb_domain_info = NULL;
 	struct winbindd_domain *domain =  NULL;
 	NTSTATUS status;
+	bool ok;
 
 	/* Free existing list */
 	free_domain_list();
@@ -965,7 +1163,6 @@ bool init_domain_list(void)
 		enum netr_SchannelType sec_chan_type;
 		const char *account_name;
 		struct samr_Password current_nt_hash;
-		bool ok;
 
 		if (pdb_domain_info == NULL) {
 			DEBUG(0, ("Failed to fetch our own, local AD "
@@ -1071,7 +1268,14 @@ bool init_domain_list(void)
 			return false;
 		}
 	}
-	/* Add ourselves as the first entry. */
+
+	if (IS_DC) {
+		ok = add_trusted_domains_dc();
+		if (!ok) {
+			DBG_ERR("init_domain_list_dc failed\n");
+			return false;
+		}
+	}
 
 	if ( role == ROLE_DOMAIN_MEMBER ) {
 		struct dom_sid our_sid;
@@ -1113,201 +1317,11 @@ bool init_domain_list(void)
 
 	}
 
-	if (IS_DC && (pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
-		uint32_t num_domains = 0;
-		struct pdb_trusted_domain **domains = NULL;
-		uint32_t i;
-
-		status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
-		if (!NT_STATUS_IS_OK(status)) {
-			DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
-				nt_errstr(status));
-			return false;
-		}
-
-		for (i = 0; i < num_domains; i++) {
-			enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
-			uint32_t trust_flags = 0;
-
-			if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
-				sec_chan_type = SEC_CHAN_DNS_DOMAIN;
-			}
-
-			if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
-				sec_chan_type = SEC_CHAN_NULL;
-			}
-
-			if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
-				trust_flags |= NETR_TRUST_FLAG_INBOUND;
-			}
-			if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
-				trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
-			}
-			if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
-				trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
-			}
-
-			status = add_trusted_domain(domains[i]->netbios_name,
-						    domains[i]->domain_name,
-						    &domains[i]->security_identifier,
-						    domains[i]->trust_type,
-						    trust_flags,
-						    domains[i]->trust_attributes,
-						    sec_chan_type,
-						    NULL,
-						    &domain);
-			if (!NT_STATUS_IS_OK(status)) {
-				DBG_NOTICE("add_trusted_domain returned %s\n",
-					   nt_errstr(status));
-				return false;
-			}
-
-			if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
-				domain->active_directory = true;
-			}
-			domain->domain_type = domains[i]->trust_type;
-			domain->domain_trust_attribs = domains[i]->trust_attributes;
-
-			if (sec_chan_type != SEC_CHAN_NULL) {
-				/* Even in the parent winbindd we'll need to
-				   talk to the DC, so try and see if we can
-				   contact it. Theoretically this isn't neccessary
-				   as the init_dc_connection() in init_child_recv()
-				   will do this, but we can start detecting the DC
-				   early here. */
-				set_domain_online_request(domain);
-			}
-		}
-
-		for (i = 0; i < num_domains; i++) {
-			struct ForestTrustInfo fti;
-			uint32_t fi;
-			enum ndr_err_code ndr_err;
-			struct winbindd_domain *routing_domain = NULL;
-
-			if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
-				continue;
-			}
-
-			if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
-				continue;
-			}
-
-			if (domains[i]->trust_forest_trust_info.length == 0) {
-				continue;
-			}
-
-			routing_domain = find_domain_from_name_noinit(
-				domains[i]->netbios_name);
-			if (routing_domain == NULL) {
-				DBG_ERR("Can't find winbindd domain [%s]\n",
-					domains[i]->netbios_name);
-				return false;
-			}
-
-			ndr_err = ndr_pull_struct_blob_all(
-					&domains[i]->trust_forest_trust_info,
-					talloc_tos(), &fti,
-					(ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
-			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-				DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
-					domains[i]->netbios_name,
-					ndr_map_error2string(ndr_err));
-				return false;
-			}
-
-			for (fi = 0; fi < fti.count; fi++) {
-				struct ForestTrustInfoRecord *rec =
-					&fti.records[fi].record;
-				struct ForestTrustDataDomainInfo *drec = NULL;
-
-				if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
-					continue;
-				}
-				drec = &rec->data.info;
-
-				if (rec->flags & LSA_NB_DISABLED_MASK) {
-					continue;
-				}
-
-				if (rec->flags & LSA_SID_DISABLED_MASK) {
-					continue;
-				}
-
-				/*
-				 * TODO:
-				 * also try to find a matching
-				 * LSA_TLN_DISABLED_MASK ???
-				 */
-
-				domain = find_domain_from_name_noinit(drec->netbios_name.string);
-				if (domain != NULL) {
-					continue;
-				}
-
-				status = add_trusted_domain(drec->netbios_name.string,
-							    drec->dns_name.string,
-							    &drec->sid,
-							    LSA_TRUST_TYPE_UPLEVEL,
-							    NETR_TRUST_FLAG_OUTBOUND,
-							    0,
-							    SEC_CHAN_NULL,
-							    routing_domain,
-							    &domain);
-				if (!NT_STATUS_IS_OK(status)) {
-					DBG_NOTICE("add_trusted_domain returned %s\n",
-						   nt_errstr(status));
-					return false;
-				}
-				if (domain == NULL) {
-					continue;
-				}
-			}
-		}
-	} else if (IS_DC) {
-		uint32_t num_domains = 0;
-		struct trustdom_info **domains = NULL;
-		uint32_t i;
-
-		status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &domains);
-		if (!NT_STATUS_IS_OK(status)) {
-			DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
-				nt_errstr(status));
-			return false;
-		}
-
-		for (i = 0; i < num_domains; i++) {
-			status = add_trusted_domain(domains[i]->name,
-						    NULL,
-						    &domains[i]->sid,
-						    LSA_TRUST_TYPE_DOWNLEVEL,
-						    NETR_TRUST_FLAG_OUTBOUND,
-						    0,
-						    SEC_CHAN_DOMAIN,
-						    NULL,
-						    &domain);
-			if (!NT_STATUS_IS_OK(status)) {
-				DBG_NOTICE("add_trusted_domain returned %s\n",
-					   nt_errstr(status));
-				return false;
-			}
-
-			/* Even in the parent winbindd we'll need to
-			   talk to the DC, so try and see if we can
-			   contact it. Theoretically this isn't neccessary
-			   as the init_dc_connection() in init_child_recv()
-			   will do this, but we can start detecting the DC
-			   early here. */
-			set_domain_online_request(domain);
-		}
-	}
-
 	status = imessaging_register(winbind_imessaging_context(), NULL,
 				     MSG_WINBIND_NEW_TRUSTED_DOMAIN,
 				     wb_imsg_new_trusted_domain);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0, ("imessaging_register(MSG_WINBIND_NEW_TRUSTED_DOMAIN) - %s\n",
-			  nt_errstr(status)));
+		DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
 		return false;
 	}
 
-- 
2.13.6


From aec89aac882058d13750d60fdaaa6c15fa0be227 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 18 Jan 2018 11:30:53 +0100
Subject: [PATCH 14/37] winbindd: use add_trusted_domains_dc in
 wb_imsg_new_trusted_domain

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13237

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/winbindd/winbindd_util.c | 63 ++++------------------------------------
 1 file changed, 6 insertions(+), 57 deletions(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 600abe6deac..a4d912d2ca1 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -43,6 +43,7 @@
  * Winbind daemon for NT domain authentication nss module.
  **/
 
+static bool add_trusted_domains_dc(void);
 
 /* The list of trusted domains.  Note that the list can be deleted and
    recreated using the init_domain_list() function so pointers to
@@ -813,66 +814,14 @@ static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
 				       struct server_id server_id,
 				       DATA_BLOB *data)
 {
-	TALLOC_CTX *frame = talloc_stackframe();
-	enum netr_SchannelType secure_channel_type = SEC_CHAN_DOMAIN;
-	struct lsa_TrustDomainInfoInfoEx info;
-	enum ndr_err_code ndr_err;
-	struct winbindd_domain *d = NULL;
-	uint32_t trust_flags = 0;
-	NTSTATUS status;
-
-	DEBUG(5, ("wb_imsg_new_trusted_domain\n"));
-
-	if (data == NULL) {
-		TALLOC_FREE(frame);
-		return;
-	}
+	bool ok;
 
-	ndr_err = ndr_pull_struct_blob_all(data, frame, &info,
-			(ndr_pull_flags_fn_t)ndr_pull_lsa_TrustDomainInfoInfoEx);
-	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-		TALLOC_FREE(frame);
-		return;
-	}
+	DBG_NOTICE("Rescanning trusted domains\n");
 
-	d = find_domain_from_name_noinit(info.netbios_name.string);
-	if (d != NULL) {
-		TALLOC_FREE(frame);
-		return;
-	}
-
-	if (info.trust_type == LSA_TRUST_TYPE_UPLEVEL) {
-		secure_channel_type = SEC_CHAN_DNS_DOMAIN;
-	}
-	if (info.trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
-		trust_flags |= NETR_TRUST_FLAG_INBOUND;
-	}
-	if (info.trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
-		trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
-	}
-	if (info.trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
-		trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
-	}
-
-	status = add_trusted_domain(info.netbios_name.string,
-				    info.domain_name.string,
-				    info.sid,
-				    info.trust_type,
-				    trust_flags,
-				    info.trust_attributes,
-				    secure_channel_type,
-				    find_default_route_domain(),
-				    &d);
-	if (!NT_STATUS_IS_OK(status) &&
-	    !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
-	{
-		DBG_NOTICE("add_trusted_domain returned %s\n",
-			   nt_errstr(status));
-		TALLOC_FREE(frame);
-		return;
+	ok = add_trusted_domains_dc();
+	if (!ok) {
+		DBG_ERR("Failed to reload trusted domains\n");
 	}
-
-	TALLOC_FREE(frame);
 }
 
 /*
-- 
2.13.6


From ac835983d741920e976c0adc1be96889d9d0d39c Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 18 Jan 2018 11:32:30 +0100
Subject: [PATCH 15/37] s4/rpc_server: remove unused data argument from
 MSG_WINBIND_NEW_TRUSTED_DOMAIN

winbindd doesn't use that data anymore.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13237

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source4/rpc_server/lsa/dcesrv_lsa.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index 8b212222bc9..b2115fd49f9 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -1360,15 +1360,8 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
 				     "winbind_server",
 				     &num_server_ids, &server_ids);
 	if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
-		enum ndr_err_code ndr_err;
-		DATA_BLOB b = {};
-
-		ndr_err = ndr_push_struct_blob(&b, mem_ctx, r->in.info,
-			(ndr_push_flags_fn_t)ndr_push_lsa_TrustDomainInfoInfoEx);
-		if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-			imessaging_send(dce_call->msg_ctx, server_ids[0],
-				MSG_WINBIND_NEW_TRUSTED_DOMAIN, &b);
-		}
+		imessaging_send(dce_call->msg_ctx, server_ids[0],
+				MSG_WINBIND_NEW_TRUSTED_DOMAIN, NULL);
 	}
 	TALLOC_FREE(server_ids);
 
-- 
2.13.6


From 5593cb2fc7d7332b885cd170e0e9f64b4699c827 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 18 Jan 2018 16:35:13 +0100
Subject: [PATCH 16/37] winbindd: rename MSG_WINBIND_NEW_TRUSTED_DOMAIN to
 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS

This reflects the new implementation in winbindd.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13237

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 librpc/idl/messaging.idl            | 2 +-
 source3/winbindd/winbindd_util.c    | 2 +-
 source4/rpc_server/lsa/dcesrv_lsa.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl
index 37f8fccfb8d..b35f1e1e9ae 100644
--- a/librpc/idl/messaging.idl
+++ b/librpc/idl/messaging.idl
@@ -123,7 +123,7 @@ interface messaging
 		MSG_WINBIND_IP_DROPPED		= 0x040A,
 		MSG_WINBIND_DOMAIN_ONLINE	= 0x040B,
 		MSG_WINBIND_DOMAIN_OFFLINE	= 0x040C,
-		MSG_WINBIND_NEW_TRUSTED_DOMAIN	= 0x040D,
+		MSG_WINBIND_RELOAD_TRUSTED_DOMAINS = 0x040D,
 
 		/* event messages */
 		MSG_DUMP_EVENT_LIST		= 0x0500,
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index a4d912d2ca1..05c963f858f 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -1267,7 +1267,7 @@ bool init_domain_list(void)
 	}
 
 	status = imessaging_register(winbind_imessaging_context(), NULL,
-				     MSG_WINBIND_NEW_TRUSTED_DOMAIN,
+				     MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
 				     wb_imsg_new_trusted_domain);
 	if (!NT_STATUS_IS_OK(status)) {
 		DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index b2115fd49f9..4424b5667b7 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -1361,7 +1361,7 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
 				     &num_server_ids, &server_ids);
 	if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
 		imessaging_send(dce_call->msg_ctx, server_ids[0],
-				MSG_WINBIND_NEW_TRUSTED_DOMAIN, NULL);
+				MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
 	}
 	TALLOC_FREE(server_ids);
 
-- 
2.13.6


From 75726f0800c503520e68d600d023199b39f67bee Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 18 Jan 2018 16:35:52 +0100
Subject: [PATCH 17/37] s4/rpc_server: trigger trusts reload in winbindd after
 successfull trust info acquisition

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13237

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source4/rpc_server/lsa/dcesrv_lsa.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index 4424b5667b7..9714e74a720 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -4363,6 +4363,8 @@ static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_stat
 	struct lsa_ForestTrustCollisionInfo *c_info = NULL;
 	DATA_BLOB ft_blob = {};
 	struct ldb_message *msg = NULL;
+	struct server_id *server_ids = NULL;
+	uint32_t num_server_ids = 0;
 	NTSTATUS status;
 	enum ndr_err_code ndr_err;
 	int ret;
@@ -4602,6 +4604,21 @@ static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_stat
 		goto done;
 	}
 
+	/*
+	 * Notify winbindd that we have a acquired forest trust info
+	 */
+	status = irpc_servers_byname(dce_call->msg_ctx,
+				     mem_ctx,
+				     "winbind_server",
+				     &num_server_ids, &server_ids);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("irpc_servers_byname failed\n");
+		goto done;
+	}
+
+	imessaging_send(dce_call->msg_ctx, server_ids[0],
+			MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
+
 	status = NT_STATUS_OK;
 
 done:
-- 
2.13.6


From e18c87d8b7d24108f277d3c0f459474ba611f99c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 31 Jan 2018 08:22:07 +0100
Subject: [PATCH 18/37] winbindd: fix debug message in
 find_default_route_domain() on a DC

As we don't support multiple domains in a forest yet,
we don't need to print a warning a log level 0.

This also adds a missing \n.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13255

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 05c963f858f..5f4f905db4c 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -1426,7 +1426,7 @@ struct winbindd_domain *find_default_route_domain(void)
 	if (!IS_DC) {
 		return find_our_domain();
 	}
-	DBG_ERR("Routing logic not yet implemented on a DC");
+	DBG_DEBUG("Routing logic not yet implemented on a DC\n");
 	return NULL;
 }
 
-- 
2.13.6


From dc519b1d8cd1ae987f1eac6a8f42a081eb1d4050 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sun, 4 Feb 2018 22:48:01 +0100
Subject: [PATCH 19/37] wbinfo: avoid segfault in wbinfo_auth_crap() if
 winbindd is not available

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13256

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 nsswitch/wbinfo.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/nsswitch/wbinfo.c b/nsswitch/wbinfo.c
index 54d5758aa6c..82863c26760 100644
--- a/nsswitch/wbinfo.c
+++ b/nsswitch/wbinfo.c
@@ -1798,13 +1798,22 @@ static bool wbinfo_auth_crap(char *username, bool use_ntlmv2, bool use_lanman)
 	if (use_ntlmv2) {
 		DATA_BLOB server_chal;
 		DATA_BLOB names_blob;
+		const char *netbios_name = NULL;
+		const char *domain = NULL;
+
+		netbios_name = get_winbind_netbios_name(),
+		domain = get_winbind_domain();
+		if (domain == NULL) {
+			d_fprintf(stderr, "Failed to get domain from winbindd\n");
+			return false;
+		}
 
 		server_chal = data_blob(params.password.response.challenge, 8);
 
 		/* Pretend this is a login to 'us', for blob purposes */
 		names_blob = NTLMv2_generate_names_blob(NULL,
-						get_winbind_netbios_name(),
-						get_winbind_domain());
+							netbios_name,
+							domain);
 
 		if (pass != NULL &&
 		    !SMBNTLMv2encrypt(NULL, name_user, name_domain, pass,
-- 
2.13.6


From ab243bf5ba648f8886273c86379c3ffe2d2d72e7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 23:19:32 +0100
Subject: [PATCH 20/37] winbindd: add_trusted_domain_from_auth() should not use
 dns_name = ""

Check whether the DNS domain name in the info6 struct is actually more
then just an empty string. If it is we want to call add_trusted_domain()
with NULL as DNS domain name argument.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13257

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_util.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 5f4f905db4c..6292cce9d51 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -336,7 +336,9 @@ bool add_trusted_domain_from_auth(uint16_t validation_level,
 	}
 
 	if (validation_level == 6) {
-		dns_domainname = &info6->dns_domainname[0];
+		if (!strequal(info6->dns_domainname, "")) {
+			dns_domainname = info6->dns_domainname;
+		}
 	}
 
 	status = add_trusted_domain(info3->logon_dom,
-- 
2.13.6


From b2e92b948da780a46f1917df467fc2cb08c18a9a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 9 Feb 2018 16:15:18 +0100
Subject: [PATCH 21/37] s3/rpc_client: add rpccli_netlogon_interactive_logon()

This will be used in a subsequent commit.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13258

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/rpc_client/cli_netlogon.c | 112 ++++++++++++++++++++++++++++++++++++++
 source3/rpc_client/cli_netlogon.h |  15 +++++
 2 files changed, 127 insertions(+)

diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index d8ccce72e0d..2aa0f5e7b1c 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -701,3 +701,115 @@ NTSTATUS rpccli_netlogon_network_logon(
 
 	return NT_STATUS_OK;
 }
+
+NTSTATUS rpccli_netlogon_interactive_logon(
+	struct netlogon_creds_cli_context *creds_ctx,
+	struct dcerpc_binding_handle *binding_handle,
+	TALLOC_CTX *mem_ctx,
+	uint32_t logon_parameters,
+	const char *username,
+	const char *domain,
+	const char *workstation,
+	DATA_BLOB lm_hash,
+	DATA_BLOB nt_hash,
+	enum netr_LogonInfoClass logon_type,
+	uint8_t *authoritative,
+	uint32_t *flags,
+	uint16_t *_validation_level,
+	union netr_Validation **_validation)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	NTSTATUS status;
+	const char *workstation_name_slash;
+	union netr_LogonLevel *logon = NULL;
+	struct netr_PasswordInfo *password_info = NULL;
+	uint16_t validation_level = 0;
+	union netr_Validation *validation = NULL;
+	struct netr_ChallengeResponse lm;
+	struct netr_ChallengeResponse nt;
+
+	*_validation = NULL;
+
+	ZERO_STRUCT(lm);
+	ZERO_STRUCT(nt);
+
+	switch (logon_type) {
+	case NetlogonInteractiveInformation:
+	case NetlogonInteractiveTransitiveInformation:
+		break;
+	default:
+		DEBUG(0, ("switch value %d not supported\n",
+			logon_type));
+		TALLOC_FREE(frame);
+		return NT_STATUS_INVALID_INFO_CLASS;
+	}
+
+	logon = talloc_zero(mem_ctx, union netr_LogonLevel);
+	if (logon == NULL) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	password_info = talloc_zero(logon, struct netr_PasswordInfo);
+	if (password_info == NULL) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if (workstation[0] != '\\' && workstation[1] != '\\') {
+		workstation_name_slash = talloc_asprintf(frame, "\\\\%s", workstation);
+	} else {
+		workstation_name_slash = workstation;
+	}
+
+	if (workstation_name_slash == NULL) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/* Initialise input parameters */
+
+	password_info->identity_info.domain_name.string		= domain;
+	password_info->identity_info.parameter_control		= logon_parameters;
+	password_info->identity_info.logon_id_low		= 0xdead;
+	password_info->identity_info.logon_id_high		= 0xbeef;
+	password_info->identity_info.account_name.string	= username;
+	password_info->identity_info.workstation.string		= workstation_name_slash;
+
+	if (nt_hash.length != sizeof(password_info->ntpassword.hash)) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	memcpy(password_info->ntpassword.hash, nt_hash.data, nt_hash.length);
+	if (lm_hash.length != 0) {
+		if (lm_hash.length != sizeof(password_info->lmpassword.hash)) {
+			TALLOC_FREE(frame);
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+		memcpy(password_info->lmpassword.hash, lm_hash.data, lm_hash.length);
+	}
+
+	logon->password = password_info;
+
+	/* Marshall data and send request */
+
+	status = netlogon_creds_cli_LogonSamLogon(creds_ctx,
+						  binding_handle,
+						  logon_type,
+						  logon,
+						  mem_ctx,
+						  &validation_level,
+						  &validation,
+						  authoritative,
+						  flags);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(frame);
+		return status;
+	}
+
+	*_validation_level = validation_level;
+	*_validation = validation;
+
+	TALLOC_FREE(frame);
+	return NT_STATUS_OK;
+}
diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h
index dc04c0b0676..d0232b51d98 100644
--- a/source3/rpc_client/cli_netlogon.h
+++ b/source3/rpc_client/cli_netlogon.h
@@ -89,5 +89,20 @@ NTSTATUS rpccli_netlogon_network_logon(
 	uint32_t *flags,
 	uint16_t *_validation_level,
 	union netr_Validation **_validation);
+NTSTATUS rpccli_netlogon_interactive_logon(
+	struct netlogon_creds_cli_context *creds_ctx,
+	struct dcerpc_binding_handle *binding_handle,
+	TALLOC_CTX *mem_ctx,
+	uint32_t logon_parameters,
+	const char *username,
+	const char *domain,
+	const char *workstation,
+	DATA_BLOB lm_hash,
+	DATA_BLOB nt_hash,
+	enum netr_LogonInfoClass logon_type,
+	uint8_t *authoritative,
+	uint32_t *flags,
+	uint16_t *_validation_level,
+	union netr_Validation **_validation);
 
 #endif /* _RPC_CLIENT_CLI_NETLOGON_H_ */
-- 
2.13.6


From 765394668df88d1ef9fb619c9271ea6b086560f3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 16:36:45 +0100
Subject: [PATCH 22/37] winbindd: separate plaintext given and interactive in
 winbind_samlogon_retry_loop()

We need to handle 4 cases:

plaintext_given=true  interactive=true
plaintext_given=false interactive=true
plaintext_given=true  interactive=false
plaintext_given=false interactive=false

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13258

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_pam.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index a14b801cb94..c618b7a1a24 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1421,6 +1421,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 					    const char *password,
 					    const char *domainname,
 					    const char *workstation,
+					    bool plaintext_given,
 					    const uint8_t chal[8],
 					    DATA_BLOB lm_response,
 					    DATA_BLOB nt_response,
@@ -1524,7 +1525,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 			DBG_NOTICE("No security credentials available for "
 				  "domain [%s]\n", domainname);
 			result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-		} else if (interactive) {
+		} else if (plaintext_given) {
 			result = rpccli_netlogon_password_logon(
 				domain->conn.netlogon_creds_ctx,
 				netlogon_pipe->binding_handle,
@@ -1539,6 +1540,22 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 				flags,
 				&validation_level,
 				&validation);
+		} else if (interactive) {
+			result = rpccli_netlogon_interactive_logon(
+				domain->conn.netlogon_creds_ctx,
+				netlogon_pipe->binding_handle,
+				mem_ctx,
+				logon_parameters,
+				username,
+				domainname,
+				workstation,
+				lm_response,
+				nt_response,
+				logon_type_i,
+				authoritative,
+				flags,
+				&validation_level,
+				&validation);
 		} else {
 			result = rpccli_netlogon_network_logon(
 				domain->conn.netlogon_creds_ctx,
@@ -1745,6 +1762,7 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(
 					     pass,
 					     name_domain,
 					     lp_netbios_name(),
+					     true, /* plaintext_given */
 					     NULL,
 					     data_blob_null, data_blob_null,
 					     true, /* interactive */
@@ -2251,6 +2269,7 @@ NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
 					     name_domain,
 					     /* Bug #3248 - found by Stefan Burkei. */
 					     workstation, /* We carefully set this above so use it... */
+					     false, /* plaintext_given */
 					     chal,
 					     lm_response,
 					     nt_response,
-- 
2.13.6


From 239dccb1715a11b8ef75154da0a73c2b9cf2fcd1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 8 Feb 2018 17:23:49 +0100
Subject: [PATCH 23/37] winbindd: add a comment to a parameter in
 _winbind_SamLogon()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13258

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_dual_srv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index c76531ddb5d..2775a1569e1 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -898,7 +898,7 @@ NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
 				       r->in.logon.network->challenge,
 				       lm_response, nt_response,
 				       &r->out.authoritative,
-				       true,
+				       true, /* skip_sam */
 				       &flags,
 				       &validation_level,
 				       &validation);
-- 
2.13.6


From 2ab6299875cb7ced70205aabbed386abcc95702c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 17:37:54 +0100
Subject: [PATCH 24/37] winbindd: pass 'bool interactive' to
 winbind_dual_SamLogon()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13258

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_dual_srv.c | 1 +
 source3/winbindd/winbindd_pam.c      | 6 ++++--
 source3/winbindd/winbindd_proto.h    | 1 +
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 2775a1569e1..4ac38ff19d2 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -891,6 +891,7 @@ NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
 	nt_response = data_blob_talloc(p->mem_ctx, r->in.logon.network->nt.data, r->in.logon.network->nt.length);
 
 	status = winbind_dual_SamLogon(domain, p->mem_ctx,
+				       false, /* interactive */
 				       r->in.logon.network->identity_info.parameter_control,
 				       r->in.logon.network->identity_info.account_name.string,
 				       r->in.logon.network->identity_info.domain_name.string,
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index c618b7a1a24..9cab59dd640 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -2201,6 +2201,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
 
 NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
 			       TALLOC_CTX *mem_ctx,
+			       bool interactive,
 			       uint32_t logon_parameters,
 			       const char *name_user,
 			       const char *name_domain,
@@ -2237,7 +2238,7 @@ NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
 			logon_parameters,
 			name_domain, name_user,
 			&chal_blob, &lm_response, &nt_response,
-			false, /* interactive */
+			interactive,
 			authoritative,
 			&info3);
 		if (NT_STATUS_IS_OK(result)) {
@@ -2273,7 +2274,7 @@ NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
 					     chal,
 					     lm_response,
 					     nt_response,
-					     false, /* interactive */
+					     interactive,
 					     authoritative,
 					     flags,
 					     &validation_level,
@@ -2417,6 +2418,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
 
 	result = winbind_dual_SamLogon(domain,
 				       state->mem_ctx,
+				       false, /* interactive */
 				       state->request->data.auth_crap.logon_parameters,
 				       name_user,
 				       name_domain,
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 49d44af97ff..568978141c9 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -421,6 +421,7 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
 
 NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
 			       TALLOC_CTX *mem_ctx,
+			       bool interactive,
 			       uint32_t logon_parameters,
 			       const char *name_user,
 			       const char *name_domain,
-- 
2.13.6


From e09446eeb980a14b653d573f6883745de10ebb0d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 17:39:15 +0100
Subject: [PATCH 25/37] winbindd: handle interactive logons in
 _winbind_SamLogon()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13258

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_dual_srv.c | 76 ++++++++++++++++++++++++++++++------
 1 file changed, 63 insertions(+), 13 deletions(-)

diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 4ac38ff19d2..4804da91583 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -868,35 +868,85 @@ NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
 {
 	struct winbindd_domain *domain;
 	NTSTATUS status;
+	struct netr_IdentityInfo *identity_info = NULL;
+	const uint8_t chal_zero[8] = {0, };
+	const uint8_t *challenge = chal_zero;
 	DATA_BLOB lm_response, nt_response;
 	uint32_t flags = 0;
 	uint16_t validation_level;
 	union netr_Validation *validation = NULL;
+	bool interactive = false;
 
 	domain = wb_child_domain();
 	if (domain == NULL) {
 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
 	}
 
-	/* TODO: Handle interactive logons here */
-	if (r->in.validation_level != 3 ||
-	    r->in.logon.network == NULL ||
-	    (r->in.logon_level != NetlogonNetworkInformation
-	     && r->in.logon_level != NetlogonNetworkTransitiveInformation)) {
+	if (r->in.validation_level != 3) {
 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
 	}
 
+	switch (r->in.logon_level) {
+	case NetlogonInteractiveInformation:
+	case NetlogonServiceInformation:
+	case NetlogonInteractiveTransitiveInformation:
+	case NetlogonServiceTransitiveInformation:
+		if (r->in.logon.password == NULL) {
+			return NT_STATUS_REQUEST_NOT_ACCEPTED;
+		}
+
+		interactive = true;
+		identity_info = &r->in.logon.password->identity_info;
+
+		challenge = chal_zero;
+		lm_response = data_blob_talloc(p->mem_ctx,
+					r->in.logon.password->lmpassword.hash,
+					sizeof(r->in.logon.password->lmpassword.hash));
+		nt_response = data_blob_talloc(p->mem_ctx,
+					r->in.logon.password->ntpassword.hash,
+					sizeof(r->in.logon.password->ntpassword.hash));
+		break;
+
+	case NetlogonNetworkInformation:
+	case NetlogonNetworkTransitiveInformation:
+		if (r->in.logon.network == NULL) {
+			return NT_STATUS_REQUEST_NOT_ACCEPTED;
+		}
+
+		interactive = false;
+		identity_info = &r->in.logon.network->identity_info;
+
+		challenge = r->in.logon.network->challenge;
+		lm_response = data_blob_talloc(p->mem_ctx,
+					r->in.logon.network->lm.data,
+					r->in.logon.network->lm.length);
+		nt_response = data_blob_talloc(p->mem_ctx,
+					r->in.logon.network->nt.data,
+					r->in.logon.network->nt.length);
+		break;
 
-	lm_response = data_blob_talloc(p->mem_ctx, r->in.logon.network->lm.data, r->in.logon.network->lm.length);
-	nt_response = data_blob_talloc(p->mem_ctx, r->in.logon.network->nt.data, r->in.logon.network->nt.length);
+	case NetlogonGenericInformation:
+		if (r->in.logon.generic == NULL) {
+			return NT_STATUS_REQUEST_NOT_ACCEPTED;
+		}
+
+		identity_info = &r->in.logon.generic->identity_info;
+		/*
+		 * Not implemented here...
+		 */
+		return NT_STATUS_REQUEST_NOT_ACCEPTED;
+
+	default:
+		return NT_STATUS_REQUEST_NOT_ACCEPTED;
+	}
 
 	status = winbind_dual_SamLogon(domain, p->mem_ctx,
-				       false, /* interactive */
-				       r->in.logon.network->identity_info.parameter_control,
-				       r->in.logon.network->identity_info.account_name.string,
-				       r->in.logon.network->identity_info.domain_name.string,
-				       r->in.logon.network->identity_info.workstation.string,
-				       r->in.logon.network->challenge,
+				       interactive,
+				       identity_info->parameter_control,
+				       identity_info->account_name.string,
+				       identity_info->domain_name.string,
+				       identity_info->workstation.string,
+				       challenge,
 				       lm_response, nt_response,
 				       &r->out.authoritative,
 				       true, /* skip_sam */
-- 
2.13.6


From 739bef83b58bb6c290d86856892e2fc16060dbe6 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 2 Feb 2018 15:24:00 +0100
Subject: [PATCH 26/37] winbindd: introduce a cm_connect_netlogon_secure()
 which gives a valid netlogon_creds_ctx

At lot of callers require a valid schannel connection.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13259

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_cm.c       | 30 ++++++++++++----
 source3/winbindd/winbindd_dual.c     |  7 ++--
 source3/winbindd/winbindd_dual_srv.c | 69 +++++++++++++++++++++++++-----------
 source3/winbindd/winbindd_pam.c      | 16 ++++-----
 source3/winbindd/winbindd_proto.h    |  3 ++
 5 files changed, 87 insertions(+), 38 deletions(-)

diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index b7fd981547f..54416e02dcd 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -2623,16 +2623,11 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
 		return NT_STATUS_OK;
 	}
 
-	result = cm_connect_netlogon(domain, &netlogon_pipe);
+	result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
 	if (!NT_STATUS_IS_OK(result)) {
 		return result;
 	}
 
-	if (domain->conn.netlogon_creds_ctx == NULL) {
-		return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
-	}
-
-	*ppdc = domain->conn.netlogon_creds_ctx;
 	return NT_STATUS_OK;
 }
 
@@ -3325,6 +3320,29 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
 	return status;
 }
 
+NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
+				    struct rpc_pipe_client **cli,
+				    struct netlogon_creds_cli_context **ppdc)
+{
+	NTSTATUS status;
+
+	if (domain->secure_channel_type == SEC_CHAN_NULL) {
+		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+	}
+
+	status = cm_connect_netlogon(domain, cli);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	if (domain->conn.netlogon_creds_ctx == NULL) {
+		return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
+	}
+
+	*ppdc = domain->conn.netlogon_creds_ctx;
+	return NT_STATUS_OK;
+}
+
 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
 			    void *private_data,
 			    uint32_t msg_type,
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index a05644d2c34..33f1393e082 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -1055,6 +1055,7 @@ static void machine_password_change_handler(struct tevent_context *ctx,
 	struct winbindd_child *child =
 		(struct winbindd_child *)private_data;
 	struct rpc_pipe_client *netlogon_pipe = NULL;
+	struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 	NTSTATUS result;
 	struct timeval next_change;
 
@@ -1083,7 +1084,9 @@ static void machine_password_change_handler(struct tevent_context *ctx,
 		return;
 	}
 
-	result = cm_connect_netlogon(child->domain, &netlogon_pipe);
+	result = cm_connect_netlogon_secure(child->domain,
+					    &netlogon_pipe,
+					    &netlogon_creds_ctx);
 	if (!NT_STATUS_IS_OK(result)) {
 		DEBUG(10,("machine_password_change_handler: "
 			"failed to connect netlogon pipe: %s\n",
@@ -1091,7 +1094,7 @@ static void machine_password_change_handler(struct tevent_context *ctx,
 		return;
 	}
 
-	result = trust_pw_change(child->domain->conn.netlogon_creds_ctx,
+	result = trust_pw_change(netlogon_creds_ctx,
 				 msg_ctx,
 				 netlogon_pipe->binding_handle,
 				 child->domain->name,
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 4804da91583..5c12414fd25 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -679,8 +679,11 @@ NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p,
 	domain->conn.netlogon_force_reauth = true;
 
 	{
-		struct rpc_pipe_client *netlogon_pipe;
-		status = cm_connect_netlogon(domain, &netlogon_pipe);
+		struct rpc_pipe_client *netlogon_pipe = NULL;
+		struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
+		status = cm_connect_netlogon_secure(domain,
+						    &netlogon_pipe,
+						    &netlogon_creds_ctx);
 	}
 
         /* There is a race condition between fetching the trust account
@@ -721,20 +724,23 @@ NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p,
 	struct messaging_context *msg_ctx = server_messaging_context();
 	struct winbindd_domain *domain;
 	NTSTATUS status;
-	struct rpc_pipe_client *netlogon_pipe;
+	struct rpc_pipe_client *netlogon_pipe = NULL;
+	struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 
 	domain = wb_child_domain();
 	if (domain == NULL) {
 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
 	}
 
-	status = cm_connect_netlogon(domain, &netlogon_pipe);
+	status = cm_connect_netlogon_secure(domain,
+					    &netlogon_pipe,
+					    &netlogon_creds_ctx);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
 		goto done;
 	}
 
-	status = trust_pw_change(domain->conn.netlogon_creds_ctx,
+	status = trust_pw_change(netlogon_creds_ctx,
 				 msg_ctx,
 				 netlogon_pipe->binding_handle,
 				 domain->name,
@@ -830,20 +836,23 @@ NTSTATUS _winbind_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p,
 {
 	struct winbindd_domain *domain;
 	NTSTATUS status;
-	struct rpc_pipe_client *netlogon_pipe;
+	struct rpc_pipe_client *netlogon_pipe = NULL;
+	struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 
 	domain = wb_child_domain();
 	if (domain == NULL) {
 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
 	}
 
-	status = cm_connect_netlogon(domain, &netlogon_pipe);
+	status = cm_connect_netlogon_secure(domain,
+					    &netlogon_pipe,
+					    &netlogon_creds_ctx);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
 		goto done;
 	}
 
-	status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(domain->conn.netlogon_creds_ctx,
+	status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(netlogon_creds_ctx,
 								      netlogon_pipe->binding_handle,
 								      r->in.site_name,
 								      r->in.dns_ttl,
@@ -973,6 +982,7 @@ static WERROR _winbind_LogonControl_REDISCOVER(struct pipes_struct *p,
 {
 	NTSTATUS status;
 	struct rpc_pipe_client *netlogon_pipe = NULL;
+	struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 	struct netr_NETLOGON_INFO_2 *info2 = NULL;
 	WERROR check_result = WERR_INTERNAL_ERROR;
 
@@ -993,7 +1003,9 @@ static WERROR _winbind_LogonControl_REDISCOVER(struct pipes_struct *p,
 	 */
 	invalidate_cm_connection(domain);
 	domain->conn.netlogon_force_reauth = true;
-	status = cm_connect_netlogon(domain, &netlogon_pipe);
+	status = cm_connect_netlogon_secure(domain,
+					    &netlogon_pipe,
+					    &netlogon_creds_ctx);
 	reset_cm_connection_on_error(domain, status);
 	if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
 		status = NT_STATUS_NO_LOGON_SERVERS;
@@ -1049,6 +1061,7 @@ static WERROR _winbind_LogonControl_TC_QUERY(struct pipes_struct *p,
 {
 	NTSTATUS status;
 	struct rpc_pipe_client *netlogon_pipe = NULL;
+	struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 	struct netr_NETLOGON_INFO_2 *info2 = NULL;
 	WERROR check_result = WERR_INTERNAL_ERROR;
 
@@ -1062,7 +1075,9 @@ static WERROR _winbind_LogonControl_TC_QUERY(struct pipes_struct *p,
 		goto check_return;
 	}
 
-	status = cm_connect_netlogon(domain, &netlogon_pipe);
+	status = cm_connect_netlogon_secure(domain,
+					    &netlogon_pipe,
+					    &netlogon_creds_ctx);
 	reset_cm_connection_on_error(domain, status);
 	if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
 		status = NT_STATUS_NO_LOGON_SERVERS;
@@ -1121,6 +1136,7 @@ static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p,
 	struct policy_handle local_lsa_policy = {};
 	struct dcerpc_binding_handle *local_lsa = NULL;
 	struct rpc_pipe_client *netlogon_pipe = NULL;
+	struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 	struct cli_credentials *creds = NULL;
 	struct samr_Password *cur_nt_hash = NULL;
 	uint32_t trust_attributes = 0;
@@ -1241,7 +1257,9 @@ static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p,
 	}
 
 reconnect:
-	status = cm_connect_netlogon(domain, &netlogon_pipe);
+	status = cm_connect_netlogon_secure(domain,
+					    &netlogon_pipe,
+					    &netlogon_creds_ctx);
 	reset_cm_connection_on_error(domain, status);
 	if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
 		status = NT_STATUS_NO_LOGON_SERVERS;
@@ -1261,7 +1279,7 @@ static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p,
 	}
 
 	if (fetch_fti) {
-		status = netlogon_creds_cli_GetForestTrustInformation(domain->conn.netlogon_creds_ctx,
+		status = netlogon_creds_cli_GetForestTrustInformation(netlogon_creds_ctx,
 								      b, frame,
 								      &new_fti);
 		if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
@@ -1323,7 +1341,7 @@ static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p,
 		}
 	}
 
-	status = netlogon_creds_cli_ServerGetTrustInfo(domain->conn.netlogon_creds_ctx,
+	status = netlogon_creds_cli_ServerGetTrustInfo(netlogon_creds_ctx,
 						       b, frame,
 						       &new_owf_password,
 						       &old_owf_password,
@@ -1434,7 +1452,8 @@ static WERROR _winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct *p,
 {
 	struct messaging_context *msg_ctx = server_messaging_context();
 	NTSTATUS status;
-	struct rpc_pipe_client *netlogon_pipe;
+	struct rpc_pipe_client *netlogon_pipe = NULL;
+	struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 	struct cli_credentials *creds = NULL;
 	struct samr_Password *cur_nt_hash = NULL;
 	struct netr_NETLOGON_INFO_1 *info1 = NULL;
@@ -1461,7 +1480,9 @@ static WERROR _winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct *p,
 	}
 
 reconnect:
-	status = cm_connect_netlogon(domain, &netlogon_pipe);
+	status = cm_connect_netlogon_secure(domain,
+					    &netlogon_pipe,
+					    &netlogon_creds_ctx);
 	reset_cm_connection_on_error(domain, status);
 	if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
 		status = NT_STATUS_NO_LOGON_SERVERS;
@@ -1484,7 +1505,7 @@ static WERROR _winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct *p,
 	}
 	TALLOC_FREE(cur_nt_hash);
 
-	status = trust_pw_change(domain->conn.netlogon_creds_ctx,
+	status = trust_pw_change(netlogon_creds_ctx,
 				 msg_ctx, b, domain->name,
 				 domain->dcname,
 				 true); /* force */
@@ -1567,7 +1588,8 @@ WERROR _winbind_GetForestTrustInformation(struct pipes_struct *p,
 	TALLOC_CTX *frame = talloc_stackframe();
 	NTSTATUS status, result;
 	struct winbindd_domain *domain;
-	struct rpc_pipe_client *netlogon_pipe;
+	struct rpc_pipe_client *netlogon_pipe = NULL;
+	struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 	struct dcerpc_binding_handle *b;
 	bool retry = false;
 	struct lsa_String trusted_domain_name = {};
@@ -1666,7 +1688,9 @@ WERROR _winbind_GetForestTrustInformation(struct pipes_struct *p,
 	}
 
 reconnect:
-	status = cm_connect_netlogon(domain, &netlogon_pipe);
+	status = cm_connect_netlogon_secure(domain,
+					    &netlogon_pipe,
+					    &netlogon_creds_ctx);
 	reset_cm_connection_on_error(domain, status);
 	if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
 		status = NT_STATUS_NO_LOGON_SERVERS;
@@ -1679,7 +1703,7 @@ WERROR _winbind_GetForestTrustInformation(struct pipes_struct *p,
 	}
 	b = netlogon_pipe->binding_handle;
 
-	status = netlogon_creds_cli_GetForestTrustInformation(domain->conn.netlogon_creds_ctx,
+	status = netlogon_creds_cli_GetForestTrustInformation(netlogon_creds_ctx,
 							      b, p->mem_ctx,
 							      &new_fti);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -1778,6 +1802,7 @@ NTSTATUS _winbind_SendToSam(struct pipes_struct *p, struct winbind_SendToSam *r)
 	struct winbindd_domain *domain;
 	NTSTATUS status;
 	struct rpc_pipe_client *netlogon_pipe;
+	struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 
 	DEBUG(5, ("_winbind_SendToSam received\n"));
 	domain = wb_child_domain();
@@ -1785,13 +1810,15 @@ NTSTATUS _winbind_SendToSam(struct pipes_struct *p, struct winbind_SendToSam *r)
 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
 	}
 
-	status = cm_connect_netlogon(domain, &netlogon_pipe);
+	status = cm_connect_netlogon_secure(domain,
+					    &netlogon_pipe,
+					    &netlogon_creds_ctx);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
 		return status;
 	}
 
-	status = netlogon_creds_cli_SendToSam(domain->conn.netlogon_creds_ctx,
+	status = netlogon_creds_cli_SendToSam(netlogon_creds_ctx,
 					      netlogon_pipe->binding_handle,
 					      &r->in.message);
 
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 9cab59dd640..9c598d71855 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1442,10 +1442,12 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 
 	do {
 		struct rpc_pipe_client *netlogon_pipe;
+		struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
 
 		retry = false;
 
-		result = cm_connect_netlogon(domain, &netlogon_pipe);
+		result = cm_connect_netlogon_secure(domain, &netlogon_pipe,
+						    &netlogon_creds_ctx);
 
 		if (NT_STATUS_EQUAL(result,
 				    NT_STATUS_CANT_ACCESS_DOMAIN_INFO)) {
@@ -1521,13 +1523,9 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 		}
 
 		netr_attempts = 0;
-		if (domain->conn.netlogon_creds_ctx == NULL) {
-			DBG_NOTICE("No security credentials available for "
-				  "domain [%s]\n", domainname);
-			result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-		} else if (plaintext_given) {
+		if (plaintext_given) {
 			result = rpccli_netlogon_password_logon(
-				domain->conn.netlogon_creds_ctx,
+				netlogon_creds_ctx,
 				netlogon_pipe->binding_handle,
 				mem_ctx,
 				logon_parameters,
@@ -1542,7 +1540,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 				&validation);
 		} else if (interactive) {
 			result = rpccli_netlogon_interactive_logon(
-				domain->conn.netlogon_creds_ctx,
+				netlogon_creds_ctx,
 				netlogon_pipe->binding_handle,
 				mem_ctx,
 				logon_parameters,
@@ -1558,7 +1556,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 				&validation);
 		} else {
 			result = rpccli_netlogon_network_logon(
-				domain->conn.netlogon_creds_ctx,
+				netlogon_creds_ctx,
 				netlogon_pipe->binding_handle,
 				mem_ctx,
 				logon_parameters,
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 568978141c9..015fd717b34 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -210,6 +210,9 @@ NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
 			 struct policy_handle *lsa_policy);
 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
 			     struct rpc_pipe_client **cli);
+NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
+				    struct rpc_pipe_client **cli,
+				    struct netlogon_creds_cli_context **ppdc);
 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
 				    const char *domain_name,
 				    char **p_dc_name, char **p_dc_ip);
-- 
2.13.6


From a485d1d8c1e205d3eaccb345ba447afdc44a1da0 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 17:53:49 +0100
Subject: [PATCH 27/37] s3/rpc_client: add copy_netr_SamInfo6() and
 map_validation_to_info6()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13260

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/rpc_client/util_netlogon.c | 146 +++++++++++++++++++++++++++++++++++++
 source3/rpc_client/util_netlogon.h |   7 ++
 2 files changed, 153 insertions(+)

diff --git a/source3/rpc_client/util_netlogon.c b/source3/rpc_client/util_netlogon.c
index 15c769ffe41..008861f00d1 100644
--- a/source3/rpc_client/util_netlogon.c
+++ b/source3/rpc_client/util_netlogon.c
@@ -190,6 +190,152 @@ NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx,
 	return NT_STATUS_OK;
 }
 
+NTSTATUS copy_netr_SamInfo6(TALLOC_CTX *mem_ctx,
+			    const struct netr_SamInfo6 *in,
+			    struct netr_SamInfo6 **pout)
+{
+	struct netr_SamInfo6 *info6 = NULL;
+	unsigned int i;
+	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+
+	info6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
+	if (info6 == NULL) {
+		status = NT_STATUS_NO_MEMORY;
+		goto out;
+	}
+
+	status = copy_netr_SamBaseInfo(info6, &in->base, &info6->base);
+	if (!NT_STATUS_IS_OK(status)) {
+		goto out;
+	}
+
+	if (in->sidcount) {
+		info6->sidcount = in->sidcount;
+		info6->sids = talloc_array(info6, struct netr_SidAttr,
+					   in->sidcount);
+		if (info6->sids == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+
+		for (i = 0; i < in->sidcount; i++) {
+			info6->sids[i].sid = dom_sid_dup(info6->sids,
+							 in->sids[i].sid);
+			if (info6->sids[i].sid == NULL) {
+				status = NT_STATUS_NO_MEMORY;
+				goto out;
+			}
+			info6->sids[i].attributes = in->sids[i].attributes;
+		}
+	}
+
+	if (in->dns_domainname.string != NULL) {
+		info6->dns_domainname.string = talloc_strdup(info6,
+						in->dns_domainname.string);
+		if (info6->dns_domainname.string == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+	}
+
+	if (in->principal_name.string != NULL) {
+		info6->principal_name.string = talloc_strdup(info6,
+						in->principal_name.string);
+		if (info6->principal_name.string == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+	}
+
+	*pout = info6;
+	info6 = NULL;
+
+	status = NT_STATUS_OK;
+out:
+	TALLOC_FREE(info6);
+	return status;
+}
+
+NTSTATUS map_validation_to_info6(TALLOC_CTX *mem_ctx,
+				 uint16_t validation_level,
+				 union netr_Validation *validation,
+				 struct netr_SamInfo6 **info6_p)
+{
+	struct netr_SamInfo3 *info3 = NULL;
+	struct netr_SamInfo6 *info6 = NULL;
+	NTSTATUS status;
+
+	if (validation == NULL) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	switch (validation_level) {
+	case 3:
+		if (validation->sam3 == NULL) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+		info3 = validation->sam3;
+
+		info6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
+		if (info6 == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		status = copy_netr_SamBaseInfo(info6,
+					       &info3->base,
+					       &info6->base);
+		if (!NT_STATUS_IS_OK(status)) {
+			TALLOC_FREE(info6);
+			return status;
+		}
+
+		if (validation->sam3->sidcount > 0) {
+			int i;
+
+			info6->sidcount = info3->sidcount;
+
+			info6->sids = talloc_array(info6,
+						   struct netr_SidAttr,
+						   info6->sidcount);
+			if (info6->sids == NULL) {
+				TALLOC_FREE(info6);
+				return NT_STATUS_NO_MEMORY;
+			}
+
+			for (i = 0; i < info6->sidcount; i++) {
+				info6->sids[i].sid = dom_sid_dup(
+					info6->sids, info3->sids[i].sid);
+				if (info6->sids[i].sid == NULL) {
+					TALLOC_FREE(info6);
+					return NT_STATUS_NO_MEMORY;
+				}
+				info6->sids[i].attributes =
+					info3->sids[i].attributes;
+			}
+		}
+		break;
+	case 6:
+		if (validation->sam6 == NULL) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
+		status = copy_netr_SamInfo6(mem_ctx,
+					    validation->sam6,
+					    &info6);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+
+		break;
+	default:
+		return NT_STATUS_BAD_VALIDATION_CLASS;
+	}
+
+	*info6_p = info6;
+
+	return NT_STATUS_OK;
+}
+
 NTSTATUS map_info3_to_validation(TALLOC_CTX *mem_ctx,
 				 struct netr_SamInfo3 *info3,
 				 uint16_t *_validation_level,
diff --git a/source3/rpc_client/util_netlogon.h b/source3/rpc_client/util_netlogon.h
index 8b3a372ee8e..fc1da1face3 100644
--- a/source3/rpc_client/util_netlogon.h
+++ b/source3/rpc_client/util_netlogon.h
@@ -32,6 +32,13 @@ NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx,
 				 uint16_t validation_level,
 				 union netr_Validation *validation,
 				 struct netr_SamInfo3 **info3_p);
+NTSTATUS copy_netr_SamInfo6(TALLOC_CTX *mem_ctx,
+			    const struct netr_SamInfo6 *in,
+			    struct netr_SamInfo6 **pout);
+NTSTATUS map_validation_to_info6(TALLOC_CTX *mem_ctx,
+				 uint16_t validation_level,
+				 union netr_Validation *validation,
+				 struct netr_SamInfo6 **info6_p);
 NTSTATUS map_info3_to_validation(TALLOC_CTX *mem_ctx,
 				 struct netr_SamInfo3 *info3,
 				 uint16_t *_validation_level,
-- 
2.13.6


From 6d3e41ba02f00c5049282731906fae93b457cedf Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 17:57:37 +0100
Subject: [PATCH 28/37] winbindd: allow validation level 6 in winbind_SamLogon

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13260

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_dual_srv.c | 38 +++++++++++++++++++++++++++---------
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 5c12414fd25..66b4ee82a25 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -891,7 +891,11 @@ NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
 	}
 
-	if (r->in.validation_level != 3) {
+	switch (r->in.validation_level) {
+	case 3:
+	case 6:
+		break;
+	default:
 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
 	}
 
@@ -965,15 +969,31 @@ NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
-	status = map_validation_to_info3(p->mem_ctx,
-					 validation_level,
-					 validation,
-					 &r->out.validation.sam3);
-	TALLOC_FREE(validation);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
+	switch (r->in.validation_level) {
+	case 3:
+		status = map_validation_to_info3(p->mem_ctx,
+						 validation_level,
+						 validation,
+						 &r->out.validation.sam3);
+		TALLOC_FREE(validation);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+		return NT_STATUS_OK;
+	case 6:
+		status = map_validation_to_info6(p->mem_ctx,
+						 validation_level,
+						 validation,
+						 &r->out.validation.sam6);
+		TALLOC_FREE(validation);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+		return NT_STATUS_OK;
 	}
-	return NT_STATUS_OK;
+
+	smb_panic(__location__);
+	return NT_STATUS_INTERNAL_ERROR;
 }
 
 static WERROR _winbind_LogonControl_REDISCOVER(struct pipes_struct *p,
-- 
2.13.6


From f667d66cd06b4d818a5154ae350966e9771ccd4d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 17:58:07 +0100
Subject: [PATCH 29/37] s4/auth_winbind: ask for validation level 6

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13260

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source4/auth/ntlm/auth_winbind.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/auth/ntlm/auth_winbind.c b/source4/auth/ntlm/auth_winbind.c
index e887d5ea06d..2e885638ebe 100644
--- a/source4/auth/ntlm/auth_winbind.c
+++ b/source4/auth/ntlm/auth_winbind.c
@@ -176,7 +176,7 @@ static struct tevent_req *winbind_check_password_send(TALLOC_CTX *mem_ctx,
 	identity_info->account_name.string	= user_info->client.account_name;
 	identity_info->workstation.string	= user_info->workstation_name;
 
-	state->req.in.validation_level = 3;
+	state->req.in.validation_level = 6;
 
 	subreq = dcerpc_winbind_SamLogon_r_send(state, ev, irpc_handle,
 						&state->req);
-- 
2.13.6


From b42d8739c0cc89b7bcec7cb6752992d7651bbbfb Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 21:32:25 +0100
Subject: [PATCH 30/37] s3/auth: add create_info6_from_pac()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13261

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/auth/proto.h       |  4 ++++
 source3/auth/server_info.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index e7746701022..ca851c21d4b 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -312,6 +312,10 @@ NTSTATUS serverinfo_to_SamInfo6(struct auth_serversupplied_info *server_info,
 NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx,
                                         const struct PAC_LOGON_INFO *logon_info,
                                         struct netr_SamInfo3 **pp_info3);
+NTSTATUS create_info6_from_pac(TALLOC_CTX *mem_ctx,
+			       const struct PAC_LOGON_INFO *logon_info,
+			       const struct PAC_UPN_DNS_INFO *upn_dns_info,
+			       struct netr_SamInfo6 **pp_info6);
 NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
 			  struct samu *samu,
 			  const char *login_server,
diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c
index 78981751286..339cce6c4ec 100644
--- a/source3/auth/server_info.c
+++ b/source3/auth/server_info.c
@@ -363,6 +363,62 @@ NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx,
 }
 
 /*
+ * Create a copy of an info6 struct from the PAC_UPN_DNS_INFO and PAC_LOGON_INFO
+ * then merge resource SIDs, if any, into it. If successful return the created
+ * info6 struct.
+ */
+NTSTATUS create_info6_from_pac(TALLOC_CTX *mem_ctx,
+			       const struct PAC_LOGON_INFO *logon_info,
+			       const struct PAC_UPN_DNS_INFO *upn_dns_info,
+			       struct netr_SamInfo6 **pp_info6)
+{
+	NTSTATUS status;
+	struct netr_SamInfo6 *info6 = NULL;
+	struct netr_SamInfo3 *info3 = NULL;
+
+	info6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
+	if (info6 == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	status = copy_netr_SamInfo3(info6,
+				    &logon_info->info3,
+				    &info3);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(info6);
+		return status;
+	}
+
+	status = merge_resource_sids(logon_info, info3);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(info6);
+		return status;
+	}
+
+	info6->base = info3->base;
+	info6->sids = info3->sids;
+	info6->sidcount = info3->sidcount;
+
+	if (upn_dns_info != NULL) {
+		info6->dns_domainname.string = talloc_strdup(info6,
+				upn_dns_info->dns_domain_name);
+		if (info6->dns_domainname.string == NULL) {
+			TALLOC_FREE(info6);
+			return NT_STATUS_NO_MEMORY;
+		}
+		info6->principal_name.string = talloc_strdup(info6,
+				upn_dns_info->upn_name);
+		if (info6->principal_name.string == NULL) {
+			TALLOC_FREE(info6);
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
+
+	*pp_info6 = info6;
+	return NT_STATUS_OK;
+}
+
+/*
  * Check if this is a "Unix Users" domain user, or a
  * "Unix Groups" domain group, we need to handle it
  * in a special way if that's the case.
-- 
2.13.6


From 9074bb66425893cbc061bd4944be7bb160f3216d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 21:32:53 +0100
Subject: [PATCH 31/37] s3/rpc_client: add map_info6_to_validation()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13261

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/rpc_client/util_netlogon.c | 25 +++++++++++++++++++++++++
 source3/rpc_client/util_netlogon.h |  4 ++++
 2 files changed, 29 insertions(+)

diff --git a/source3/rpc_client/util_netlogon.c b/source3/rpc_client/util_netlogon.c
index 008861f00d1..2d73bc95cea 100644
--- a/source3/rpc_client/util_netlogon.c
+++ b/source3/rpc_client/util_netlogon.c
@@ -360,3 +360,28 @@ NTSTATUS map_info3_to_validation(TALLOC_CTX *mem_ctx,
 	*_validation = validation;
 	return NT_STATUS_OK;
 }
+
+NTSTATUS map_info6_to_validation(TALLOC_CTX *mem_ctx,
+				 const struct netr_SamInfo6 *info6,
+				 uint16_t *_validation_level,
+				 union netr_Validation **_validation)
+{
+	union netr_Validation *validation = NULL;
+	NTSTATUS status;
+
+	validation = talloc_zero(mem_ctx, union netr_Validation);
+	if (validation == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	status = copy_netr_SamInfo6(mem_ctx,
+				    info6,
+				    &validation->sam6);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	* _validation_level = 6;
+	*_validation = validation;
+	return NT_STATUS_OK;
+}
diff --git a/source3/rpc_client/util_netlogon.h b/source3/rpc_client/util_netlogon.h
index fc1da1face3..c3ed3f67201 100644
--- a/source3/rpc_client/util_netlogon.h
+++ b/source3/rpc_client/util_netlogon.h
@@ -43,5 +43,9 @@ NTSTATUS map_info3_to_validation(TALLOC_CTX *mem_ctx,
 				 struct netr_SamInfo3 *info3,
 				 uint16_t *_validation_level,
 				 union netr_Validation **_validation);
+NTSTATUS map_info6_to_validation(TALLOC_CTX *mem_ctx,
+				 const struct netr_SamInfo6 *info6,
+				 uint16_t *_validation_level,
+				 union netr_Validation **_validation);
 
 #endif /* _RPC_CLIENT_UTIL_NETLOGON_H_ */
-- 
2.13.6


From 1335c413a52d5ca681f6111a3c3ab52e578ae2a0 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 21:34:46 +0100
Subject: [PATCH 32/37] winbindd: get netr_SamInfo6 out of
 winbindd_dual_pam_auth_kerberos()

This way we don't loose dns_domain_name and user principal.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13261

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_pam.c | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 9c598d71855..1e6cfb9736f 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -635,7 +635,7 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
 					    const char *pass,
 					    const char *krb5_cc_type,
 					    uid_t uid,
-					    struct netr_SamInfo3 **info3,
+					    struct netr_SamInfo6 **info6,
 					    fstring krb5ccname)
 {
 #ifdef HAVE_KRB5
@@ -652,13 +652,14 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
 	time_t time_offset = 0;
 	const char *user_ccache_file;
 	struct PAC_LOGON_INFO *logon_info = NULL;
+	struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
 	struct PAC_DATA *pac_data = NULL;
 	struct PAC_DATA_CTR *pac_data_ctr = NULL;
 	const char *local_service;
 	uint32_t i;
-	struct netr_SamInfo3 *info3_copy = NULL;
+	struct netr_SamInfo6 *info6_copy = NULL;
 
-	*info3 = NULL;
+	*info6 = NULL;
 
 	if (domain->alt_name == NULL) {
 		return NT_STATUS_INVALID_PARAMETER;
@@ -764,16 +765,15 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
 
 	for (i=0; i < pac_data->num_buffers; i++) {
 
-		if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) {
+		if (pac_data->buffers[i].type == PAC_TYPE_LOGON_INFO) {
+			logon_info = pac_data->buffers[i].info->logon_info.info;
 			continue;
 		}
 
-		logon_info = pac_data->buffers[i].info->logon_info.info;
-		if (!logon_info) {
-			return NT_STATUS_INVALID_PARAMETER;
+		if (pac_data->buffers[i].type == PAC_TYPE_UPN_DNS_INFO) {
+			upn_dns_info = &pac_data->buffers[i].info->upn_dns_info;
+			continue;
 		}
-
-		break;
 	}
 
 	if (logon_info == NULL) {
@@ -785,7 +785,8 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
 	DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n",
 		principal_s));
 
-	result = create_info3_from_pac_logon_info(mem_ctx, logon_info, &info3_copy);
+	result = create_info6_from_pac(mem_ctx, logon_info,
+				       upn_dns_info, &info6_copy);
 	if (!NT_STATUS_IS_OK(result)) {
 		goto failed;
 	}
@@ -825,7 +826,7 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
 		}
 
 	}
-	*info3 = info3_copy;
+	*info6 = info6_copy;
 	return NT_STATUS_OK;
 
 failed:
@@ -1240,7 +1241,7 @@ static NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
 
 static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
 						struct winbindd_cli_state *state,
-						struct netr_SamInfo3 **info3)
+						struct netr_SamInfo6 **info6)
 {
 	struct winbindd_domain *contact_domain;
 	fstring name_domain, name_user;
@@ -1299,7 +1300,7 @@ static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
 		state->request->data.auth.pass,
 		state->request->data.auth.krb5_cc_type,
 		get_uid_from_request(state->request),
-		info3, state->response->data.auth.krb5ccname);
+		info6, state->response->data.auth.krb5ccname);
 done:
 	return result;
 }
@@ -1928,23 +1929,22 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
 
 	/* Check for Kerberos authentication */
 	if (domain->online && (state->request->flags & WBFLAG_PAM_KRB5)) {
-		struct netr_SamInfo3 *info3 = NULL;
+		struct netr_SamInfo6 *info6 = NULL;
 
-		result = winbindd_dual_pam_auth_kerberos(domain, state, &info3);
+		result = winbindd_dual_pam_auth_kerberos(domain, state, &info6);
 		/* save for later */
 		krb5_result = result;
 
-
 		if (NT_STATUS_IS_OK(result)) {
 			DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n"));
 
-			result = map_info3_to_validation(state->mem_ctx,
-							 info3,
+			result = map_info6_to_validation(state->mem_ctx,
+							 info6,
 							 &validation_level,
 							 &validation);
-			TALLOC_FREE(info3);
+			TALLOC_FREE(info6);
 			if (!NT_STATUS_IS_OK(result)) {
-				DBG_ERR("map_info3_to_validation failed\n");
+				DBG_ERR("map_info6_to_validation failed\n");
 				goto done;
 			}
 			goto process_result;
-- 
2.13.6


From 208ffc23b2d2df7cad3fce5c768e503bd7462e9b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 22:00:35 +0100
Subject: [PATCH 33/37] winbindd: call add_trusted_domain_from_auth() in
 winbindd_pam_auth_crap_done()

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13262

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_pam_auth_crap.c | 33 ++++++++++++++++---------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c
index eb4087b1c2c..fe0ce4ade62 100644
--- a/source3/winbindd/winbindd_pam_auth_crap.c
+++ b/source3/winbindd/winbindd_pam_auth_crap.c
@@ -119,6 +119,23 @@ static void winbindd_pam_auth_crap_done(struct tevent_req *subreq)
 		tevent_req_nterror(req, map_nt_error_from_unix(err));
 		return;
 	}
+
+	if (NT_STATUS_IS_OK(NT_STATUS(state->response->data.auth.nt_status)) &&
+	    (state->flags & WBFLAG_PAM_INFO3_TEXT))
+	{
+		bool ok;
+
+		ok = add_trusted_domain_from_auth(
+			state->response->data.auth.validation_level,
+			&state->response->data.auth.info3,
+			&state->response->data.auth.info6);
+		if (!ok) {
+			DBG_ERR("add_trusted_domain_from_auth failed\n");
+			tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
+			return;
+		}
+	}
+
 	tevent_req_done(req);
 }
 
@@ -157,22 +174,6 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req,
 
 	}
 
- 	if (NT_STATUS_IS_OK(NT_STATUS(state->response->data.auth.nt_status)) &&
-	    (state->flags & WBFLAG_PAM_INFO3_TEXT))
-	{
-		bool ok;
-
-		ok = add_trusted_domain_from_auth(
-			state->response->data.auth.validation_level,
-			&state->response->data.auth.info3,
-			&state->response->data.auth.info6);
-		if (!ok) {
-			DBG_ERR("add_trusted_domain_from_auth failed\n");
-			set_auth_errors(response, NT_STATUS_LOGON_FAILURE);
-			return NT_STATUS_LOGON_FAILURE;
-		}
-	}
-
 	*response = *state->response;
 	response->result = WINBINDD_PENDING;
 	state->response = talloc_move(response, &state->response);
-- 
2.13.6


From 2a3b241896f22d138e8a67a580f5c46fbeca3732 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 23:02:26 +0100
Subject: [PATCH 34/37] winbindd: let winbindd_pam_auth_pac_send() compute
 info6 from PAC

This way we don't loose the DNS info and UPN. A subsequent commit will
let winbindd_pam_auth_pac_send() return the full validation info.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13262

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_pam.c | 108 +++++++++++++++++++++++++---------------
 1 file changed, 68 insertions(+), 40 deletions(-)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 1e6cfb9736f..f186d865f56 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -2823,7 +2823,7 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai
 
 #ifdef HAVE_KRB5
 static NTSTATUS extract_pac_vrfy_sigs(TALLOC_CTX *mem_ctx, DATA_BLOB pac_blob,
-				      struct PAC_LOGON_INFO **logon_info)
+				      struct PAC_DATA **p_pac_data)
 {
 	krb5_context krbctx = NULL;
 	krb5_error_code k5ret;
@@ -2861,10 +2861,14 @@ static NTSTATUS extract_pac_vrfy_sigs(TALLOC_CTX *mem_ctx, DATA_BLOB pac_blob,
 
 	k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor);
 	while (k5ret == 0) {
-		status = kerberos_pac_logon_info(mem_ctx, pac_blob,
-						 krbctx, NULL,
-						 KRB5_KT_KEY(&entry), NULL, 0,
-						 logon_info);
+		status = kerberos_decode_pac(mem_ctx,
+					     pac_blob,
+					     krbctx,
+					     NULL, /* krbtgt_keyblock */
+					     KRB5_KT_KEY(&entry), /* service_keyblock */
+					     NULL, /* client_principal */
+					     0, /* tgs_authtime */
+					     p_pac_data);
 		if (NT_STATUS_IS_OK(status)) {
 			break;
 		}
@@ -2894,20 +2898,75 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
 {
 	struct winbindd_request *req = state->request;
 	DATA_BLOB pac_blob;
+	struct PAC_DATA *pac_data = NULL;
 	struct PAC_LOGON_INFO *logon_info = NULL;
+	struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
+	struct netr_SamInfo6 *info6 = NULL;
+	uint16_t validation_level = 0;
+	union netr_Validation *validation = NULL;
 	struct netr_SamInfo3 *info3_copy = NULL;
 	NTSTATUS result;
+	bool is_trusted = false;
+	uint32_t i;
 
 	pac_blob = data_blob_const(req->extra_data.data, req->extra_len);
-	result = extract_pac_vrfy_sigs(state->mem_ctx, pac_blob, &logon_info);
-	if (!NT_STATUS_IS_OK(result) &&
-	    !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
+	result = extract_pac_vrfy_sigs(state->mem_ctx, pac_blob, &pac_data);
+	if (NT_STATUS_IS_OK(result)) {
+		is_trusted = true;
+	}
+	if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
+		/* Try without signature verification */
+		result = kerberos_decode_pac(state->mem_ctx,
+					     pac_blob,
+					     NULL, /* krb5_context */
+					     NULL, /* krbtgt_keyblock */
+					     NULL, /* service_keyblock */
+					     NULL, /* client_principal */
+					     0, /* tgs_authtime */
+					     &pac_data);
+	}
+	if (!NT_STATUS_IS_OK(result)) {
 		DEBUG(1, ("Error during PAC signature verification: %s\n",
 			  nt_errstr(result)));
 		return result;
 	}
 
-	if (logon_info) {
+	for (i=0; i < pac_data->num_buffers; i++) {
+		if (pac_data->buffers[i].type == PAC_TYPE_LOGON_INFO) {
+			logon_info = pac_data->buffers[i].info->logon_info.info;
+			continue;
+		}
+		if (pac_data->buffers[i].type == PAC_TYPE_UPN_DNS_INFO) {
+			upn_dns_info = &pac_data->buffers[i].info->upn_dns_info;
+			continue;
+		}
+	}
+
+	result = create_info6_from_pac(state->mem_ctx,
+				       logon_info,
+				       upn_dns_info,
+				       &info6);
+	if (!NT_STATUS_IS_OK(result)) {
+		return result;
+	}
+
+	result = map_info6_to_validation(state->mem_ctx,
+					 info6,
+					 &validation_level,
+					 &validation);
+	if (!NT_STATUS_IS_OK(result)) {
+		return result;
+	}
+
+	result = map_validation_to_info3(state->mem_ctx,
+					 validation_level,
+					 validation,
+					 &info3_copy);
+	if (!NT_STATUS_IS_OK(result)) {
+		return result;
+	}
+
+	if (is_trusted) {
 		/*
 		 * Signature verification succeeded, we can
 		 * trust the PAC and prime the netsamlogon
@@ -2917,12 +2976,6 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
 		 */
 		struct winbindd_domain *domain = NULL;
 
-		result = create_info3_from_pac_logon_info(state->mem_ctx,
-							logon_info,
-							&info3_copy);
-		if (!NT_STATUS_IS_OK(result)) {
-			return result;
-		}
 		netsamlogon_cache_store(NULL, info3_copy);
 
 		/*
@@ -2949,31 +3002,6 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
 				info3_copy->base.account_name.string,
 				sid_string_dbg(&user_sid));
 		}
-
-	} else {
-		/* Try without signature verification */
-		result = kerberos_pac_logon_info(state->mem_ctx, pac_blob, NULL,
-						 NULL, NULL, NULL, 0,
-						 &logon_info);
-		if (!NT_STATUS_IS_OK(result)) {
-			DEBUG(10, ("Could not extract PAC: %s\n",
-				   nt_errstr(result)));
-			return result;
-		}
-		if (logon_info) {
-			/*
-			 * Don't strictly need to copy here,
-			 * but it makes it explicit we're
-			 * returning a copy talloc'ed off
-			 * the state->mem_ctx.
-			 */
-			result = copy_netr_SamInfo3(state->mem_ctx,
-						    &logon_info->info3,
-						    &info3_copy);
-			if (!NT_STATUS_IS_OK(result)) {
-				return result;
-			}
-		}
 	}
 
 	*info3 = info3_copy;
-- 
2.13.6


From 12b3ebd617547ec9622c70f1721186a6d44592bf Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 23:10:42 +0100
Subject: [PATCH 35/37] winbindd: complete WBFLAG_PAM_AUTH_PAC handling in
 winbindd_pam_auth_crap_send()

winbindd_pam_auth_crap_recv() should not have any real logic.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13262

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_pam_auth_crap.c | 64 ++++++++++++++++---------------
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c
index fe0ce4ade62..afcce03172e 100644
--- a/source3/winbindd/winbindd_pam_auth_crap.c
+++ b/source3/winbindd/winbindd_pam_auth_crap.c
@@ -24,7 +24,6 @@
 
 struct winbindd_pam_auth_crap_state {
 	struct winbindd_response *response;
-	struct netr_SamInfo3 *info3;
 	uint32_t flags;
 };
 
@@ -50,16 +49,44 @@ struct tevent_req *winbindd_pam_auth_crap_send(
 	state->flags = request->flags;
 
 	if (state->flags & WBFLAG_PAM_AUTH_PAC) {
+		struct netr_SamInfo3 *info3 = NULL;
+		uint16_t validation_level;
+		union netr_Validation *validation = NULL;
 		NTSTATUS status;
 
-		status = winbindd_pam_auth_pac_send(cli, &state->info3);
-		if (NT_STATUS_IS_OK(status)) {
-			/* Defer filling out response to recv */
-			tevent_req_done(req);
-		} else {
-			tevent_req_nterror(req, status);
+		status = winbindd_pam_auth_pac_send(cli, &info3);
+		if (tevent_req_nterror(req, status)) {
+			return tevent_req_post(req, ev);
+		}
+
+		state->response = talloc_zero(state,
+					      struct winbindd_response);
+		if (tevent_req_nomem(state->response, req)) {
+			return tevent_req_post(req, ev);
 		}
+		state->response->result = WINBINDD_PENDING;
+		state->response->length = sizeof(struct winbindd_response);
 
+		status = map_info3_to_validation(talloc_tos(),
+						 info3,
+						 &validation_level,
+						 &validation);
+		if (tevent_req_nterror(req, status)) {
+			return tevent_req_post(req, ev);
+		}
+
+		status = append_auth_data(state->response,
+					  state->response,
+					  state->flags,
+					  validation_level,
+					  validation,
+					  NULL, NULL);
+		TALLOC_FREE(validation);
+		if (tevent_req_nterror(req, status)) {
+			return tevent_req_post(req, ev);
+		}
+
+		tevent_req_done(req);
 		return tevent_req_post(req, ev);
 	}
 
@@ -151,29 +178,6 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req,
 		return status;
 	}
 
-	if (state->flags & WBFLAG_PAM_AUTH_PAC)	{
-		uint16_t validation_level;
-		union netr_Validation *validation = NULL;
-
-		status = map_info3_to_validation(talloc_tos(),
-						 state->info3,
-						 &validation_level,
-						 &validation);
-		if (!NT_STATUS_IS_OK(status)) {
-			return status;
-		}
-
-		status = append_auth_data(response,
-					response,
-					state->flags,
-					validation_level,
-					validation,
-					NULL, NULL);
-		TALLOC_FREE(validation);
-		return status;
-
-	}
-
 	*response = *state->response;
 	response->result = WINBINDD_PENDING;
 	state->response = talloc_move(response, &state->response);
-- 
2.13.6


From 6876c6f1a38c9b4d62876dfdb46b9ee53490fb67 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 9 Feb 2018 08:38:18 +0100
Subject: [PATCH 36/37] winbindd: rename winbindd_pam_auth_pac_send and let it
 return validation

Just a preperational step. The next commit will update the caller to
make use of the validation info.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13262

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_pam.c           | 25 +++++++++++++++++++------
 source3/winbindd/winbindd_pam_auth_crap.c | 15 +++++----------
 source3/winbindd/winbindd_proto.h         |  6 ++++--
 3 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index f186d865f56..8403d7d57b6 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -2893,8 +2893,10 @@ static NTSTATUS extract_pac_vrfy_sigs(TALLOC_CTX *mem_ctx, DATA_BLOB pac_blob,
 	return status;
 }
 
-NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
-				    struct netr_SamInfo3 **info3)
+NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
+				      bool *p_is_trusted,
+				      uint16_t *p_validation_level,
+				      union netr_Validation **p_validation)
 {
 	struct winbindd_request *req = state->request;
 	DATA_BLOB pac_blob;
@@ -2909,6 +2911,10 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
 	bool is_trusted = false;
 	uint32_t i;
 
+	*p_is_trusted = false;
+	*p_validation_level = 0;
+	*p_validation = NULL;
+
 	pac_blob = data_blob_const(req->extra_data.data, req->extra_len);
 	result = extract_pac_vrfy_sigs(state->mem_ctx, pac_blob, &pac_data);
 	if (NT_STATUS_IS_OK(result)) {
@@ -3004,14 +3010,21 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
 		}
 	}
 
-	*info3 = info3_copy;
-
+	*p_is_trusted = is_trusted;
+	*p_validation_level = validation_level;
+	*p_validation = validation;
 	return NT_STATUS_OK;
 }
 #else /* HAVE_KRB5 */
-NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
-				    struct netr_SamInfo3 **info3)
+NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
+				      bool *p_is_trusted,
+				      uint16_t *p_validation_level,
+				      union netr_Validation **p_validation);
 {
+
+	*p_is_trusted = false;
+	*p_validation_level = 0;
+	*p_validation = NULL;
 	return NT_STATUS_NO_SUCH_USER;
 }
 #endif /* HAVE_KRB5 */
diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c
index afcce03172e..6fb65a27461 100644
--- a/source3/winbindd/winbindd_pam_auth_crap.c
+++ b/source3/winbindd/winbindd_pam_auth_crap.c
@@ -49,12 +49,15 @@ struct tevent_req *winbindd_pam_auth_crap_send(
 	state->flags = request->flags;
 
 	if (state->flags & WBFLAG_PAM_AUTH_PAC) {
-		struct netr_SamInfo3 *info3 = NULL;
+		bool is_trusted = false;
 		uint16_t validation_level;
 		union netr_Validation *validation = NULL;
 		NTSTATUS status;
 
-		status = winbindd_pam_auth_pac_send(cli, &info3);
+		status = winbindd_pam_auth_pac_verify(cli,
+						      &is_trusted,
+						      &validation_level,
+						      &validation);
 		if (tevent_req_nterror(req, status)) {
 			return tevent_req_post(req, ev);
 		}
@@ -67,14 +70,6 @@ struct tevent_req *winbindd_pam_auth_crap_send(
 		state->response->result = WINBINDD_PENDING;
 		state->response->length = sizeof(struct winbindd_response);
 
-		status = map_info3_to_validation(talloc_tos(),
-						 info3,
-						 &validation_level,
-						 &validation);
-		if (tevent_req_nterror(req, status)) {
-			return tevent_req_post(req, ev);
-		}
-
 		status = append_auth_data(state->response,
 					  state->response,
 					  state->flags,
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 015fd717b34..d09176d954a 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -419,8 +419,10 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact
 enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain,
 					      struct winbindd_cli_state *state) ;
 enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state);
-NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
-				    struct netr_SamInfo3 **info3);
+NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
+				      bool *p_is_trusted,
+				      uint16_t *p_validation_level,
+				      union netr_Validation **p_validation);
 
 NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
 			       TALLOC_CTX *mem_ctx,
-- 
2.13.6


From a3c84021c117ad4b760e6a62363ad6d4b0893b74 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Jan 2018 23:13:12 +0100
Subject: [PATCH 37/37] winbindd: WBFLAG_PAM_AUTH_PAC should call
 add_trusted_domain_from_auth() is the result is trusted

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13262

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/winbindd_pam_auth_crap.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c
index 6fb65a27461..046517d1245 100644
--- a/source3/winbindd/winbindd_pam_auth_crap.c
+++ b/source3/winbindd/winbindd_pam_auth_crap.c
@@ -81,6 +81,20 @@ struct tevent_req *winbindd_pam_auth_crap_send(
 			return tevent_req_post(req, ev);
 		}
 
+		if (is_trusted && (state->flags & WBFLAG_PAM_INFO3_TEXT)) {
+			bool ok;
+
+			ok = add_trusted_domain_from_auth(
+				state->response->data.auth.validation_level,
+				&state->response->data.auth.info3,
+				&state->response->data.auth.info6);
+			if (!ok) {
+				DBG_ERR("add_trusted_domain_from_auth failed\n");
+				tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
+				return tevent_req_post(req, ev);
+			}
+		}
+
 		tevent_req_done(req);
 		return tevent_req_post(req, ev);
 	}
-- 
2.13.6



More information about the samba-technical mailing list