From a280f61d71d5ea7e2212d253b84ac5b25810b88e Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri@samba.org>
Date: Wed, 10 Feb 2016 00:26:45 +0200
Subject: [PATCH 1/4] winbindd: introduce add_trusted_domain_from_tdc()

This is purely a refactoring patch -
Add a routine that adds a winbindd domain object based on
domain trust cache entry. add_trusted_domain() becomes
a wrapper for this new routine.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11691

Signed-off-by: Uri Simchoni <uri@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
---
 source3/winbindd/winbindd_util.c | 76 +++++++++++++++++++++++++---------------
 1 file changed, 48 insertions(+), 28 deletions(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 353722e..70a9041 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -30,6 +30,10 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
+static struct winbindd_domain *
+add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
+			    struct winbindd_methods *methods);
+
 extern struct winbindd_methods cache_methods;
 
 /**
@@ -91,11 +95,31 @@ static bool is_in_internal_domain(const struct dom_sid *sid)
 
 /* Add a trusted domain to our list of domains.
    If the domain already exists in the list,
-   return it and don't re-initialize.
- */
-static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
-						  struct winbindd_methods *methods,
-						  const struct dom_sid *sid)
+   return it and don't re-initialize.  */
+
+static struct winbindd_domain *
+add_trusted_domain(const char *domain_name, const char *alt_name,
+		   struct winbindd_methods *methods, const struct dom_sid *sid)
+{
+	struct winbindd_tdc_domain tdc;
+
+	ZERO_STRUCT(tdc);
+
+	tdc.domain_name = domain_name;
+	tdc.dns_name = alt_name;
+	if (sid) {
+		sid_copy(&tdc.sid, sid);
+	}
+
+	return add_trusted_domain_from_tdc(&tdc, methods);
+}
+
+/* Add a trusted domain out of a trusted domain cache
+   entry
+*/
+static struct winbindd_domain *
+add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
+			    struct winbindd_methods *methods)
 {
 	struct winbindd_domain *domain;
 	const char *alternative_name = NULL;
@@ -103,6 +127,12 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 	const char *param;
 	const char **ignored_domains, **dom;
 	int role = lp_server_role();
+	const char *domain_name = tdc->domain_name;
+	const struct dom_sid *sid = &tdc->sid;
+
+	if (is_null_sid(sid)) {
+		sid = NULL;
+	}
 
 	ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
 	for (dom=ignored_domains; dom && *dom; dom++) {
@@ -114,8 +144,8 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 
 	/* ignore alt_name if we are not in an AD domain */
 
-	if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) {
-		alternative_name = alt_name;
+	if (tdc->dns_name && *tdc->dns_name) {
+		alternative_name = tdc->dns_name;
 	}
 
 	/* We can't call domain_list() as this function is called from
@@ -127,8 +157,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 			break;
 		}
 
-		if (alternative_name && *alternative_name)
-		{
+		if (alternative_name) {
 			if (strequal(alternative_name, domain->name) ||
 			    strequal(alternative_name, domain->alt_name))
 			{
@@ -136,12 +165,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 			}
 		}
 
-		if (sid)
-		{
-			if (is_null_sid(sid)) {
-				continue;
-			}
-
+		if (sid != NULL) {
 			if (dom_sid_equal(sid, &domain->sid)) {
 				break;
 			}
@@ -191,11 +215,11 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 	domain->internal = is_internal_domain(sid);
 	domain->sequence_number = DOM_SEQUENCE_NONE;
 	domain->last_seq_check = 0;
-	domain->initialized = False;
+	domain->initialized = false;
 	domain->online = is_internal_domain(sid);
 	domain->check_online_timeout = 0;
 	domain->dc_probe_pid = (pid_t)-1;
-	if (sid) {
+	if (sid != NULL) {
 		sid_copy(&domain->sid, sid);
 	}
 
@@ -246,9 +270,9 @@ done:
 
 	setup_domain_child(domain);
 
-	DEBUG(2,("Added domain %s %s %s\n",
-		 domain->name, domain->alt_name,
-		 &domain->sid?sid_string_dbg(&domain->sid):""));
+	DEBUG(2,
+	      ("Added domain %s %s %s\n", domain->name, domain->alt_name,
+	       !is_null_sid(&domain->sid) ? sid_string_dbg(&domain->sid) : ""));
 
 	return domain;
 }
@@ -432,10 +456,8 @@ static void rescan_forest_root_trusts( void )
 		d = find_domain_from_name_noinit( dom_list[i].domain_name );
 
 		if ( !d ) {
-			(void)add_trusted_domain( dom_list[i].domain_name,
-						dom_list[i].dns_name,
-						&cache_methods,
-						&dom_list[i].sid);
+			d = add_trusted_domain_from_tdc(&dom_list[i],
+							&cache_methods);
 		}
 
 		if (d == NULL) {
@@ -501,10 +523,8 @@ static void rescan_forest_trusts( void )
 			   about it */
 
 			if ( !d ) {
-				(void)add_trusted_domain( dom_list[i].domain_name,
-							dom_list[i].dns_name,
-							&cache_methods,
-							&dom_list[i].sid);
+				d = add_trusted_domain_from_tdc(&dom_list[i],
+								&cache_methods);
 			}
 
 			if (d == NULL) {
-- 
2.9.4


From 153f173eea81ffa1caa4768589a08bb20a6a1950 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 23 Dec 2014 09:43:03 +0000
Subject: [PATCH 2/4] s3:winbindd: mark our primary as active_directory if
 possible

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
---
 source3/winbindd/winbindd_util.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 70a9041..700076a 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -232,6 +232,12 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
 		domain->primary = true;
 	}
 
+	if (domain->primary) {
+		if (lp_security() == SEC_ADS) {
+			domain->active_directory = true;
+		}
+	}
+
 	/* Link to domain list */
 	DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *);
 
-- 
2.9.4


From 5d741ee3d1dafbb32c106fed817840892b69598d Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri@samba.org>
Date: Wed, 10 Feb 2016 00:32:23 +0200
Subject: [PATCH 3/4] winbindd: initialize foreign domain as AD based on trust

Based on trust parameters, initialize the active_directory
member of domain object to true.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11691

Signed-off-by: Uri Simchoni <uri@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
---
 source3/winbindd/winbindd_util.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 700076a..aaa9ee8 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -222,6 +222,9 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
 	if (sid != NULL) {
 		sid_copy(&domain->sid, sid);
 	}
+	domain->domain_flags = tdc->trust_flags;
+	domain->domain_type = tdc->trust_type;
+	domain->domain_trust_attribs = tdc->trust_attribs;
 
 	/* Is this our primary domain ? */
 	if (strequal(domain_name, get_global_sam_name()) &&
@@ -236,6 +239,10 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
 		if (lp_security() == SEC_ADS) {
 			domain->active_directory = true;
 		}
+	} else if (!domain->internal) {
+		if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
+			domain->active_directory = true;
+		}
 	}
 
 	/* Link to domain list */
