commit 9dd0bb462b613a5f6f41d4130bfd31c0a64debd7
Author:     Jeremy Allison <jra@samba.org>
AuthorDate: Mon Jan 13 15:23:00 2014 +0100
Commit:     Andreas Schneider <asn@samba.org>
CommitDate: Wed Feb 5 11:45:44 2014 +0100

    s3-winbind: Move setup_domain_child() into add_trusted_domain().
    
    Ensure it only gets called when a new domain is allocated
    and added to the list.
    
    This should fix problems with the previous logic where
    setup_domain_child() was called in places where an existing
    domain was returned.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10358
---
 source3/winbindd/winbindd_util.c | 74 ++++++++++++++++++----------------------
 1 file changed, 33 insertions(+), 41 deletions(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 37b6578..353722e 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -89,7 +89,10 @@ static bool is_in_internal_domain(const struct dom_sid *sid)
 }
 
 
-/* Add a trusted domain to our list of domains */
+/* 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)
@@ -99,6 +102,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 	char *idmap_config_option;
 	const char *param;
 	const char **ignored_domains, **dom;
+	int role = lp_server_role();
 
 	ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
 	for (dom=ignored_domains; dom && *dom; dom++) {
@@ -146,7 +150,10 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 
 	if (domain != NULL) {
 		/*
-		 * We found a match. Possibly update the SID
+		 * We found a match on domain->name or
+		 * domain->alt_name. Possibly update the SID
+		 * if the stored SID was the NULL SID
+		 * and return the matching entry.
 		 */
 		if ((sid != NULL)
 		    && dom_sid_equal(&domain->sid, &global_sid_NULL)) {
@@ -192,6 +199,15 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 		sid_copy(&domain->sid, sid);
 	}
 
+	/* Is this our primary domain ? */
+	if (strequal(domain_name, get_global_sam_name()) &&
+	    (role != ROLE_DOMAIN_MEMBER)) {
+		domain->primary = true;
+	} else if (strequal(domain_name, lp_workgroup()) &&
+		   (role == ROLE_DOMAIN_MEMBER)) {
+		domain->primary = true;
+	}
+
 	/* Link to domain list */
 	DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *);
 
@@ -228,6 +244,8 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 
 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):""));
@@ -341,18 +359,10 @@ static void trustdom_list_done(struct tevent_req *req)
  		   necessary.  This is important because we need the
  		   SID for sibling domains */
 
-		if ( find_domain_from_name_noinit(p) != NULL ) {
-			domain = add_trusted_domain(p, alternate_name,
-						    &cache_methods,
-						    &sid);
-		} else {
-			domain = add_trusted_domain(p, alternate_name,
-						    &cache_methods,
-						    &sid);
-			if (domain) {
-				setup_domain_child(domain);
-			}
-		}
+		(void)add_trusted_domain(p, alternate_name,
+					    &cache_methods,
+					    &sid);
+
 		p=q;
 		if (p != NULL)
 			p += 1;
@@ -422,13 +432,10 @@ static void rescan_forest_root_trusts( void )
 		d = find_domain_from_name_noinit( dom_list[i].domain_name );
 
 		if ( !d ) {
-			d = add_trusted_domain( dom_list[i].domain_name,
+			(void)add_trusted_domain( dom_list[i].domain_name,
 						dom_list[i].dns_name,
 						&cache_methods,
-						&dom_list[i].sid );
-			if (d != NULL) {
-				setup_domain_child(d);
-			}
+						&dom_list[i].sid);
 		}
 
 		if (d == NULL) {
@@ -494,13 +501,10 @@ static void rescan_forest_trusts( void )
 			   about it */
 
 			if ( !d ) {
-				d = add_trusted_domain( dom_list[i].domain_name,
+				(void)add_trusted_domain( dom_list[i].domain_name,
 							dom_list[i].dns_name,
 							&cache_methods,
-							&dom_list[i].sid );
-				if (d != NULL) {
-					setup_domain_child(d);
-				}
+							&dom_list[i].sid);
 			}
 
 			if (d == NULL) {
@@ -601,7 +605,6 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai
 /* Look up global info for the winbind daemon */
 bool init_domain_list(void)
 {
-	struct winbindd_domain *domain;
 	int role = lp_server_role();
 
 	/* Free existing list */
@@ -609,26 +612,18 @@ bool init_domain_list(void)
 
 	/* BUILTIN domain */
 
-	domain = add_trusted_domain("BUILTIN", NULL, &cache_methods,
-				    &global_sid_Builtin);
-	if (domain) {
-		setup_domain_child(domain);
-	}
+	(void)add_trusted_domain("BUILTIN", NULL, &cache_methods,
+				 &global_sid_Builtin);
 
 	/* Local SAM */
 
-	domain = add_trusted_domain(get_global_sam_name(), NULL,
-				    &cache_methods, get_global_sam_sid());
-	if (domain) {
-		if ( role != ROLE_DOMAIN_MEMBER ) {
-			domain->primary = True;
-		}
-		setup_domain_child(domain);
-	}
+	(void)add_trusted_domain(get_global_sam_name(), NULL,
+				 &cache_methods, get_global_sam_sid());
 
 	/* Add ourselves as the first entry. */
 
 	if ( role == ROLE_DOMAIN_MEMBER ) {
+		struct winbindd_domain *domain;
 		struct dom_sid our_sid;
 
 		if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
@@ -639,9 +634,6 @@ bool init_domain_list(void)
 		domain = add_trusted_domain( lp_workgroup(), lp_realm(),
 					     &cache_methods, &our_sid);
 		if (domain) {
-			domain->primary = True;
-			setup_domain_child(domain);
-
 			/* 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
