int num_dcs = 0;
TALLOC_CTX *mem_ctx = NULL;
pid_t parent_pid = sys_getpid();
+ char *lfile = NULL;
/* Stop zombies */
CatchChild();
/* Leave messages blocked - we will never process one. */
- if (!reinit_after_fork(winbind_messaging_context(), true)) {
- DEBUG(0,("reinit_after_fork() failed\n"));
+ if (!override_logfile) {
+ if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
+ DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
+ _exit(1);
+ }
+ }
+
+ if (!winbindd_reinit_after_fork(lfile)) {
messaging_send_buf(winbind_messaging_context(),
pid_to_procid(parent_pid),
MSG_WINBIND_FAILED_TO_GO_ONLINE,
(uint8 *)domain->name,
strlen(domain->name)+1);
- _exit(0);
- }
-
- close_conns_after_fork();
-
- if (!override_logfile) {
- char *logfile;
- if (asprintf(&logfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) > 0) {
- lp_set_logfile(logfile);
- SAFE_FREE(logfile);
- reopen_logs();
- }
+ _exit(1);
}
+ SAFE_FREE(lfile);
mem_ctx = talloc_init("fork_child_dc_connect");
if (!mem_ctx) {
MSG_WINBIND_FAILED_TO_GO_ONLINE,
(uint8 *)domain->name,
strlen(domain->name)+1);
- _exit(0);
+ _exit(1);
}
if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
static void check_domain_online_handler(struct event_context *ctx,
struct timed_event *te,
- const struct timeval *now,
+ struct timeval now,
void *private_data)
{
struct winbindd_domain *domain =
/* Are we still in "startup" mode ? */
- if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
+ if (domain->startup && (now.tv_sec > domain->startup_time + 30)) {
/* No longer in "startup" mode. */
DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
domain->name ));
domain->check_online_event = event_add_timed(winbind_event_context(),
NULL,
timeval_current_ofs(domain->check_online_timeout,0),
- "check_domain_online_handler",
check_domain_online_handler,
domain);
static void set_domain_online(struct winbindd_domain *domain)
{
- struct timeval now;
-
DEBUG(10,("set_domain_online: called for domain %s\n",
domain->name ));
winbindd_set_locator_kdc_envs(domain);
/* If we are waiting to get a krb5 ticket, trigger immediately. */
- GetTimeOfDay(&now);
- set_event_dispatch_time(winbind_event_context(),
- "krb5_ticket_gain_handler", now);
+ ccache_regain_all_now();
/* Ok, we're out of any startup mode now... */
domain->startup = False;
because network manager seems to lie.
Wait at least 5 seconds. Heuristics suck... */
+
+ GetTimeOfDay(&tev);
+
+ /* Go into "startup" mode again. */
+ domain->startup_time = tev.tv_sec;
+ domain->startup = True;
+
+ tev.tv_sec += 5;
+
if (!domain->check_online_event) {
/* If we've come from being globally offline we
don't have a check online event handler set.
DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
domain->name ));
-
- domain->check_online_event = event_add_timed(winbind_event_context(),
- NULL,
- timeval_current_ofs(5, 0),
- "check_domain_online_handler",
- check_domain_online_handler,
- domain);
-
- /* The above *has* to succeed for winbindd to work. */
- if (!domain->check_online_event) {
- smb_panic("set_domain_online_request: failed to add online handler");
- }
}
- GetTimeOfDay(&tev);
-
- /* Go into "startup" mode again. */
- domain->startup_time = tev.tv_sec;
- domain->startup = True;
+ TALLOC_FREE(domain->check_online_event);
- tev.tv_sec += 5;
+ domain->check_online_event = event_add_timed(winbind_event_context(),
+ NULL,
+ tev,
+ check_domain_online_handler,
+ domain);
- set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
+ /* The above *has* to succeed for winbindd to work. */
+ if (!domain->check_online_event) {
+ smb_panic("set_domain_online_request: failed to add online handler");
+ }
}
/****************************************************************
DS_RETURN_DNS_NAME,
&domain_info,
&werr);
- if (W_ERROR_IS_OK(werr)) {
+ if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
tmp = talloc_strdup(
mem_ctx, domain_info->dc_unc);
if (tmp == NULL) {
if (!W_ERROR_IS_OK(werr)) {
DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
- dos_errstr(werr)));
+ win_errstr(werr)));
talloc_destroy(mem_ctx);
return false;
}
}
}
- cli_setup_signing_state(*cli, Undefined);
+ result = cli_negprot(*cli);
- if (!cli_negprot(*cli)) {
- DEBUG(1, ("cli_negprot failed\n"));
- result = NT_STATUS_UNSUCCESSFUL;
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
goto done;
}
result = ads_ntstatus(ads_status);
if (NT_STATUS_IS_OK(result)) {
/* Ensure creds are stored for NTLMSSP authenticated pipe access. */
- cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
+ result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
goto session_setup_done;
}
}
result = ads_ntstatus(ads_status);
if (NT_STATUS_IS_OK(result)) {
/* Ensure creds are stored for NTLMSSP authenticated pipe access. */
- cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
+ result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
goto session_setup_done;
}
}
ipc_password, strlen(ipc_password)+1,
ipc_domain))) {
/* Successful logon with given username. */
- cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
+ result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
goto session_setup_done;
} else {
DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
NULL, 0, ""))) {
DEBUG(5, ("Connected anonymously\n"));
- cli_init_creds(*cli, "", "", "");
+ result = cli_init_creds(*cli, "", "", "");
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
goto session_setup_done;
}
winbindd_set_locator_kdc_envs(domain);
- if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
-
- result = cli_nt_error(*cli);
+ result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
+ if (!NT_STATUS_IS_OK(result)) {
DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
-
- if (NT_STATUS_IS_OK(result))
- result = NT_STATUS_UNSUCCESSFUL;
-
goto done;
}
*retry = False;
/* set the domain if empty; needed for schannel connections */
- if ( !*(*cli)->domain ) {
- fstrcpy( (*cli)->domain, domain->name );
+ if ( !(*cli)->domain[0] ) {
+ result = cli_set_domain((*cli), domain->name);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
}
result = NT_STATUS_OK;
return result;
}
+/*******************************************************************
+ Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
+ array.
+
+ Keeps the list unique by not adding duplicate entries.
+
+ @param[in] mem_ctx talloc memory context to allocate from
+ @param[in] domain_name domain of the DC
+ @param[in] dcname name of the DC to add to the list
+ @param[in] pss Internet address and port pair to add to the list
+ @param[in,out] dcs array of dc_name_ip structures to add to
+ @param[in,out] num_dcs number of dcs returned in the dcs array
+ @return true if the list was added to, false otherwise
+*******************************************************************/
+
static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
const char *dcname, struct sockaddr_storage *pss,
struct dc_name_ip **dcs, int *num)
{
+ int i = 0;
+
if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
return False;
}
+ /* Make sure there's no duplicates in the list */
+ for (i=0; i<*num; i++)
+ if (sockaddr_equal((struct sockaddr *)&(*dcs)[i].ss, (struct sockaddr *)pss))
+ return False;
+
*dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
if (*dcs == NULL)
}
(*addrs)[*num] = *pss;
- set_sockaddr_port(&(*addrs)[*num], port);
+ set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
*num += 1;
return True;
fstring name )
{
struct ip_service ip_list;
- uint32_t nt_version = NETLOGON_VERSION_1;
+ uint32_t nt_version = NETLOGON_NT_VERSION_1;
ip_list.ss = *pss;
ip_list.port = 0;
}
/*******************************************************************
- Retreive a list of IP address for domain controllers. Fill in
- the dcs[] with results.
+ Retrieve a list of IP addresses for domain controllers.
+
+ The array is sorted in the preferred connection order.
+
+ @param[in] mem_ctx talloc memory context to allocate from
+ @param[in] domain domain to retrieve DCs for
+ @param[out] dcs array of dcs that will be returned
+ @param[out] num_dcs number of dcs returned in the dcs array
+ @return always true
*******************************************************************/
static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
is_our_domain = strequal(domain->name, lp_workgroup());
+ /* If not our domain, get the preferred DC, by asking our primary DC */
if ( !is_our_domain
&& get_dc_name_via_netlogon(domain, dcname, &ss)
- && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs, num_dcs) )
+ && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
+ num_dcs) )
{
char addr[INET6_ADDRSTRLEN];
print_sockaddr(addr, sizeof(addr), &ss);
if (sitename) {
/* Do the site-specific AD dns lookup first. */
- get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
+ get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
+ &iplist_size, True);
+ /* Add ips to the DC array. We don't look up the name
+ of the DC in this function, but we fill in the char*
+ of the ip now to make the failed connection cache
+ work */
for ( i=0; i<iplist_size; i++ ) {
char addr[INET6_ADDRSTRLEN];
print_sockaddr(addr, sizeof(addr),
iplist_size = 0;
}
- /* Now we add DCs from the main AD dns lookup. */
- get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
+ /* Now we add DCs from the main AD DNS lookup. */
+ get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
+ &iplist_size, True);
for ( i=0; i<iplist_size; i++ ) {
char addr[INET6_ADDRSTRLEN];
dcs,
num_dcs);
}
- }
- /* try standard netbios queries if no ADS */
-
- if (iplist_size==0) {
- get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
- }
+ SAFE_FREE(ip_list);
+ iplist_size = 0;
+ }
- /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
+ /* Try standard netbios queries if no ADS */
+ if (*num_dcs == 0) {
+ get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
+ False);
- /* 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 */
+ for ( i=0; i<iplist_size; i++ ) {
+ char addr[INET6_ADDRSTRLEN];
+ print_sockaddr(addr, sizeof(addr),
+ &ip_list[i].ss);
+ add_one_dc_unique(mem_ctx,
+ domain->name,
+ addr,
+ &ip_list[i].ss,
+ dcs,
+ num_dcs);
+ }
- for ( i=0; i<iplist_size; i++ ) {
- char addr[INET6_ADDRSTRLEN];
- print_sockaddr(addr, sizeof(addr),
- &ip_list[i].ss);
- add_one_dc_unique(mem_ctx, domain->name, addr,
- &ip_list[i].ss, dcs, num_dcs);
+ SAFE_FREE(ip_list);
+ iplist_size = 0;
}
- SAFE_FREE( ip_list );
-
return True;
}
+/*******************************************************************
+ Find and make a connection to a DC in the given domain.
+
+ @param[in] mem_ctx talloc memory context to allocate from
+ @param[in] domain domain to find a dc in
+ @param[out] dcname NetBIOS or FQDN of DC that's connected to
+ @param[out] pss DC Internet address and port
+ @param[out] fd fd of the open socket connected to the newly found dc
+ @return true when a DC connection is made, false otherwise
+*******************************************************************/
+
static bool find_new_dc(TALLOC_CTX *mem_ctx,
struct winbindd_domain *domain,
fstring dcname, struct sockaddr_storage *pss, int *fd)
NTSTATUS result;
WERROR werr;
TALLOC_CTX *mem_ctx = NULL;
- struct rpc_pipe_client *cli;
- POLICY_HND pol;
+ struct rpc_pipe_client *cli = NULL;
+ struct policy_handle pol;
union dssetup_DsRoleInfo info;
union lsa_PolicyInformation *lsa_info = NULL;
}
NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
- struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
+ struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
{
struct winbindd_cm_conn *conn;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- fstring conn_pwd;
struct dcinfo *p_dcinfo;
char *machine_password = NULL;
char *machine_account = NULL;
* anonymous.
*/
- pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
if ((conn->cli->user_name[0] == '\0') ||
(conn->cli->domain[0] == '\0') ||
- (conn_pwd[0] == '\0'))
+ (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
{
result = get_trust_creds(domain, &machine_password,
&machine_account, NULL);
}
domain_name = domain->name;
} else {
- machine_password = SMB_STRDUP(conn_pwd);
+ machine_password = SMB_STRDUP(conn->cli->password);
machine_account = SMB_STRDUP(conn->cli->user_name);
domain_name = conn->cli->domain;
}
}
NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
- struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
+ struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
{
struct winbindd_cm_conn *conn;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- fstring conn_pwd;
struct dcinfo *p_dcinfo;
result = init_dc_connection(domain);
goto done;
}
- pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
if ((conn->cli->user_name[0] == '\0') ||
(conn->cli->domain[0] == '\0') ||
- (conn_pwd[0] == '\0')) {
+ (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
DEBUG(10, ("cm_connect_lsa: No no user available for "
"domain %s, trying schannel\n", conn->cli->domain));
goto schannel;
result = cli_rpc_pipe_open_spnego_ntlmssp
(conn->cli, &ndr_table_lsarpc.syntax_id,
PIPE_AUTH_LEVEL_PRIVACY,
- conn->cli->domain, conn->cli->user_name, conn_pwd,
+ conn->cli->domain, conn->cli->user_name, conn->cli->password,
&conn->lsa_pipe);
if (!NT_STATUS_IS_OK(result)) {