X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fauth%2Fauth_domain.c;h=2991684280546b794ede64d5a9432ea183d11afc;hb=cad20ab63b55462836da007de39fc84ffa38eda8;hp=f74f1bb9e89f393effd5cd1edacdbc6f5cdc9232;hpb=2edcc96c11c1f5c9294f1730973e7582b3a3acbd;p=sfrench%2Fsamba-autobuild%2F.git diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index f74f1bb9e89..29916842805 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -24,9 +24,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH -BOOL global_machine_password_needs_changing = False; +extern BOOL global_machine_password_needs_changing; -extern pstring global_myname; extern userdom_struct current_user_info; @@ -46,21 +45,23 @@ static NTSTATUS ads_resolve_dc(fstring remote_machine, return NT_STATUS_NO_LOGON_SERVERS; } + DEBUG(4,("ads_resolve_dc: realm=%s\n", ads->config.realm)); + + ads->auth.flags |= ADS_AUTH_NO_BIND; + #ifdef HAVE_ADS /* a full ads_connect() is actually overkill, as we don't srictly need to do the SASL auth in order to get the info we need, but libads doesn't offer a better way right now */ - if (!ADS_ERR_OK(ads_connect(ads))) { - return NT_STATUS_NO_LOGON_SERVERS; - } + ads_connect(ads); #endif - fstrcpy(remote_machine, ads->ldap_server_name); + fstrcpy(remote_machine, ads->config.ldap_server_name); strupper(remote_machine); - *dest_ip = *interpret_addr2(ads->ldap_server); + *dest_ip = ads->ldap_ip; ads_destroy(&ads); - if (!*remote_machine) { + if (!*remote_machine || is_zero_ip(*dest_ip)) { return NT_STATUS_NO_LOGON_SERVERS; } @@ -86,8 +87,7 @@ static NTSTATUS rpc_resolve_dc(const char *server, way to find it, but until we have a RPC call that does this it will have to do */ if (!name_status_find("*", 0x20, 0x20, to_ip, remote_machine)) { - DEBUG(2, ("connect_to_domain_password_server: Can't " - "resolve name for IP %s\n", server)); + DEBUG(2, ("rpc_resolve_dc: Can't resolve name for IP %s\n", server)); return NT_STATUS_NO_LOGON_SERVERS; } @@ -98,7 +98,7 @@ static NTSTATUS rpc_resolve_dc(const char *server, fstrcpy(remote_machine, server); strupper(remote_machine); if (!resolve_name(remote_machine, dest_ip, 0x20)) { - DEBUG(1,("connect_to_domain_password_server: Can't resolve address for %s\n", + DEBUG(1,("rpc_resolve_dc: Can't resolve address for %s\n", remote_machine)); return NT_STATUS_NO_LOGON_SERVERS; } @@ -115,7 +115,7 @@ static NTSTATUS rpc_resolve_dc(const char *server, * @param cli the cli to return containing the active connection * @param server either a machine name or text IP address to * connect to. - * @param trust_password the trust password to establish the + * @param trust_passwd the trust password to establish the * credentials with. * **/ @@ -124,17 +124,19 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, const char *server, const char *setup_creds_as, uint16 sec_chan, - const unsigned char *trust_passwd) + const unsigned char *trust_passwd, + BOOL *retry) { struct in_addr dest_ip; fstring remote_machine; NTSTATUS result; - if (lp_security() == SEC_ADS) { + *retry = False; + + if (lp_security() == SEC_ADS) result = ads_resolve_dc(remote_machine, &dest_ip); - } else { + else result = rpc_resolve_dc(server, remote_machine, &dest_ip); - } if (!NT_STATUS_IS_OK(result)) { DEBUG(2,("connect_to_domain_password_server: unable to resolve DC: %s\n", @@ -162,14 +164,21 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, * ACCESS_DENIED errors if 2 auths are done from the same machine. JRA. */ + *retry = True; + if (!grab_server_mutex(server)) return NT_STATUS_NO_LOGON_SERVERS; /* Attempt connection */ - result = cli_full_connection(cli, global_myname, server, - &dest_ip, 0, "IPC$", "IPC", "", "", "", 0); + result = cli_full_connection(cli, global_myname(), remote_machine, + &dest_ip, 0, "IPC$", "IPC", "", "", "",0, retry); if (!NT_STATUS_IS_OK(result)) { + /* map to something more useful */ + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + result = NT_STATUS_NO_LOGON_SERVERS; + } + release_server_mutex(); return result; } @@ -187,7 +196,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, * into account also. This patch from "Bjart Kvarme" . */ - if(cli_nt_session_open(*cli, PIPE_NETLOGON) == False) { + if(cli_nt_session_open(*cli, PI_NETLOGON) == False) { DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli))); cli_nt_session_close(*cli); @@ -204,10 +213,10 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli))); return NT_STATUS_NO_MEMORY; } - result = cli_nt_setup_creds(*cli, sec_chan, trust_passwd); + result = cli_nt_establish_netlogon(*cli, sec_chan, trust_passwd); if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("connect_to_domain_password_server: unable to setup the PDC credentials to machine \ + DEBUG(0,("connect_to_domain_password_server: unable to setup the NETLOGON credentials to machine \ %s. Error was : %s.\n", remote_machine, nt_errstr(result))); cli_nt_session_close(*cli); cli_ulogoff(*cli); @@ -232,7 +241,10 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, uint16 sec_chan, const unsigned char *trust_passwd) { + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + BOOL retry = True; fstring dc_name; + int i; /* * Ignore addresses we have already tried. @@ -241,97 +253,36 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, if (is_zero_ip(*ip)) return NT_STATUS_NO_LOGON_SERVERS; - if (!lookup_dc_name(global_myname, domain, ip, dc_name)) + if (!lookup_dc_name(global_myname(), domain, ip, dc_name)) return NT_STATUS_NO_LOGON_SERVERS; - return connect_to_domain_password_server(cli, dc_name, setup_creds_as, sec_chan, trust_passwd); + for (i = 0; (!NT_STATUS_IS_OK(ret)) && retry && (i < 3); i++) + ret = connect_to_domain_password_server(cli, dc_name, setup_creds_as, + sec_chan, trust_passwd, &retry); + return ret; } /*********************************************************************** - We have been asked to dynamcially determine the IP addresses of + 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_pdc(struct cli_state **cli, +static NTSTATUS find_connect_dc(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 *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; - - /* - * 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; + struct in_addr dc_ip; + fstring srv_name; - if (!get_dc_list(use_pdc_only, domain, &ip_list, &count)) + if (!rpc_find_dc(domain, 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; - - /* - * 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(!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; + + return attempt_connect_to_dc( cli, domain, &dc_ip, setup_creds_as, + sec_chan, trust_passwd ); } /*********************************************************************** @@ -345,7 +296,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, const char *domain, uchar chal[8], auth_serversupplied_info **server_info, - char *server, char *setup_creds_as, + const char *server, const char *setup_creds_as, uint16 sec_chan, unsigned char trust_passwd[16], time_t last_change_time) @@ -366,9 +317,13 @@ 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_pdc(&cli, domain, setup_creds_as, sec_chan, trust_passwd, last_change_time); + nt_status = find_connect_dc(&cli, domain, setup_creds_as, sec_chan, trust_passwd, last_change_time); } else { - nt_status = connect_to_domain_password_server(&cli, remote_machine, setup_creds_as, sec_chan, trust_passwd); + int i; + BOOL retry = True; + for (i = 0; !NT_STATUS_IS_OK(nt_status) && retry && (i < 3); i++) + nt_status = connect_to_domain_password_server(&cli, remote_machine, setup_creds_as, + sec_chan, trust_passwd, &retry); } } @@ -385,6 +340,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, */ nt_status = cli_netlogon_sam_network_logon(cli, mem_ctx, + NULL, user_info->smb_name.str, user_info->domain.str, user_info->wksta_name.str, chal, user_info->lm_resp, user_info->nt_resp, @@ -396,16 +352,14 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, "Error was %s.\n", user_info->smb_name.str, user_info->domain.str, cli->srv_name_slash, nt_errstr(nt_status))); + + /* map to something more useful */ + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) { + nt_status = NT_STATUS_NO_LOGON_SERVERS; + } } else { nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str, user_info->smb_name.str, domain, server_info, &info3); -#if 0 - /* The stuff doesn't work right yet */ - SMB_ASSERT(sizeof((*server_info)->session_key) == sizeof(info3.user_sess_key)); - memcpy((*server_info)->session_key, info3.user_sess_key, sizeof((*server_info)->session_key)/* 16 */); - SamOEMhash((*server_info)->session_key, trust_passwd, sizeof((*server_info)->session_key)); -#endif - uni_group_cache_store_netlogon(mem_ctx, &info3); } @@ -450,7 +404,8 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, char *password_server; unsigned char trust_passwd[16]; time_t last_change_time; - char *domain = lp_workgroup(); + const char *domain = lp_workgroup(); + uint32 sec_channel_type = 0; if (!user_info || !server_info || !auth_context) { DEBUG(1,("check_ntdomain_security: Critical variables not present. Failing.\n")); @@ -463,7 +418,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, * password file. */ - if(is_netbios_alias_or_name(user_info->domain.str)) { + if(is_myname(user_info->domain.str)) { DEBUG(3,("check_ntdomain_security: Requested domain was for this machine.\n")); return NT_STATUS_LOGON_FAILURE; } @@ -473,16 +428,19 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, * No need to become_root() as secrets_init() is done at startup. */ - if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time)) + if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time, &sec_channel_type)) { DEBUG(0, ("check_ntdomain_security: could not fetch trust account password for domain '%s'\n", domain)); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } - /* Test if machine password is expired and need to be changed */ - if (time(NULL) > last_change_time + lp_machine_password_timeout()) - { - global_machine_password_needs_changing = True; + /* Test if machine password has expired and needs to be changed */ + if (lp_machine_password_timeout()) { + if (last_change_time > 0 && + time(NULL) > (last_change_time + + lp_machine_password_timeout())) { + global_machine_password_needs_changing = True; + } } /* @@ -495,12 +453,12 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, nt_status = domain_client_validate(mem_ctx, user_info, domain, (uchar *)auth_context->challenge.data, server_info, - password_server, global_myname, SEC_CHAN_WKSTA, trust_passwd, last_change_time); + password_server, global_myname(), sec_channel_type,trust_passwd, last_change_time); return nt_status; } /* module initialisation */ -NTSTATUS auth_init_ntdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) +static NTSTATUS auth_init_ntdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; @@ -539,7 +497,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte * password file. */ - if(is_netbios_alias_or_name(user_info->domain.str)) { + if(is_myname(user_info->domain.str)) { DEBUG(3,("check_trustdomain_security: Requested domain was for this machine.\n")); return NT_STATUS_LOGON_FAILURE; } @@ -588,7 +546,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte } /* module initialisation */ -NTSTATUS auth_init_trustdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) +static NTSTATUS auth_init_trustdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; @@ -598,3 +556,10 @@ NTSTATUS auth_init_trustdomain(struct auth_context *auth_context, const char* pa (*auth_method)->auth = check_trustdomain_security; return NT_STATUS_OK; } + +NTSTATUS auth_domain_init(void) +{ + smb_register_auth(AUTH_INTERFACE_VERSION, "trustdomain", auth_init_trustdomain); + smb_register_auth(AUTH_INTERFACE_VERSION, "ntdomain", auth_init_ntdomain); + return NT_STATUS_OK; +}