From 0d087e3ba28a9061529c95799624ccc4686eb1e9 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 31 Jul 2003 05:43:47 +0000 Subject: working on transtive trusts issue: * use DsEnumerateDomainTrusts() instead of LDAP search. wbinfo -m now lists all trusted downlevel domains and all domains in the forest. Thnigs to do: o Look at Krb5 connection trusted domains o make sure to initial the trusted domain cache as soon as possible (This used to be commit 0ab00ccaedf204b39c86a9e1c2fcac5f15d0e033) --- source3/nsswitch/winbindd_ads.c | 85 ++++++++++++++++++++++++++++++++++----- source3/nsswitch/winbindd_cache.c | 2 +- source3/nsswitch/winbindd_cm.c | 29 ++++++++++--- source3/nsswitch/winbindd_pam.c | 49 ---------------------- source3/nsswitch/winbindd_util.c | 58 ++++++++++++++++++++++++-- 5 files changed, 154 insertions(+), 69 deletions(-) (limited to 'source3/nsswitch') diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index 462dd21531..7140dc35a0 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -801,24 +801,91 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, char ***alt_names, DOM_SID **dom_sids) { - ADS_STRUCT *ads; - ADS_STATUS rc; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DS_DOMAIN_TRUSTS *domains = NULL; + int count = 0; + int i; + struct cli_state *cli = NULL; + /* i think we only need our forest and downlevel trusted domains */ + uint32 flags = DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND; DEBUG(3,("ads: trusted_domains\n")); *num_domains = 0; - *names = NULL; + *alt_names = NULL; + *names = NULL; + *dom_sids = NULL; + + if ( !NT_STATUS_IS_OK(result = cm_fresh_connection(domain->name, PI_NETLOGON, &cli)) ) { + DEBUG(5, ("trusted_domains: Could not open a connection to %s for PIPE_NETLOGON (%s)\n", + domain->name, nt_errstr(result))); + return NT_STATUS_UNSUCCESSFUL; + } + + if ( NT_STATUS_IS_OK(result) ) + result = cli_ds_enum_domain_trusts( cli, mem_ctx, cli->desthost, flags, &domains, &count ); + + if ( NT_STATUS_IS_OK(result) && count) { + + /* Allocate memory for trusted domain names and sids */ - ads = ads_cached_connection(domain); + if ( !(*names = (char **)talloc(mem_ctx, sizeof(char *) * count)) ) { + DEBUG(0, ("trusted_domains: out of memory\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } - if (!ads) { - domain->last_status = NT_STATUS_SERVER_DISABLED; - return NT_STATUS_UNSUCCESSFUL; + if ( !(*alt_names = (char **)talloc(mem_ctx, sizeof(char *) * count)) ) { + DEBUG(0, ("trusted_domains: out of memory\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + + if ( !(*dom_sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) * count)) ) { + DEBUG(0, ("trusted_domains: out of memory\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + + /* Copy across names and sids */ + + for (i = 0; i < count; i++) { + fstring tmp; + fstring tmp2; + + (*names)[i] = NULL; + (*alt_names)[i] = NULL; + ZERO_STRUCT( (*dom_sids)[i] ); + + if ( domains[i].netbios_ptr ) { + unistr2_to_ascii(tmp, &domains[i].netbios_domain, sizeof(tmp) - 1); + (*names)[i] = talloc_strdup(mem_ctx, tmp); + } + + if ( domains[i].dns_ptr ) { + unistr2_to_ascii(tmp2, &domains[i].dns_domain, sizeof(tmp2) - 1); + (*alt_names)[i] = talloc_strdup(mem_ctx, tmp2); + } + + /* sometimes we will get back a NULL SID from this call */ + + if ( domains[i].sid_ptr ) + sid_copy(&(*dom_sids)[i], &domains[i].sid.sid); + } + + *num_domains = count; } - rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids); +done: + + SAFE_FREE( domains ); + + /* remove connection; This is a special case to the \NETLOGON pipe */ + + if ( cli ) + cli_shutdown( cli ); - return ads_ntstatus(rc); + return result; } /* find the domain sid for a domain */ diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index f1c8542815..af4ccabade 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -106,7 +106,7 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) case SEC_ADS: { extern struct winbindd_methods ads_methods; /* always obey the lp_security parameter for our domain */ - if ( strequal(lp_realm(), domain->alt_name) ) { + if ( strequal(lp_realm(), domain->alt_name) || strequal(lp_workgroup(), domain->name) ) { domain->backend = &ads_methods; break; } diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index dbc3062edd..f07117b5ab 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -152,7 +152,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller, &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, - ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, + ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, &retry); secrets_named_mutex_release(new_conn->controller); @@ -194,6 +194,25 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, return NT_STATUS_OK; } +/************************************************************************ + Wrapper around statuc cm_open_connection to retreive a freshly + setup cli_state struct +************************************************************************/ + +NTSTATUS cm_fresh_connection(const char *domain, const int pipe_index, + struct cli_state **cli) +{ + NTSTATUS result; + struct winbindd_cm_conn conn; + + result = cm_open_connection( domain, pipe_index, &conn ); + + if ( NT_STATUS_IS_OK(result) ) + *cli = conn.cli; + + return result; +} + /* Return true if a connection is still alive */ static BOOL connection_ok(struct winbindd_cm_conn *conn) @@ -326,13 +345,11 @@ BOOL cm_check_for_native_mode_win2k( const char *domain ) done: -#if 0 - /* - * I don't think we need to shutdown here ? JRA. - */ + /* close the connection; no other cals use this pipe and it is called only + on reestablishing the domain list --jerry */ + if ( conn.cli ) cli_shutdown( conn.cli ); -#endif return ret; } diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 8edd00f806..a8908487c1 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -53,55 +53,6 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -/******************************************************************* - wrapper around retrieving the trust account password -*******************************************************************/ - -static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], - time_t *pass_last_set_time, uint32 *channel) -{ - DOM_SID sid; - char *pwd; - - /* if we are a DC and this is not our domain, then lookup an account - for the domain trust */ - - if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) - { - if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, - pass_last_set_time) ) - { - DEBUG(0, ("get_trust_pw: could not fetch trust account " - "password for trusted domain %s\n", domain)); - return False; - } - - *channel = SEC_CHAN_DOMAIN; - E_md4hash(pwd, ret_pwd); - SAFE_FREE(pwd); - - return True; - } - else /* just get the account for our domain (covers - ROLE_DOMAIN_MEMBER as well */ - { - /* get the machine trust account for our domain */ - - if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd, - pass_last_set_time, channel) ) - { - DEBUG(0, ("get_trust_pw: could not fetch trust account " - "password for my domain %s\n", domain)); - return False; - } - - return True; - } - - /* Failure */ - return False; -} - /********************************************************************** Authenticate a user with a clear test password **********************************************************************/ diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 6177c46aef..ca5146fc56 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -111,7 +111,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const fstrcpy(domain->name, alt_name); fstrcpy(domain->alt_name, domain_name); } else { - fstrcpy(domain->name, domain_name); + fstrcpy(domain->name, domain_name); if (alt_name) { fstrcpy(domain->alt_name, alt_name); } @@ -183,8 +183,8 @@ void rescan_trusted_domains(BOOL force) continue; } - /* Add each domain to the trusted domain list. Each domain inherits - the access methods of its parent */ + /* Add each domain to the trusted domain list */ + for(i = 0; i < num_domains; i++) { DEBUG(10,("Found domain %s\n", names[i])); add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, @@ -209,7 +209,7 @@ BOOL init_domain_list(void) free_domain_list(); /* Add ourselves as the first entry */ - domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL); + domain = add_trusted_domain( lp_workgroup(), NULL, &cache_methods, NULL); if (!secrets_fetch_domain_sid(domain->name, &domain->sid)) { DEBUG(1, ("Could not fetch sid for our domain %s\n", domain->name)); @@ -782,3 +782,53 @@ BOOL winbindd_upgrade_idmap(void) return idmap_convert(idmap_name); } + +/******************************************************************* + wrapper around retrieving the trust account password +*******************************************************************/ + +BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], + time_t *pass_last_set_time, uint32 *channel) +{ + DOM_SID sid; + char *pwd; + + /* if we are a DC and this is not our domain, then lookup an account + for the domain trust */ + + if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) + { + if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, + pass_last_set_time) ) + { + DEBUG(0, ("get_trust_pw: could not fetch trust account " + "password for trusted domain %s\n", domain)); + return False; + } + + *channel = SEC_CHAN_DOMAIN; + E_md4hash(pwd, ret_pwd); + SAFE_FREE(pwd); + + return True; + } + else /* just get the account for our domain (covers + ROLE_DOMAIN_MEMBER as well */ + { + /* get the machine trust account for our domain */ + + if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd, + pass_last_set_time, channel) ) + { + DEBUG(0, ("get_trust_pw: could not fetch trust account " + "password for my domain %s\n", domain)); + return False; + } + + return True; + } + + /* Failure */ + return False; +} + -- cgit