--- /dev/null
+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