diff options
Diffstat (limited to 'source3/nsswitch/winbindd_cm.c')
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 150 |
1 files changed, 86 insertions, 64 deletions
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index f5dcb69ce0..dc2d6cfc6f 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -459,97 +459,107 @@ static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx, return True; } -static BOOL get_dcs_1c(TALLOC_CTX *mem_ctx, - const struct winbindd_domain *domain, - struct dc_name_ip **dcs, int *num_dcs) +/******************************************************************* + convert an ip to a name +*******************************************************************/ + +static void dcip_to_name( const char *domainname, const char *realm, struct in_addr ip, fstring name ) { - struct ip_service *iplist = NULL; - int i, num = 0; + /* try node status request first */ - if (!internal_resolve_name(domain->name, 0x1c, &iplist, &num, - lp_name_resolve_order())) - return False; + if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) + return; - /* Now try to find the server names of at least one IP address, hosts - * not replying are cached as such */ + /* backup in case the ads stuff fails */ - for (i=0; i<num; i++) { + fstrcpy( name, inet_ntoa(ip) ); - fstring dcname; +#ifdef WITH_ADS + /* for active directory servers, try to get the ldap server name. + None of these failure should be considered critical for now */ - if (!name_status_find(domain->name, 0x1c, 0x20, iplist[i].ip, - dcname)) - continue; + if ( lp_security() == SEC_ADS ) + { + ADS_STRUCT *ads; + ADS_STATUS status; - if (add_one_dc_unique(mem_ctx, domain->name, dcname, - iplist[i].ip, dcs, num_dcs)) { - /* One DC responded, so we assume that he will also - work on 139/445 */ - break; + ads = ads_init( realm, domainname, NULL ); + ads->auth.flags |= ADS_AUTH_NO_BIND; + + if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) ) { + ads_destroy( &ads ); + return; } - } - SAFE_FREE(iplist); + status = ads_server_info(ads); + if ( !ADS_ERR_OK(status) ) { + ads_destroy( &ads ); + return; + } - return True; + fstrcpy(name, ads->config.ldap_server_name); + + ads_destroy( &ads ); + } +#endif + + return; } + +/******************************************************************* + Retreive a list of IP address for domain controllers. Fill in + the dcs[] with results. +*******************************************************************/ + static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, struct dc_name_ip **dcs, int *num_dcs) { fstring dcname; - struct in_addr ip; - BOOL is_our_domain; + struct in_addr ip; + struct ip_service *ip_list = NULL; + int iplist_size = 0; + int i; + BOOL is_our_domain; - const char *p; is_our_domain = strequal(domain->name, lp_workgroup()); - if (!is_our_domain && get_dc_name_via_netlogon(domain, dcname, &ip) && - add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs)) - return True; - - if (!is_our_domain) { - /* NETLOGON to our own domain could not give us a DC name - * (which is an error), fall back to looking up domain#1c */ - return get_dcs_1c(mem_ctx, domain, dcs, num_dcs); + if ( !is_our_domain + && get_dc_name_via_netlogon(domain, dcname, &ip) + && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) ) + { + return True; } - if (must_use_pdc(domain->name) && get_pdc_ip(domain->name, &ip)) { - - if (!name_status_find(domain->name, 0x1b, 0x20, ip, dcname)) - return False; - - if (add_one_dc_unique(mem_ctx, domain->name, - dcname, ip, dcs, num_dcs)) + if ( is_our_domain + && must_use_pdc(domain->name) + && get_pdc_ip(domain->name, &ip)) + { + if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs)) return True; } - p = lp_passwordserver(); - - if (*p == 0) - return get_dcs_1c(mem_ctx, domain, dcs, num_dcs); + /* try standard netbios queries first */ - while (next_token(&p, dcname, LIST_SEP, sizeof(dcname))) { - - if (strequal(dcname, "*")) { - get_dcs_1c(mem_ctx, domain, dcs, num_dcs); - continue; - } + get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False); - if (!resolve_name(dcname, &ip, 0x20)) - continue; + /* check for security = ads and use DNS if we can */ - /* Even if we got the dcname, double check the name to use for - * the netlogon auth2 */ + if ( iplist_size==0 && lp_security() == SEC_ADS ) + get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True); - if (!name_status_find(domain->name, 0x1c, 0x20, ip, dcname)) - continue; + /* now add to the dc array. We'll wait until the last minute + to look up the name of the DC. But we fill in the char* for + the ip now in to make the failed connection cache work */ - add_one_dc_unique(mem_ctx, domain->name, dcname, ip, - dcs, num_dcs); + for ( i=0; i<iplist_size; i++ ) { + add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip), + ip_list[i].ip, dcs, num_dcs); } + SAFE_FREE( ip_list ); + return True; } @@ -560,7 +570,7 @@ static BOOL find_new_dc(TALLOC_CTX *mem_ctx, struct dc_name_ip *dcs = NULL; int num_dcs = 0; - char **dcnames = NULL; + const char **dcnames = NULL; int num_dcnames = 0; struct sockaddr_in *addrs = NULL; @@ -587,18 +597,25 @@ static BOOL find_new_dc(TALLOC_CTX *mem_ctx, if ((num_dcnames == 0) || (num_dcnames != num_addrs)) return False; - if (!open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd)) { + if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) ) + { for (i=0; i<num_dcs; i++) { add_failed_connection_entry(domain->name, - dcs[i].name, - NT_STATUS_UNSUCCESSFUL); + dcs[i].name, NT_STATUS_UNSUCCESSFUL); } return False; } - fstrcpy(dcname, dcnames[fd_index]); *addr = addrs[fd_index]; + /* if we have no name on the server or just an IP address for + the name, now try to get the name */ + + if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' ) + dcip_to_name( domain->name, domain->alt_name, addr->sin_addr, dcname ); + else + fstrcpy(dcname, dcnames[fd_index]); + return True; } @@ -883,6 +900,11 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) done: + DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name, + domain->active_directory ? "ADS" : "NT4", + domain->native_mode ? "native mode" : + ((domain->active_directory && !domain->native_mode) ? "mixed mode" : ""))); + /* close the connection; no other calls use this pipe and it is called only on reestablishing the domain list --jerry */ |