-- 
2.9.4


From a8ac7dcae2e3b00362ea9d91b5ef7f149bc734a0 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri@samba.org>
Date: Wed, 10 Feb 2016 00:38:11 +0200
Subject: [PATCH 4/4] winbindd: return trust parameters when listing trusts
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When asking a child domain process to list trusts on that domain,
return (along with trust domain names and SID) the trust properties -
flags, type, and attributes.

Use those attributes to initialize domain object.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11691

Signed-off-by: Uri Simchoni <uri@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>

Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Tue Feb 23 22:02:16 CET 2016 on sn-devel-144
---
 source3/winbindd/winbindd_misc.c | 11 +++---
 source3/winbindd/winbindd_util.c | 82 +++++++++++++++++++++++++++++-----------
 2 files changed, 65 insertions(+), 28 deletions(-)

diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index 7d25167..5335ad9 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -172,11 +172,12 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
 
 	for (i=0; i<trusts.count; i++) {
 		extra_data = talloc_asprintf_append_buffer(
-			extra_data, "%s\\%s\\%s\n",
-			trusts.array[i].netbios_name,
-			trusts.array[i].dns_name,
-			sid_string_talloc(state->mem_ctx,
-					  trusts.array[i].sid));
+		    extra_data, "%s\\%s\\%s\\%u\\%u\\%u\n",
+		    trusts.array[i].netbios_name, trusts.array[i].dns_name,
+		    sid_string_talloc(state->mem_ctx, trusts.array[i].sid),
+		    trusts.array[i].trust_flags,
+		    (uint32_t)trusts.array[i].trust_type,
+		    trusts.array[i].trust_attributes);
 	}
 
 	/* add our primary domain */
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index aaa9ee8..b99fac4 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -343,6 +343,8 @@ static void trustdom_list_done(struct tevent_req *req)
 	struct winbindd_response *response;
 	int res, err;
 	char *p;
