static void cm_get_ipc_userpass(char **username, char **domain, char **password)
{
- *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
- *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
- *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
+ *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
+ *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
+ *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
if (*username && **username) {
char *ipc_username, *ipc_domain, *ipc_password;
BOOL got_mutex;
- BOOL add_failed_connection = True;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
- if ((*cli = cli_initialise(NULL)) == NULL) {
+ if ((*cli = cli_initialise()) == NULL) {
DEBUG(1, ("Could not cli_initialize\n"));
result = NT_STATUS_NO_MEMORY;
goto done;
(peeraddr_in->sin_family != PF_INET))
{
DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
+ result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
if (!cli_session_request(*cli, &calling, &called)) {
DEBUG(8, ("cli_session_request failed for %s\n",
controller));
+ result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
}
if (!cli_negprot(*cli)) {
DEBUG(1, ("cli_negprot failed\n"));
- cli_shutdown(*cli);
+ result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
-
if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
ADS_STATUS ads_status;
DEBUG(5, ("connecting to %s from %s with username "
"[%s]\\[%s]\n", controller, global_myname(),
- machine_account, machine_password));
+ lp_workgroup(), machine_account));
ads_status = cli_session_setup_spnego(*cli,
machine_account,
"[%s]\\[%s]\n", controller, global_myname(),
ipc_domain, ipc_username));
- if (cli_session_setup(*cli, ipc_username,
- ipc_password, strlen(ipc_password)+1,
- ipc_password, strlen(ipc_password)+1,
- ipc_domain)) {
+ if (NT_STATUS_IS_OK(cli_session_setup(
+ *cli, ipc_username,
+ ipc_password, strlen(ipc_password)+1,
+ ipc_password, strlen(ipc_password)+1,
+ ipc_domain))) {
/* Successful logon with given username. */
cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
goto session_setup_done;
/* Fall back to anonymous connection, this might fail later */
- if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
+ if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
+ NULL, 0, ""))) {
DEBUG(5, ("Connected anonymously\n"));
cli_init_creds(*cli, "", "", "");
goto session_setup_done;
session_setup_done:
+ /* cache the server name for later connections */
+
+ saf_store( domain->name, (*cli)->desthost );
+
if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
result = cli_nt_error(*cli);
if (NT_STATUS_IS_OK(result))
result = NT_STATUS_UNSUCCESSFUL;
- cli_shutdown(*cli);
goto done;
}
}
result = NT_STATUS_OK;
- add_failed_connection = False;
done:
if (got_mutex) {
SAFE_FREE(ipc_domain);
SAFE_FREE(ipc_password);
- if (add_failed_connection) {
+ if (!NT_STATUS_IS_OK(result)) {
add_failed_connection_entry(domain->name, controller, result);
+ if ((*cli) != NULL) {
+ cli_shutdown(*cli);
+ *cli = NULL;
+ }
}
return result;
convert an ip to a name
*******************************************************************/
-static void dcip_to_name( const char *domainname, const char *realm,
+static BOOL dcip_to_name( const char *domainname, const char *realm,
const DOM_SID *sid, struct in_addr ip, fstring name )
{
+ struct ip_service ip_list;
- /* try GETDC requests first */
-
- if (send_getdc_request(ip, domainname, sid)) {
- int i;
- smb_msleep(100);
- for (i=0; i<5; i++) {
- if (receive_getdc_response(ip, domainname, name))
- return;
- smb_msleep(500);
- }
- }
-
- /* try node status request */
-
- if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
- return;
-
- /* backup in case the netbios stuff fails */
-
- fstrcpy( name, inet_ntoa(ip) );
+ ip_list.ip = ip;
+ ip_list.port = 0;
#ifdef WITH_ADS
- /* for active directory servers, try to get the ldap server name.
- None of these failure should be considered critical for now */
+ /* For active directory servers, try to get the ldap server name.
+ None of these failures should be considered critical for now */
- if ( lp_security() == SEC_ADS )
- {
+ if ( lp_security() == SEC_ADS ) {
ADS_STRUCT *ads;
- ADS_STATUS status;
- ads = ads_init( realm, domainname, NULL );
+ 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;
- }
-
- status = ads_server_info(ads);
- if ( !ADS_ERR_OK(status) ) {
+ if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
+ const char *sitename = sitename_fetch();
+ /* We got a cldap packet. */
+ fstrcpy(name, ads->config.ldap_server_name);
+ namecache_store(name, 0x20, 1, &ip_list);
+
+#ifdef HAVE_KRB5
+ if ((ads->config.flags & ADS_KDC) && sitename) {
+ /* We're going to use this KDC for this realm/domain.
+ If we are using sites, then force the krb5 libs
+ to use this KDC. */
+
+ create_local_private_krb5_conf_for_domain(realm,
+ domainname,
+ ip);
+ }
+#endif
+ SAFE_FREE(sitename);
ads_destroy( &ads );
- return;
+ return True;
}
- fstrcpy(name, ads->config.ldap_server_name);
-
ads_destroy( &ads );
}
#endif
- return;
+ /* try GETDC requests next */
+
+ if (send_getdc_request(ip, domainname, sid)) {
+ int i;
+ smb_msleep(100);
+ for (i=0; i<5; i++) {
+ if (receive_getdc_response(ip, domainname, name)) {
+ namecache_store(name, 0x20, 1, &ip_list);
+ return True;
+ }
+ smb_msleep(500);
+ }
+ }
+
+ /* try node status request */
+
+ if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
+ namecache_store(name, 0x20, 1, &ip_list);
+ return True;
+ }
+ return False;
}
/*******************************************************************
int iplist_size = 0;
int i;
BOOL is_our_domain;
-
+ enum security_types sec = (enum security_types)lp_security();
is_our_domain = strequal(domain->name, lp_workgroup());
return True;
}
- 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;
- }
+#ifdef WITH_ADS
+ if (sec == SEC_ADS) {
+ /* We need to make sure we know the local site before
+ doing any DNS queries, as this will restrict the
+ get_sorted_dc_list() call below to only fetching
+ DNS records for the correct site. */
+
+ /* Find any DC to get the site record.
+ We deliberately don't care about the
+ return here. */
+ get_dc_name(domain->name, lp_realm(), dcname, &ip);
+ }
+#endif
/* try standard netbios queries first */
/* check for security = ads and use DNS if we can */
- if ( iplist_size==0 && lp_security() == SEC_ADS )
+ if ( iplist_size==0 && sec == SEC_ADS )
get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
/* FIXME!! this is where we should re-insert the GETDC requests --jerry */
int i, fd_index;
+ again:
if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
return False;
if ((num_dcnames == 0) || (num_dcnames != num_addrs))
return False;
+ if ((addrs == NULL) || (dcnames == NULL))
+ return False;
+
if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) )
{
for (i=0; i<num_dcs; i++) {
*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, &domain->sid, addr->sin_addr, dcname );
- else
+ if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
+ /* Ok, we've got a name for the DC */
fstrcpy(dcname, dcnames[fd_index]);
+ return True;
+ }
- return True;
+ /* Try to figure out the name */
+ if (dcip_to_name( domain->name, domain->alt_name, &domain->sid,
+ addr->sin_addr, dcname )) {
+ return True;
+ }
+
+ /* We can not continue without the DC's name */
+ add_failed_connection_entry(domain->name, dcs[fd_index].name,
+ NT_STATUS_UNSUCCESSFUL);
+ goto again;
}
static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
{
TALLOC_CTX *mem_ctx;
NTSTATUS result;
-
+ char *saf_servername = saf_fetch( domain->name );
int retries;
if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
return NT_STATUS_NO_MEMORY;
+ /* we have to check the server affinity cache here since
+ later we selecte a DC based on response time and not preference */
+
+ if ( saf_servername )
+ {
+ /* convert an ip address to a name */
+ if ( is_ipaddress( saf_servername ) )
+ {
+ fstring saf_name;
+ struct in_addr ip;
+
+ ip = *interpret_addr2( saf_servername );
+ if (dcip_to_name( domain->name, domain->alt_name,
+ &domain->sid, ip, saf_name )) {
+ fstrcpy( domain->dcname, saf_name );
+ } else {
+ add_failed_connection_entry(
+ domain->name, saf_servername,
+ NT_STATUS_UNSUCCESSFUL);
+ }
+ }
+ else
+ {
+ fstrcpy( domain->dcname, saf_servername );
+ }
+
+ SAFE_FREE( saf_servername );
+ }
+
for (retries = 0; retries < 3; retries++) {
int fd = -1;
result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
- if ((strlen(domain->dcname) > 0) &&
- NT_STATUS_IS_OK(check_negative_conn_cache(
- domain->name, domain->dcname)) &&
- (resolve_name(domain->dcname, &domain->dcaddr.sin_addr,
- 0x20))) {
- int dummy;
- struct sockaddr_in addrs[2];
- addrs[0] = domain->dcaddr;
- addrs[0].sin_port = htons(445);
- addrs[1] = domain->dcaddr;
- addrs[1].sin_port = htons(139);
- if (!open_any_socket_out(addrs, 2, 10000,
- &dummy, &fd)) {
+ if ((strlen(domain->dcname) > 0)
+ && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
+ && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
+ {
+ struct sockaddr_in *addrs = NULL;
+ int num_addrs = 0;
+ int dummy = 0;
+
+ add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
+ add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
+
+ if (!open_any_socket_out(addrs, num_addrs, 10000, &dummy, &fd)) {
+ domain->online = False;
fd = -1;
}
}
- if ((fd == -1) &&
- !find_new_dc(mem_ctx, domain, domain->dcname,
- &domain->dcaddr, &fd))
+ if ((fd == -1)
+ && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
+ {
+ /* This is the one place where we will
+ set the global winbindd offline state
+ to true, if a "WINBINDD_OFFLINE" entry
+ is found in the winbindd cache. */
+ set_global_winbindd_state_offline();
+ domain->online = False;
break;
+ }
new_conn->cli = NULL;
break;
}
+ if (NT_STATUS_IS_OK(result)) {
+ if (domain->online == False) {
+ /* We're changing state from offline to online. */
+ set_global_winbindd_state_online();
+ }
+ domain->online = True;
+ }
+
talloc_destroy(mem_ctx);
return result;
}
-/* Return true if a connection is still alive */
+/* Close down all open pipes on a connection. */
void invalidate_cm_connection(struct winbindd_cm_conn *conn)
{
/* Fall back to schannel if it's a W2K pre-SP1 box. */
if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
- DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
+ DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
"for domain %s, trying anon\n", conn->cli->domain));
goto anonymous;
}
if (conn->netlogon_pipe == NULL) {
DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
"was %s\n", nt_errstr(result)));
- return result;
+
+ /* make sure we return something besides OK */
+ return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
}
*cli = conn->netlogon_pipe;