This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Child failed to find DC's. Reschedule check.
****************************************************************/
-static void msg_failed_to_go_online(int msg_type, struct process_id src, void *buf, size_t len)
+static void msg_failed_to_go_online(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
{
struct winbindd_domain *domain;
- const char *domainname = (const char *)buf;
+ const char *domainname = (const char *)data->data;
- if (buf == NULL || len == 0) {
+ if (data->data == NULL || data->length == 0) {
return;
}
Actually cause a reconnect from a message.
****************************************************************/
-static void msg_try_to_go_online(int msg_type, struct process_id src, void *buf, size_t len)
+static void msg_try_to_go_online(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
{
struct winbindd_domain *domain;
- const char *domainname = (const char *)buf;
+ const char *domainname = (const char *)data->data;
- if (buf == NULL || len == 0) {
+ if (data->data == NULL || data->length == 0) {
return;
}
/* Stop zombies */
CatchChild();
- message_block();
-
child_pid = sys_fork();
if (child_pid == -1) {
DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
- message_unblock();
return False;
}
if (child_pid != 0) {
/* Parent */
- message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,msg_try_to_go_online);
- message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,msg_failed_to_go_online);
- message_unblock();
+ messaging_register(winbind_messaging_context(), NULL,
+ MSG_WINBIND_TRY_TO_GO_ONLINE,
+ msg_try_to_go_online);
+ messaging_register(winbind_messaging_context(), NULL,
+ MSG_WINBIND_FAILED_TO_GO_ONLINE,
+ msg_failed_to_go_online);
return True;
}
close_conns_after_fork();
if (!override_logfile) {
+ pstring logfile;
+ pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
+ lp_set_logfile(logfile);
reopen_logs();
}
if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
/* Still offline ? Can't find DC's. */
- message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
- domain->name,
- strlen(domain->name)+1, False);
+ 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);
}
/* We got a DC. Send a message to our parent to get it to
try and do the same. */
- message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
- domain->name,
- strlen(domain->name)+1, False);
+ messaging_send_buf(winbind_messaging_context(),
+ pid_to_procid(parent_pid),
+ MSG_WINBIND_TRY_TO_GO_ONLINE,
+ (uint8 *)domain->name,
+ strlen(domain->name)+1);
_exit(0);
}
struct winbindd_domain *domain =
(struct winbindd_domain *)private_data;
- DEBUG(10,("check_domain_online_handler: called for domain %s\n",
- domain->name ));
+ DEBUG(10,("check_domain_online_handler: called for domain "
+ "%s (online = %s)\n", domain->name,
+ domain->online ? "True" : "False" ));
- if (domain->check_online_event) {
- TALLOC_FREE(domain->check_online_event);
- }
+ TALLOC_FREE(domain->check_online_event);
/* Are we still in "startup" mode ? */
DEBUG(10,("set_domain_offline: called for domain %s\n",
domain->name ));
- if (domain->check_online_event) {
- TALLOC_FREE(domain->check_online_event);
- }
+ TALLOC_FREE(domain->check_online_event);
if (domain->internal) {
DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
calc_new_online_timeout_check(domain);
- domain->check_online_event = event_add_timed(winbind_event_context(), NULL,
+ 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,
/* The above *has* to succeed for winbindd to work. */
if (!domain->check_online_event) {
- smb_panic("set_domain_offline: failed to add online handler.\n");
+ smb_panic("set_domain_offline: failed to add online handler");
}
DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
domain->name ));
+
+ /* Send an offline message to the idmap child when our
+ primary domain goes offline */
+
+ if ( domain->primary ) {
+ struct winbindd_child *idmap = idmap_child();
+
+ if ( idmap->pid != 0 ) {
+ messaging_send_buf(winbind_messaging_context(),
+ pid_to_procid(idmap->pid),
+ MSG_WINBIND_OFFLINE,
+ (uint8 *)domain->name,
+ strlen(domain->name)+1);
+ }
+ }
+
+ return;
}
/****************************************************************
domain->name ));
if (domain->internal) {
- DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
+ DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
domain->name ));
return;
}
/* Ensure we have no online timeout checks. */
domain->check_online_timeout = 0;
- if (domain->check_online_event) {
- TALLOC_FREE(domain->check_online_event);
- }
+ TALLOC_FREE(domain->check_online_event);
/* Ensure we ignore any pending child messages. */
- message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
- message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
+ messaging_deregister(winbind_messaging_context(),
+ MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
+ messaging_deregister(winbind_messaging_context(),
+ MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
domain->online = True;
+
+ /* Send an online message to the idmap child when our
+ primary domain comes online */
+
+ if ( domain->primary ) {
+ struct winbindd_child *idmap = idmap_child();
+
+ if ( idmap->pid != 0 ) {
+ messaging_send_buf(winbind_messaging_context(),
+ pid_to_procid(idmap->pid),
+ MSG_WINBIND_ONLINE,
+ (uint8 *)domain->name,
+ strlen(domain->name)+1);
+ }
+ }
+
+ return;
}
/****************************************************************
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);
- TALLOC_FREE(domain->check_online_event);
+ /* 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);
tev.tv_sec += 5;
- domain->check_online_event = event_add_timed(
- winbind_event_context(), NULL, tev,
- "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.\n");
- }
+ set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
}
/****************************************************************
orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
- werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
- domain->name, tmp);
+ werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
+ domain->name, tmp);
/* And restore our original timeout. */
cli_set_timeout(netlogon_pipe->cli, orig_timeout);
talloc_destroy(mem_ctx);
if (!W_ERROR_IS_OK(werr)) {
- DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
+ DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
dos_errstr(werr)));
return False;
}
- /* cli_netlogon_getdcname gives us a name with \\ */
+ /* cli_netlogon_getanydcname gives us a name with \\ */
p = tmp;
if (*p == '\\') {
p+=1;
fstrcpy(dcname, p);
- DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
+ DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
if (!resolve_name(dcname, dc_ip, 0x20)) {
return False;
SSVAL(p, 6, 0xffff);
p+=8;
- return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
+ return cli_send_mailslot(winbind_messaging_context(),
+ False, "\\MAILSLOT\\NET\\NTLOGON", 0,
outbuf, PTR_DIFF(p, outbuf),
global_myname(), 0, domain_name, 0x1c,
dc_ip);
DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
- char *sitename = sitename_fetch();
+ char *sitename = sitename_fetch(ads->config.realm);
/* We're going to use this KDC for this realm/domain.
If we are using sites, then force the krb5 libs
We deliberately don't care about the
return here. */
- get_dc_name(domain->name, lp_realm(), dcname, &ip);
+ get_dc_name(domain->name, domain->alt_name, dcname, &ip);
- sitename = sitename_fetch();
+ sitename = sitename_fetch(domain->alt_name);
if (sitename) {
/* Do the site-specific AD dns lookup first. */
return init_dc_connection_network(domain);
}
+/******************************************************************************
+ Set the trust flags (direction and forest location) for a domain
+******************************************************************************/
+
+static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
+{
+ struct winbindd_domain *our_domain;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct ds_domain_trust *domains = NULL;
+ int count = 0;
+ int i;
+ uint32 flags = (DS_DOMAIN_IN_FOREST |
+ DS_DOMAIN_DIRECT_OUTBOUND |
+ DS_DOMAIN_DIRECT_INBOUND);
+ struct rpc_pipe_client *cli;
+ TALLOC_CTX *mem_ctx = NULL;
+
+ DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
+
+ /* Our primary domain doesn't need to worry about trust flags.
+ Force it to go through the network setup */
+ if ( domain->primary ) {
+ return False;
+ }
+
+ our_domain = find_our_domain();
+
+ if ( !connection_ok(our_domain) ) {
+ DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
+ return False;
+ }
+
+ /* This won't work unless our domain is AD */
+
+ if ( !our_domain->active_directory ) {
+ return False;
+ }
+
+ /* Use DsEnumerateDomainTrusts to get us the trust direction
+ and type */
+
+ result = cm_connect_netlogon(our_domain, &cli);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
+ "a connection to %s for PIPE_NETLOGON (%s)\n",
+ domain->name, nt_errstr(result)));
+ return False;
+ }
+
+ if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
+ DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
+ return False;
+ }
+
+ result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
+ cli->cli->desthost,
+ flags, &domains,
+ (unsigned int *)&count);
+
+ /* Now find the domain name and get the flags */
+
+ for ( i=0; i<count; i++ ) {
+ if ( strequal( domain->name, domains[i].netbios_domain ) ) {
+ domain->domain_flags = domains[i].flags;
+ domain->domain_type = domains[i].trust_type;
+ domain->domain_trust_attribs = domains[i].trust_attributes;
+
+ if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
+ domain->active_directory = True;
+
+ /* This flag is only set if the domain is *our*
+ primary domain and the primary domain is in
+ native mode */
+
+ domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
+
+ DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
+ "native mode.\n", domain->name,
+ domain->native_mode ? "" : "NOT "));
+
+ DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
+ "running active directory.\n", domain->name,
+ domain->active_directory ? "" : "NOT "));
+
+
+ domain->initialized = True;
+
+ if ( !winbindd_can_contact_domain( domain) )
+ domain->internal = True;
+
+ break;
+ }
+ }
+
+ talloc_destroy( mem_ctx );
+
+ return domain->initialized;
+}
+
/******************************************************************************
We can 'sense' certain things about the DC by it's replies to certain
questions.
is native mode.
******************************************************************************/
-static void set_dc_type_and_flags( struct winbindd_domain *domain )
+static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
{
NTSTATUS result;
DS_DOMINFO_CTR ctr;
return;
}
- DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
+ DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
&result);
if (cli == NULL) {
- DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
+ DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
"PI_LSARPC_DS on domain %s: (%s)\n",
domain->name, nt_errstr(result)));
- return;
+
+ /* if this is just a non-AD domain we need to continue
+ * identifying so that we can in the end return with
+ * domain->initialized = True - gd */
+
+ goto no_lsarpc_ds;
}
result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
cli_rpc_pipe_close(cli);
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
+ DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
"on domain %s failed: (%s)\n",
domain->name, nt_errstr(result)));
return;
domain->native_mode = False;
}
+no_lsarpc_ds:
cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
if (cli == NULL) {
- DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
+ DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
"PI_LSARPC on domain %s: (%s)\n",
domain->name, nt_errstr(result)));
cli_rpc_pipe_close(cli);
mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
domain->name);
if (!mem_ctx) {
- DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
+ DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
cli_rpc_pipe_close(cli);
return;
}
}
done:
- DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
+ DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
domain->name, domain->native_mode ? "" : "NOT "));
- DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
+ DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
domain->name, domain->active_directory ? "" : "NOT "));
cli_rpc_pipe_close(cli);
domain->initialized = True;
}
+/**********************************************************************
+ Set the domain_flags (trust attributes, domain operating modes, etc...
+***********************************************************************/
+
+static void set_dc_type_and_flags( struct winbindd_domain *domain )
+{
+ /* we always have to contact our primary domain */
+
+ if ( domain->primary ) {
+ DEBUG(10,("set_dc_type_and_flags: setting up flags for "
+ "primary domain\n"));
+ set_dc_type_and_flags_connect( domain );
+ return;
+ }
+
+ /* Use our DC to get the information if possible */
+
+ if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
+ /* Otherwise, fallback to contacting the
+ domain directly */
+ set_dc_type_and_flags_connect( domain );
+ }
+
+ return;
+}
+
+
+
+/**********************************************************************
+***********************************************************************/
+
static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
struct dcinfo **ppdc)
{
return NT_STATUS_OK;
}
- if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
+ if (domain->primary && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
return result;
}
+ if ( !domain->primary ) {
+ /* Clear the schannel request bit and drop down */
+ neg_flags &= ~NETLOGON_NEG_SCHANNEL;
+ goto no_schannel;
+ }
+
if (lp_client_schannel() != False) {
neg_flags |= NETLOGON_NEG_SCHANNEL;
}
return NT_STATUS_ACCESS_DENIED;
}
+ no_schannel:
if ((lp_client_schannel() == False) ||
((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
+
+ /*
+ * NetSamLogonEx only works for schannel
+ */
+ domain->can_do_samlogon_ex = False;
+
/* We're done - just keep the existing connection to NETLOGON
* open */
conn->netlogon_pipe = netlogon_pipe;
return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
}
+ /*
+ * Try NetSamLogonEx for AD domains
+ */
+ domain->can_do_samlogon_ex = domain->active_directory;
+
*cli = conn->netlogon_pipe;
return NT_STATUS_OK;
}