From b2317c097954844af4a0596fea507f0139d14465 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 2 Jan 2007 21:48:47 +0000 Subject: r20488: When joined to a child domain in a multi-domain/single domain tree, the child domain cannot always resolve SIDs in sibling domains. Windows tries to contact a DC in its own domain and then the root domain in the forest. This async changes makes winbindd's name2sid() call do the same. (This used to be commit 7b2bf0e5a6b8d4119657c7a34aa53c9a0c1d5723) --- source3/nsswitch/winbindd.h | 1 + source3/nsswitch/winbindd_async.c | 77 ++++++++++++++++++++++++++++++++++++--- source3/nsswitch/winbindd_util.c | 17 +++++++++ 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index b62cc0af19..59557c4942 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -151,6 +151,7 @@ struct winbindd_child { struct winbindd_domain { fstring name; /* Domain name */ fstring alt_name; /* alt Domain name (if any) */ + fstring forest_name; /* Name of the AD forest we're in */ DOM_SID sid; /* SID for this domain */ BOOL initialized; /* Did we already ask for the domain mode? */ BOOL native_mode; /* is this a win2k domain in native mode ? */ diff --git a/source3/nsswitch/winbindd_async.c b/source3/nsswitch/winbindd_async.c index 913cfdecc5..7bedd5a0fd 100644 --- a/source3/nsswitch/winbindd_async.c +++ b/source3/nsswitch/winbindd_async.c @@ -772,7 +772,11 @@ enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain, return WINBINDD_OK; } -static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, +/******************************************************************** + This is the second callback after contacting the forest root +********************************************************************/ + +static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) { @@ -804,8 +808,71 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, (enum lsa_SidType)response->data.sid.type); } -void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name, - const char *name, +/******************************************************************** + This is the first callback after contacting our own domain +********************************************************************/ + +static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const DOM_SID *sid, + enum lsa_SidType type) = + (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c; + DOM_SID sid; + + if (!success) { + DEBUG(5, ("lookupname_recv: lookup_name() failed!\n")); + cont(private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + if (response->result != WINBINDD_OK) { + /* Try again using the forest root */ + struct winbindd_domain *root_domain = find_root_domain(); + struct winbindd_cli_state *state = (struct winbindd_cli_state*)private_data; + struct winbindd_request request; + char *name_domain, *name_account; + + if ( !root_domain ) { + DEBUG(5,("lookupname_recv: unable determine forest root\n")); + cont(private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + name_domain = state->request.data.name.dom_name; + name_account = state->request.data.name.name; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_LOOKUPNAME; + fstrcpy(request.data.name.dom_name, name_domain); + fstrcpy(request.data.name.name, name_account); + + do_async_domain(mem_ctx, root_domain, &request, lookupname_recv2, + (void *)cont, private_data); + + return; + } + + if (!string_to_sid(&sid, response->data.sid.sid)) { + DEBUG(0, ("Could not convert string %s to sid\n", + response->data.sid.sid)); + cont(private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + cont(private_data, True, &sid, + (enum lsa_SidType)response->data.sid.type); +} + +/******************************************************************** + The lookup name call first contacts a DC in its own domain + and fallbacks to contact a DC in the forest in our domain doesn't + know the name. +********************************************************************/ + +void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, + const char *dom_name, const char *name, void (*cont)(void *private_data, BOOL success, const DOM_SID *sid, enum lsa_SidType type), @@ -814,9 +881,7 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name, struct winbindd_request request; struct winbindd_domain *domain; - domain = find_lookup_domain_from_name(dom_name); - - if (domain == NULL) { + if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) { DEBUG(5, ("Could not find domain for name %s\n", dom_name)); cont(private_data, False, NULL, SID_NAME_UNKNOWN); return; diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index d0a59b0cbe..419c80e3c4 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -529,6 +529,10 @@ BOOL init_domain_list(void) &cache_methods, &our_sid); domain->primary = True; setup_domain_child(domain, &domain->child, NULL); +#if 0 /* old code needed to get the parent domain */ + init_dc_connection(domain); +#endif + /* 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 @@ -652,6 +656,19 @@ struct winbindd_domain *find_our_domain(void) return NULL; } +struct winbindd_domain *find_root_domain(void) +{ + struct winbindd_domain *ours = find_our_domain(); + + if ( !ours ) + return NULL; + + if ( strlen(ours->forest_name) == 0 ) + return NULL; + + return find_domain_from_name( ours->forest_name ); +} + struct winbindd_domain *find_builtin_domain(void) { DOM_SID sid; -- cgit