+	struct winbindd_tdc_domain trust_params = {0};
+	ptrdiff_t extra_len;
 
 	res = wb_domain_request_recv(req, state, &response, &err);
 	if ((res == -1) || (response->result != WINBINDD_OK)) {
@@ -351,17 +353,27 @@ static void trustdom_list_done(struct tevent_req *req)
 		return;
 	}
 
+	if (response->length < sizeof(struct winbindd_response)) {
+		DEBUG(0, ("ill-formed trustdom response - short length\n"));
+		TALLOC_FREE(state);
+		return;
+	}
+
+	extra_len = response->length - sizeof(struct winbindd_response);
+
 	p = (char *)response->extra_data.data;
 
-	while ((p != NULL) && (*p != '\0')) {
+	while ((p - (char *)response->extra_data.data) < extra_len) {
 		char *q, *sidstr, *alt_name;
-		struct dom_sid sid;
-		struct winbindd_domain *domain;
-		char *alternate_name = NULL;
+
+		DEBUG(10, ("parsing response line '%s'\n", p));
+
+		ZERO_STRUCT(trust_params);
+		trust_params.domain_name = p;
 
 		alt_name = strchr(p, '\\');
 		if (alt_name == NULL) {
-			DEBUG(0, ("Got invalid trustdom response\n"));
+			DEBUG(10, ("Got invalid trustdom response\n"));
 			break;
 		}
 
@@ -370,39 +382,63 @@ static void trustdom_list_done(struct tevent_req *req)
 
 		sidstr = strchr(alt_name, '\\');
 		if (sidstr == NULL) {
-			DEBUG(0, ("Got invalid trustdom response\n"));
+			DEBUG(10, ("Got invalid trustdom response\n"));
 			break;
 		}
 
 		*sidstr = '\0';
 		sidstr += 1;
 
-		q = strchr(sidstr, '\n');
-		if (q != NULL)
-			*q = '\0';
+		/* use the real alt_name if we have one, else pass in NULL */
+		if (!strequal(alt_name, "(null)")) {
+			trust_params.dns_name = alt_name;
+		}
+
+		q = strtok(sidstr, "\\");
+		if (q == NULL) {
+			DEBUG(10, ("Got invalid trustdom response\n"));
+			break;
+		}
+
+		if (!string_to_sid(&trust_params.sid, sidstr)) {
+			DEBUG(0, ("Got invalid trustdom response\n"));
+			break;
+		}
 
-		if (!string_to_sid(&sid, sidstr)) {
+		q = strtok(NULL, "\\");
+		if (q == NULL) {
 			DEBUG(0, ("Got invalid trustdom response\n"));
 			break;
 		}
 
-		/* use the real alt_name if we have one, else pass in NULL */
+		trust_params.trust_flags = (uint32_t)strtoul(q, NULL, 10);
 
-		if ( !strequal( alt_name, "(null)" ) )
-			alternate_name = alt_name;
+		q = strtok(NULL, "\\");
+		if (q == NULL) {
+			DEBUG(0, ("Got invalid trustdom response\n"));
+			break;
+		}
+
+		trust_params.trust_type = (uint32_t)strtoul(q, NULL, 10);
 
-		/* If we have an existing domain structure, calling
- 		   add_trusted_domain() will update the SID if
- 		   necessary.  This is important because we need the
- 		   SID for sibling domains */
+		q = strtok(NULL, "\n");
+		if (q == NULL) {
+			DEBUG(10, ("Got invalid trustdom response\n"));
+			break;
+		}
 
-		(void)add_trusted_domain(p, alternate_name,
-					    &cache_methods,
-					    &sid);
+		trust_params.trust_attribs = (uint32_t)strtoul(q, NULL, 10);
+
+		/*
+		 * We always call add_trusted_domain() cause on an existing
+		 * domain structure, it will update the SID if necessary.
+		 * This is important because we need the SID for sibling
+		 * domains.
+		 */
+		(void)add_trusted_domain_from_tdc(&trust_params,
+						  &cache_methods);
 
-		p=q;
-		if (p != NULL)
-			p += 1;
+		p = q + strlen(q) + 1;
 	}
 
 	/*
-- 
2.9.4

