diff options
Diffstat (limited to 'source3/auth/auth_domain.c')
-rw-r--r-- | source3/auth/auth_domain.c | 102 |
1 files changed, 91 insertions, 11 deletions
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 79cf5b156d..eebe647ec0 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -212,7 +212,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli))); result = cli_nt_setup_creds(*cli, sec_chan, trust_passwd, &neg_flags, 2); if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("connect_to_domain_password_server: unable to setup the NETLOGON credentials to machine \ + DEBUG(0,("connect_to_domain_password_server: unable to setup the PDC credentials to machine \ %s. Error was : %s.\n", remote_machine, nt_errstr(result))); cli_nt_session_close(*cli); cli_ulogoff(*cli); @@ -262,23 +262,103 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, We have been asked to dynamically determine the IP addresses of the PDC and BDC's for DOMAIN, and query them in turn. ************************************************************************/ -static NTSTATUS find_connect_dc(struct cli_state **cli, +static NTSTATUS find_connect_pdc(struct cli_state **cli, const char *domain, const char *setup_creds_as, uint16 sec_chan, unsigned char *trust_passwd, time_t last_change_time) { - struct in_addr dc_ip; - fstring srv_name; + struct in_addr *ip_list = NULL; + int count = 0; + int i; + NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS; + time_t time_now = time(NULL); + BOOL use_pdc_only = False; + BOOL list_ordered; - if ( !rpc_find_dc(lp_workgroup(), srv_name, &dc_ip) ) { - DEBUG(0,("find_connect_dc: Failed to find an DCs for %s\n", lp_workgroup())); - return NT_STATUS_NO_LOGON_SERVERS; + /* + * If the time the machine password has changed + * was less than an hour ago then we need to contact + * the PDC only, as we cannot be sure domain replication + * has yet taken place. Bug found by Gerald (way to go + * Gerald !). JRA. + */ + + if (time_now - last_change_time < 3600) + use_pdc_only = True; + + if (use_pdc_only) { + struct in_addr pdc_ip; + + if (!get_pdc_ip(domain, &pdc_ip)) + return NT_STATUS_NO_LOGON_SERVERS; + + if ((ip_list = (struct in_addr *) + malloc(sizeof(struct in_addr))) == NULL) + return NT_STATUS_NO_MEMORY; + + ip_list[0] = pdc_ip; + count = 1; + + } else { + if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) + return NT_STATUS_NO_LOGON_SERVERS; } - - return attempt_connect_to_dc( cli, domain, &dc_ip, setup_creds_as, - sec_chan, trust_passwd ); + + /* + * Firstly try and contact a PDC/BDC who has the same + * network address as any of our interfaces. + */ + for(i = 0; i < count; i++) { + if( !list_ordered && !is_local_net(ip_list[i]) ) + continue; + + if(NT_STATUS_IS_OK(nt_status = + attempt_connect_to_dc(cli, domain, + &ip_list[i], setup_creds_as, + sec_chan, trust_passwd))) + break; + + zero_ip(&ip_list[i]); /* Tried and failed. */ + } + + /* + * Secondly try and contact a random PDC/BDC. + */ + if(!NT_STATUS_IS_OK(nt_status)) { + i = (sys_random() % count); + + if (!is_zero_ip(ip_list[i])) { + if (!NT_STATUS_IS_OK(nt_status = + attempt_connect_to_dc(cli, domain, + &ip_list[i], setup_creds_as, + sec_chan, trust_passwd))) + zero_ip(&ip_list[i]); /* Tried and failed. */ + } + } + + /* + * Finally go through the IP list in turn, ignoring any addresses + * we have already tried. + */ + if(!NT_STATUS_IS_OK(nt_status)) { + /* + * Try and connect to any of the other IP addresses in the PDC/BDC list. + * Note that from a WINS server the #1 IP address is the PDC. + */ + for(i = 0; i < count; i++) { + if (is_zero_ip(ip_list[i])) + continue; + + if (NT_STATUS_IS_OK(nt_status = attempt_connect_to_dc(cli, domain, + &ip_list[i], setup_creds_as, sec_chan, trust_passwd))) + break; + } + } + + SAFE_FREE(ip_list); + return nt_status; } /*********************************************************************** @@ -313,7 +393,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, while (!NT_STATUS_IS_OK(nt_status) && next_token(&server,remote_machine,LIST_SEP,sizeof(remote_machine))) { if(lp_security() != SEC_ADS && strequal(remote_machine, "*")) { - nt_status = find_connect_dc(&cli, domain, setup_creds_as, sec_chan, trust_passwd, last_change_time); + nt_status = find_connect_pdc(&cli, domain, setup_creds_as, sec_chan, trust_passwd, last_change_time); } else { int i; BOOL retry = True; |