struct dc_name_ip {
fstring name;
- struct in_addr ip;
+ struct sockaddr_storage ss;
};
extern struct winbindd_methods reconnect_methods;
-extern BOOL override_logfile;
+extern bool override_logfile;
static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
static void set_dc_type_and_flags( struct winbindd_domain *domain );
-static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
+static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
struct dc_name_ip **dcs, int *num_dcs);
/****************************************************************
parent.
****************************************************************/
-static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
+static bool fork_child_dc_connect(struct winbindd_domain *domain)
{
struct dc_name_ip *dcs = NULL;
int num_dcs = 0;
/* Leave messages blocked - we will never process one. */
- /* tdb needs special fork handling */
- if (tdb_reopen_all(1) == -1) {
- DEBUG(0,("tdb_reopen_all failed.\n"));
+ if (!reinit_after_fork(winbind_messaging_context())) {
+ DEBUG(0,("reinit_after_fork() failed\n"));
_exit(0);
}
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();
+ char *logfile;
+ if (asprintf(&logfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) > 0) {
+ lp_set_logfile(logfile);
+ SAFE_FREE(logfile);
+ reopen_logs();
+ }
}
mem_ctx = talloc_init("fork_child_dc_connect");
}
}
-static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
- fstring dcname, struct in_addr *dc_ip)
+static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
+ fstring dcname,
+ struct sockaddr_storage *dc_ss)
{
struct winbindd_domain *our_domain = NULL;
struct rpc_pipe_client *netlogon_pipe = NULL;
WERROR werr;
TALLOC_CTX *mem_ctx;
unsigned int orig_timeout;
- fstring tmp;
- char *p;
+ const char *tmp = NULL;
+ const char *p;
/* Hmmmm. We can only open one connection to the NETLOGON pipe at the
* moment.... */
/* This call can take a long time - allow the server to time out.
35 seconds should do it. */
- orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
-
- werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
- domain->name, tmp);
+ orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
+
+ if (our_domain->active_directory) {
+ struct netr_DsRGetDCNameInfo *domain_info = NULL;
+
+ result = rpccli_netr_DsRGetDCName(netlogon_pipe,
+ mem_ctx,
+ our_domain->dcname,
+ domain->name,
+ NULL,
+ NULL,
+ DS_RETURN_DNS_NAME,
+ &domain_info,
+ &werr);
+ if (W_ERROR_IS_OK(werr)) {
+ tmp = talloc_strdup(
+ mem_ctx, domain_info->dc_unc);
+ if (tmp == NULL) {
+ DEBUG(0, ("talloc_strdup failed\n"));
+ talloc_destroy(mem_ctx);
+ return false;
+ }
+ if (strlen(domain->alt_name) == 0) {
+ fstrcpy(domain->alt_name,
+ domain_info->domain_name);
+ }
+ if (strlen(domain->forest_name) == 0) {
+ fstrcpy(domain->forest_name,
+ domain_info->forest_name);
+ }
+ }
+ } else {
+ result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
+ our_domain->dcname,
+ domain->name,
+ &tmp,
+ &werr);
+ }
/* And restore our original timeout. */
- cli_set_timeout(netlogon_pipe->cli, orig_timeout);
+ rpccli_set_timeout(netlogon_pipe, orig_timeout);
- talloc_destroy(mem_ctx);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
+ nt_errstr(result)));
+ talloc_destroy(mem_ctx);
+ return false;
+ }
if (!W_ERROR_IS_OK(werr)) {
- DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
+ DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
dos_errstr(werr)));
- return False;
+ talloc_destroy(mem_ctx);
+ return false;
}
- /* cli_netlogon_getanydcname gives us a name with \\ */
+ /* rpccli_netr_GetAnyDCName gives us a name with \\ */
p = tmp;
if (*p == '\\') {
p+=1;
fstrcpy(dcname, p);
- DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
+ talloc_destroy(mem_ctx);
+
+ DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
- if (!resolve_name(dcname, dc_ip, 0x20)) {
+ if (!resolve_name(dcname, dc_ss, 0x20)) {
return False;
}
return True;
}
+/**
+ * Helper function to assemble trust password and account name
+ */
+static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
+ char **machine_password,
+ char **machine_account,
+ char **machine_krb5_principal)
+{
+ const char *account_name;
+ const char *name = NULL;
+
+ /* If we are a DC and this is not our own domain */
+
+ if (IS_DC) {
+ name = domain->name;
+ } else {
+ struct winbindd_domain *our_domain = find_our_domain();
+
+ if (!our_domain)
+ return NT_STATUS_INVALID_SERVER_STATE;
+
+ name = our_domain->name;
+ }
+
+ if (!get_trust_pw_clear(name, machine_password,
+ &account_name, NULL))
+ {
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ }
+
+ if ((machine_account != NULL) &&
+ (asprintf(machine_account, "%s$", account_name) == -1))
+ {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* this is at least correct when domain is our domain,
+ * which is the only case, when this is currently used: */
+ if (machine_krb5_principal != NULL)
+ {
+ if (asprintf(machine_krb5_principal, "%s$@%s",
+ account_name, domain->alt_name) == -1)
+ {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ strupper_m(*machine_krb5_principal);
+ }
+
+ return NT_STATUS_OK;
+}
+
/************************************************************************
Given a fd with a just-connected TCP connection to a DC, open a connection
to the pipe.
const int sockfd,
const char *controller,
struct cli_state **cli,
- BOOL *retry)
+ bool *retry)
{
- char *machine_password, *machine_krb5_principal, *machine_account;
- char *ipc_username, *ipc_domain, *ipc_password;
+ char *machine_password = NULL;
+ char *machine_krb5_principal = NULL;
+ char *machine_account = NULL;
+ char *ipc_username = NULL;
+ char *ipc_domain = NULL;
+ char *ipc_password = NULL;
- BOOL got_mutex;
+ struct named_mutex *mutex;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
controller, domain->name ));
- machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
- NULL);
-
- if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
- SAFE_FREE(machine_password);
- return NT_STATUS_NO_MEMORY;
- }
-
- if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
- lp_realm()) == -1) {
- SAFE_FREE(machine_account);
- SAFE_FREE(machine_password);
- return NT_STATUS_NO_MEMORY;
- }
-
- cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
-
*retry = True;
- got_mutex = secrets_named_mutex(controller,
- WINBIND_SERVER_MUTEX_WAIT_TIME);
-
- if (!got_mutex) {
+ mutex = grab_named_mutex(talloc_tos(), controller,
+ WINBIND_SERVER_MUTEX_WAIT_TIME);
+ if (mutex == NULL) {
DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
controller));
result = NT_STATUS_POSSIBLE_DEADLOCK;
result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
-
- if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
+
+ if (!is_trusted_domain_situation(domain->name) &&
+ (*cli)->protocol >= PROTOCOL_NT1 &&
+ (*cli)->capabilities & CAP_EXTENDED_SECURITY)
+ {
ADS_STATUS ads_status;
+ result = get_trust_creds(domain, &machine_password,
+ &machine_account,
+ &machine_krb5_principal);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto anon_fallback;
+ }
+
if (lp_security() == SEC_ADS) {
/* Try a krb5 session */
ads_status = cli_session_setup_spnego(*cli,
machine_krb5_principal,
machine_password,
- lp_workgroup());
+ domain->name);
if (!ADS_ERR_OK(ads_status)) {
DEBUG(4,("failed kerberos session setup with %s\n",
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);
+ cli_init_creds(*cli, machine_account, domain->name, machine_password);
goto session_setup_done;
}
}
DEBUG(5, ("connecting to %s from %s with username "
"[%s]\\[%s]\n", controller, global_myname(),
- lp_workgroup(), machine_account));
+ domain->name, machine_account));
ads_status = cli_session_setup_spnego(*cli,
machine_account,
machine_password,
- lp_workgroup());
+ domain->name);
if (!ADS_ERR_OK(ads_status)) {
DEBUG(4, ("authenticated session setup failed with %s\n",
ads_errstr(ads_status)));
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);
+ cli_init_creds(*cli, machine_account, domain->name, machine_password);
goto session_setup_done;
}
}
- /* Fall back to non-kerberos session setup */
+ /* Fall back to non-kerberos session setup with auth_user */
(*cli)->use_kerberos = False;
+ cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
+
if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
(strlen(ipc_username) > 0)) {
}
}
+ anon_fallback:
+
/* Fall back to anonymous connection, this might fail later */
if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
goto done;
}
- secrets_named_mutex_release(controller);
- got_mutex = False;
+ TALLOC_FREE(mutex);
*retry = False;
/* set the domain if empty; needed for schannel connections */
result = NT_STATUS_OK;
done:
- if (got_mutex) {
- secrets_named_mutex_release(controller);
- }
-
+ TALLOC_FREE(mutex);
SAFE_FREE(machine_account);
SAFE_FREE(machine_password);
SAFE_FREE(machine_krb5_principal);
return result;
}
-static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
- const char *dcname, struct in_addr ip,
+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)
{
if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
return False;
fstrcpy((*dcs)[*num].name, dcname);
- (*dcs)[*num].ip = ip;
+ (*dcs)[*num].ss = *pss;
*num += 1;
return True;
}
-static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
- struct in_addr ip, uint16 port,
- struct sockaddr_in **addrs, int *num)
+static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
+ struct sockaddr_storage *pss, uint16 port,
+ struct sockaddr_storage **addrs, int *num)
{
- *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
+ *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
if (*addrs == NULL) {
*num = 0;
return False;
}
- (*addrs)[*num].sin_family = PF_INET;
- putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
- (*addrs)[*num].sin_port = htons(port);
+ (*addrs)[*num] = *pss;
+ set_sockaddr_port(&(*addrs)[*num], port);
*num += 1;
return True;
}
-static void mailslot_name(struct in_addr dc_ip, fstring name)
-{
- fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
-}
-
-static BOOL send_getdc_request(struct in_addr dc_ip,
- const char *domain_name,
- const DOM_SID *sid)
-{
- pstring outbuf;
- char *p;
- fstring my_acct_name;
- fstring my_mailslot;
-
- mailslot_name(dc_ip, my_mailslot);
-
- memset(outbuf, '\0', sizeof(outbuf));
-
- p = outbuf;
-
- SCVAL(p, 0, SAMLOGON);
- p++;
-
- SCVAL(p, 0, 0); /* Count pointer ... */
- p++;
-
- SIVAL(p, 0, 0); /* The sender's token ... */
- p += 2;
-
- p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
- fstr_sprintf(my_acct_name, "%s$", global_myname());
- p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
-
- memcpy(p, my_mailslot, strlen(my_mailslot)+1);
- p += strlen(my_mailslot)+1;
-
- SIVAL(p, 0, 0x80);
- p+=4;
-
- SIVAL(p, 0, sid_size(sid));
- p+=4;
-
- p = ALIGN4(p, outbuf);
-
- sid_linearize(p, sid_size(sid), sid);
- p += sid_size(sid);
-
- SIVAL(p, 0, 1);
- SSVAL(p, 4, 0xffff);
- SSVAL(p, 6, 0xffff);
- p+=8;
-
- 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);
-}
-
-static BOOL receive_getdc_response(struct in_addr dc_ip,
- const char *domain_name,
- fstring dc_name)
-{
- struct packet_struct *packet;
- fstring my_mailslot;
- char *buf, *p;
- fstring dcname, user, domain;
- int len;
-
- mailslot_name(dc_ip, my_mailslot);
-
- packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
-
- if (packet == NULL) {
- DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
- return False;
- }
-
- DEBUG(5, ("Received packet for %s\n", my_mailslot));
-
- buf = packet->packet.dgram.data;
- len = packet->packet.dgram.datasize;
-
- if (len < 70) {
- /* 70 is a completely arbitrary value to make sure
- the SVAL below does not read uninitialized memory */
- DEBUG(3, ("GetDC got short response\n"));
- return False;
- }
-
- /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
- p = buf+SVAL(buf, smb_vwv10);
-
- if (CVAL(p,0) != SAMLOGON_R) {
- DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
- return False;
- }
-
- p+=2;
- pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
- STR_TERMINATE|STR_NOALIGN);
- p = skip_unibuf(p, PTR_DIFF(buf+len, p));
- pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
- STR_TERMINATE|STR_NOALIGN);
- p = skip_unibuf(p, PTR_DIFF(buf+len, p));
- pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
- STR_TERMINATE|STR_NOALIGN);
- p = skip_unibuf(p, PTR_DIFF(buf+len, p));
-
- if (!strequal(domain, domain_name)) {
- DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
- domain_name, domain));
- return False;
- }
-
- p = dcname;
- if (*p == '\\') p += 1;
- if (*p == '\\') p += 1;
-
- fstrcpy(dc_name, p);
-
- DEBUG(10, ("GetDC gave name %s for domain %s\n",
- dc_name, domain));
-
- return True;
-}
-
/*******************************************************************
convert an ip to a name
*******************************************************************/
-static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
+static bool dcip_to_name(const struct winbindd_domain *domain,
+ struct sockaddr_storage *pss,
+ fstring name )
{
struct ip_service ip_list;
- ip_list.ip = ip;
+ ip_list.ss = *pss;
ip_list.port = 0;
#ifdef WITH_ADS
if (lp_security() == SEC_ADS) {
ADS_STRUCT *ads;
+ char addr[INET6_ADDRSTRLEN];
+
+ print_sockaddr(addr, sizeof(addr), pss);
ads = ads_init(domain->alt_name, domain->name, NULL);
ads->auth.flags |= ADS_AUTH_NO_BIND;
- if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
+ if (ads_try_connect(ads, addr)) {
/* We got a cldap packet. */
fstrcpy(name, ads->config.ldap_server_name);
namecache_store(name, 0x20, 1, &ip_list);
create_local_private_krb5_conf_for_domain(domain->alt_name,
domain->name,
sitename,
- ip);
+ pss);
SAFE_FREE(sitename);
} else {
create_local_private_krb5_conf_for_domain(domain->alt_name,
domain->name,
NULL,
- ip);
+ pss);
}
winbindd_set_locator_kdc_envs(domain);
#endif
/* try GETDC requests next */
-
- if (send_getdc_request(ip, domain->name, &domain->sid)) {
+
+ if (send_getdc_request(winbind_messaging_context(),
+ pss, domain->name, &domain->sid)) {
int i;
smb_msleep(100);
for (i=0; i<5; i++) {
- if (receive_getdc_response(ip, domain->name, name)) {
+ if (receive_getdc_response(pss, domain->name, name)) {
namecache_store(name, 0x20, 1, &ip_list);
return True;
}
/* try node status request */
- if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
+ if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
namecache_store(name, 0x20, 1, &ip_list);
return True;
}
the dcs[] with results.
*******************************************************************/
-static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
+static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
struct dc_name_ip **dcs, int *num_dcs)
{
fstring dcname;
- struct in_addr ip;
+ struct sockaddr_storage ss;
struct ip_service *ip_list = NULL;
int iplist_size = 0;
int i;
- BOOL is_our_domain;
+ bool is_our_domain;
enum security_types sec = (enum security_types)lp_security();
is_our_domain = strequal(domain->name, lp_workgroup());
- if ( !is_our_domain
- && get_dc_name_via_netlogon(domain, dcname, &ip)
- && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
+ 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) )
{
+ char addr[INET6_ADDRSTRLEN];
+ print_sockaddr(addr, sizeof(addr), &ss);
DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
- dcname, inet_ntoa(ip)));
+ dcname, addr));
return True;
}
We deliberately don't care about the
return here. */
- get_dc_name(domain->name, domain->alt_name, dcname, &ip);
+ get_dc_name(domain->name, domain->alt_name, dcname, &ss);
sitename = sitename_fetch(domain->alt_name);
if (sitename) {
get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
for ( i=0; i<iplist_size; i++ ) {
- add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
- ip_list[i].ip, dcs, num_dcs);
+ 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);
get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
for ( i=0; i<iplist_size; i++ ) {
- add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
- ip_list[i].ip, dcs, num_dcs);
+ 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);
}
}
the ip now in to make the failed connection cache work */
for ( i=0; i<iplist_size; i++ ) {
- add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
- ip_list[i].ip, dcs, num_dcs);
+ 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 );
return True;
}
-static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
- const struct winbindd_domain *domain,
- fstring dcname, struct sockaddr_in *addr, int *fd)
+static bool find_new_dc(TALLOC_CTX *mem_ctx,
+ struct winbindd_domain *domain,
+ fstring dcname, struct sockaddr_storage *pss, int *fd)
{
struct dc_name_ip *dcs = NULL;
int num_dcs = 0;
const char **dcnames = NULL;
int num_dcnames = 0;
- struct sockaddr_in *addrs = NULL;
+ struct sockaddr_storage *addrs = NULL;
int num_addrs = 0;
int i, fd_index;
&dcnames, &num_dcnames)) {
return False;
}
- if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
+ if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
&addrs, &num_addrs)) {
return False;
}
&dcnames, &num_dcnames)) {
return False;
}
- if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
+ if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
&addrs, &num_addrs)) {
return False;
}
return False;
/* 5 second timeout. */
- if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
- {
+ if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
for (i=0; i<num_dcs; i++) {
+ char ab[INET6_ADDRSTRLEN];
+ print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
"domain %s address %s. Error was %s\n",
- domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
+ domain->name, ab, strerror(errno) ));
winbind_add_failed_connection_entry(domain,
dcs[i].name, NT_STATUS_UNSUCCESSFUL);
}
return False;
}
- *addr = addrs[fd_index];
+ *pss = addrs[fd_index];
if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
/* Ok, we've got a name for the DC */
}
/* Try to figure out the name */
- if (dcip_to_name( domain, addr->sin_addr, dcname )) {
+ if (dcip_to_name(domain, pss, dcname)) {
return True;
}
saf_servername, domain->name ));
/* convert an ip address to a name */
- if ( is_ipaddress( saf_servername ) ) {
+ if (is_ipaddress( saf_servername ) ) {
fstring saf_name;
- struct in_addr ip;
+ struct sockaddr_storage ss;
- ip = *interpret_addr2( saf_servername );
- if (dcip_to_name( domain, ip, saf_name )) {
+ if (!interpret_string_addr(&ss, saf_servername,
+ AI_NUMERICHOST)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ if (dcip_to_name( domain, &ss, saf_name )) {
fstrcpy( domain->dcname, saf_name );
} else {
winbind_add_failed_connection_entry(
}
for (retries = 0; retries < 3; retries++) {
-
int fd = -1;
- BOOL retry = False;
+ bool retry = False;
result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
if (*domain->dcname
&& NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
- && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
+ && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
{
- struct sockaddr_in *addrs = NULL;
+ struct sockaddr_storage *addrs = NULL;
int num_addrs = 0;
int dummy = 0;
- if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
+ if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
set_domain_offline(domain);
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
- if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
+ if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
set_domain_offline(domain);
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
if (conn->samr_pipe != NULL) {
- if (!cli_rpc_pipe_close(conn->samr_pipe)) {
- /* Ok, it must be dead. Drop timeout to 0.5 sec. */
- if (conn->cli) {
- cli_set_timeout(conn->cli, 500);
- }
+ TALLOC_FREE(conn->samr_pipe);
+ /* Ok, it must be dead. Drop timeout to 0.5 sec. */
+ if (conn->cli) {
+ cli_set_timeout(conn->cli, 500);
}
- conn->samr_pipe = NULL;
}
if (conn->lsa_pipe != NULL) {
- if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
- /* Ok, it must be dead. Drop timeout to 0.5 sec. */
- if (conn->cli) {
- cli_set_timeout(conn->cli, 500);
- }
+ TALLOC_FREE(conn->lsa_pipe);
+ /* Ok, it must be dead. Drop timeout to 0.5 sec. */
+ if (conn->cli) {
+ cli_set_timeout(conn->cli, 500);
}
- conn->lsa_pipe = NULL;
}
if (conn->netlogon_pipe != NULL) {
- if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
- /* Ok, it must be dead. Drop timeout to 0.5 sec. */
- if (conn->cli) {
- cli_set_timeout(conn->cli, 500);
- }
+ TALLOC_FREE(conn->netlogon_pipe);
+ /* Ok, it must be dead. Drop timeout to 0.5 sec. */
+ if (conn->cli) {
+ cli_set_timeout(conn->cli, 500);
}
- conn->netlogon_pipe = NULL;
}
if (conn->cli) {
}
}
-static BOOL connection_ok(struct winbindd_domain *domain)
+static bool connection_ok(struct winbindd_domain *domain)
{
if (domain->conn.cli == NULL) {
DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
Set the trust flags (direction and forest location) for a domain
******************************************************************************/
-static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *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;
+ struct netr_DomainTrustList trusts;
int i;
- uint32 flags = (DS_DOMAIN_IN_FOREST |
- DS_DOMAIN_DIRECT_OUTBOUND |
- DS_DOMAIN_DIRECT_INBOUND);
+ uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
+ NETR_TRUST_FLAG_OUTBOUND |
+ NETR_TRUST_FLAG_INBOUND);
struct rpc_pipe_client *cli;
TALLOC_CTX *mem_ctx = NULL;
return False;
}
- result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
- cli->cli->desthost,
- flags, &domains,
- (unsigned int *)&count);
+ result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
+ cli->desthost,
+ flags,
+ &trusts,
+ NULL);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0,("set_dc_type_and_flags_trustinfo: "
+ "failed to query trusted domain list: %s\n",
+ nt_errstr(result)));
+ talloc_destroy(mem_ctx);
+ return false;
+ }
/* 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 )
+ for ( i=0; i<trusts.count; i++ ) {
+ if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
+ domain->domain_flags = trusts.array[i].trust_flags;
+ domain->domain_type = trusts.array[i].trust_type;
+ domain->domain_trust_attribs = trusts.array[i].trust_attributes;
+
+ if ( domain->domain_type == NETR_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);
+ domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
"native mode.\n", domain->name,
static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
{
NTSTATUS result;
- DS_DOMINFO_CTR ctr;
+ WERROR werr;
TALLOC_CTX *mem_ctx = NULL;
struct rpc_pipe_client *cli;
POLICY_HND pol;
+ union dssetup_DsRoleInfo info;
+ union lsa_PolicyInformation *lsa_info = NULL;
- char *domain_name = NULL;
- char *dns_name = NULL;
- char *forest_name = NULL;
- DOM_SID *dom_sid = NULL;
-
- ZERO_STRUCT( ctr );
-
if (!connection_ok(domain)) {
return;
}
+ 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_connect: talloc_init() failed\n"));
+ return;
+ }
+
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,
+ cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_DSSETUP,
&result);
if (cli == NULL) {
DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
- "PI_LSARPC_DS on domain %s: (%s)\n",
+ "PI_DSSETUP on domain %s: (%s)\n",
domain->name, nt_errstr(result)));
/* 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;
+ goto no_dssetup;
}
- result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
- DsRolePrimaryDomainInfoBasic,
- &ctr);
- cli_rpc_pipe_close(cli);
+ result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
+ DS_ROLE_BASIC_INFORMATION,
+ &info,
+ &werr);
+ TALLOC_FREE(cli);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
domain->name, nt_errstr(result)));
/* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
- * every opcode on the LSARPC_DS pipe, continue with
- * no_lsarpc_ds mode here as well to get domain->initialized
+ * every opcode on the DSSETUP pipe, continue with
+ * no_dssetup mode here as well to get domain->initialized
* set - gd */
if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
- goto no_lsarpc_ds;
+ goto no_dssetup;
}
+ TALLOC_FREE(mem_ctx);
return;
}
-
- if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
- !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
+
+ if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
+ !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
domain->native_mode = True;
} else {
domain->native_mode = False;
}
-no_lsarpc_ds:
+no_dssetup:
cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
if (cli == NULL) {
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);
- return;
- }
-
- 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_connect: talloc_init() failed\n"));
- cli_rpc_pipe_close(cli);
+ TALLOC_FREE(cli);
+ TALLOC_FREE(mem_ctx);
return;
}
if (NT_STATUS_IS_OK(result)) {
/* This particular query is exactly what Win2k clients use
to determine that the DC is active directory */
- result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
- 12, &domain_name,
- &dns_name, &forest_name,
- NULL, &dom_sid);
+ result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
+ &pol,
+ LSA_POLICY_INFO_DNS,
+ &lsa_info);
}
if (NT_STATUS_IS_OK(result)) {
domain->active_directory = True;
- if (domain_name)
- fstrcpy(domain->name, domain_name);
+ if (lsa_info->dns.name.string) {
+ fstrcpy(domain->name, lsa_info->dns.name.string);
+ }
+
+ if (lsa_info->dns.dns_domain.string) {
+ fstrcpy(domain->alt_name,
+ lsa_info->dns.dns_domain.string);
+ }
+
+ /* See if we can set some domain trust flags about
+ ourself */
- if (dns_name)
- fstrcpy(domain->alt_name, dns_name);
+ if (lsa_info->dns.dns_forest.string) {
+ fstrcpy(domain->forest_name,
+ lsa_info->dns.dns_forest.string);
- if ( forest_name )
- fstrcpy(domain->forest_name, forest_name);
+ if (strequal(domain->forest_name, domain->alt_name)) {
+ domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
+ }
+ }
- if (dom_sid)
- sid_copy(&domain->sid, dom_sid);
+ if (lsa_info->dns.sid) {
+ sid_copy(&domain->sid, lsa_info->dns.sid);
+ }
} else {
domain->active_directory = False;
result = rpccli_lsa_open_policy(cli, mem_ctx, True,
SEC_RIGHTS_MAXIMUM_ALLOWED,
&pol);
-
- if (!NT_STATUS_IS_OK(result))
+
+ if (!NT_STATUS_IS_OK(result)) {
goto done;
-
- result = rpccli_lsa_query_info_policy(cli, mem_ctx,
- &pol, 5, &domain_name,
- &dom_sid);
-
+ }
+
+ result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
+ &pol,
+ LSA_POLICY_INFO_ACCOUNT_DOMAIN,
+ &lsa_info);
+
if (NT_STATUS_IS_OK(result)) {
- if (domain_name)
- fstrcpy(domain->name, domain_name);
- if (dom_sid)
- sid_copy(&domain->sid, dom_sid);
+ if (lsa_info->account_domain.name.string) {
+ fstrcpy(domain->name,
+ lsa_info->account_domain.name.string);
+ }
+
+ if (lsa_info->account_domain.sid) {
+ sid_copy(&domain->sid, lsa_info->account_domain.sid);
+ }
}
}
done:
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);
-
- talloc_destroy(mem_ctx);
+ TALLOC_FREE(cli);
+
+ TALLOC_FREE(mem_ctx);
domain->initialized = True;
}
/**********************************************************************
***********************************************************************/
-static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
+static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
struct dcinfo **ppdc)
{
NTSTATUS result;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
fstring conn_pwd;
struct dcinfo *p_dcinfo;
+ char *machine_password = NULL;
+ char *machine_account = NULL;
+ char *domain_name = NULL;
result = init_dc_connection(domain);
if (!NT_STATUS_IS_OK(result)) {
pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
if ((conn->cli->user_name[0] == '\0') ||
(conn->cli->domain[0] == '\0') ||
- (conn_pwd[0] == '\0')) {
- DEBUG(10, ("cm_connect_sam: No no user available for "
- "domain %s, trying schannel\n", conn->cli->domain));
- goto schannel;
+ (conn_pwd[0] == '\0'))
+ {
+ result = get_trust_creds(domain, &machine_password,
+ &machine_account, NULL);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("cm_connect_sam: No no user available for "
+ "domain %s, trying schannel\n", conn->cli->domain));
+ goto schannel;
+ }
+ domain_name = domain->name;
+ } else {
+ machine_password = SMB_STRDUP(conn_pwd);
+ machine_account = SMB_STRDUP(conn->cli->user_name);
+ domain_name = conn->cli->domain;
+ }
+
+ if (!machine_password || !machine_account) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
/* We have an authenticated connection. Use a NTLMSSP SPNEGO
conn->samr_pipe =
cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
PIPE_AUTH_LEVEL_PRIVACY,
- conn->cli->domain,
- conn->cli->user_name,
- conn_pwd, &result);
+ domain_name,
+ machine_account,
+ machine_password, &result);
if (conn->samr_pipe == NULL) {
DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
"pipe for domain %s using NTLMSSP "
"authenticated pipe: user %s\\%s. Error was "
- "%s\n", domain->name, conn->cli->domain,
- conn->cli->user_name, nt_errstr(result)));
+ "%s\n", domain->name, domain_name,
+ machine_account, nt_errstr(result)));
goto schannel;
}
DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
"domain %s using NTLMSSP authenticated "
"pipe: user %s\\%s\n", domain->name,
- conn->cli->domain, conn->cli->user_name ));
+ domain_name, machine_account));
- result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
- SEC_RIGHTS_MAXIMUM_ALLOWED,
- &conn->sam_connect_handle);
+ result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
+ conn->samr_pipe->desthost,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &conn->sam_connect_handle);
if (NT_STATUS_IS_OK(result)) {
goto open_domain;
}
- DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
+ DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
"failed for domain %s, error was %s. Trying schannel\n",
domain->name, nt_errstr(result) ));
- cli_rpc_pipe_close(conn->samr_pipe);
+ TALLOC_FREE(conn->samr_pipe);
schannel:
DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
"schannel.\n", domain->name ));
- result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
- SEC_RIGHTS_MAXIMUM_ALLOWED,
- &conn->sam_connect_handle);
+ result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
+ conn->samr_pipe->desthost,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &conn->sam_connect_handle);
if (NT_STATUS_IS_OK(result)) {
goto open_domain;
}
- DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
+ DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
"for domain %s, error was %s. Trying anonymous\n",
domain->name, nt_errstr(result) ));
- cli_rpc_pipe_close(conn->samr_pipe);
+ TALLOC_FREE(conn->samr_pipe);
anonymous:
goto done;
}
- result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
- SEC_RIGHTS_MAXIMUM_ALLOWED,
- &conn->sam_connect_handle);
+ result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
+ conn->samr_pipe->desthost,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &conn->sam_connect_handle);
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
+ DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
"for domain %s Error was %s\n",
domain->name, nt_errstr(result) ));
goto done;
}
open_domain:
- result = rpccli_samr_open_domain(conn->samr_pipe,
- mem_ctx,
- &conn->sam_connect_handle,
- SEC_RIGHTS_MAXIMUM_ALLOWED,
- &domain->sid,
- &conn->sam_domain_handle);
+ result = rpccli_samr_OpenDomain(conn->samr_pipe,
+ mem_ctx,
+ &conn->sam_connect_handle,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &domain->sid,
+ &conn->sam_domain_handle);
done:
*cli = conn->samr_pipe;
*sam_handle = conn->sam_domain_handle;
+ SAFE_FREE(machine_password);
+ SAFE_FREE(machine_account);
return result;
}
DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
"schannel\n"));
- cli_rpc_pipe_close(conn->lsa_pipe);
+ TALLOC_FREE(conn->lsa_pipe);
schannel:
DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
"anonymous\n"));
- cli_rpc_pipe_close(conn->lsa_pipe);
+ TALLOC_FREE(conn->lsa_pipe);
anonymous:
struct winbindd_cm_conn *conn;
NTSTATUS result;
- uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
uint8 mach_pwd[16];
uint32 sec_chan_type;
const char *account_name;
return NT_STATUS_OK;
}
- if ((IS_DC || domain->primary) && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
-
netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
&result);
if (netlogon_pipe == NULL) {
neg_flags &= ~NETLOGON_NEG_SCHANNEL;
goto no_schannel;
}
-
+
if (lp_client_schannel() != False) {
neg_flags |= NETLOGON_NEG_SCHANNEL;
}
- /* if we are a DC and this is a trusted domain, then we need to use our
- domain name in the net_req_auth2() request */
-
- if ( IS_DC
- && !strequal(domain->name, lp_workgroup())
- && lp_allow_trusted_domains() )
+ if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
+ &sec_chan_type))
{
- account_name = lp_workgroup();
- } else {
- account_name = domain->primary ?
- global_myname() : domain->name;
- }
-
- if (account_name == NULL) {
- cli_rpc_pipe_close(netlogon_pipe);
- return NT_STATUS_NO_MEMORY;
+ TALLOC_FREE(netlogon_pipe);
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
result = rpccli_netlogon_setup_creds(
&neg_flags);
if (!NT_STATUS_IS_OK(result)) {
- cli_rpc_pipe_close(netlogon_pipe);
+ TALLOC_FREE(netlogon_pipe);
return result;
}
if ((lp_client_schannel() == True) &&
((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
DEBUG(3, ("Server did not offer schannel\n"));
- cli_rpc_pipe_close(netlogon_pipe);
+ TALLOC_FREE(netlogon_pipe);
return NT_STATUS_ACCESS_DENIED;
}
no_schannel:
if ((lp_client_schannel() == False) ||
((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
-
/*
* NetSamLogonEx only works for schannel
*/
&result);
/* We can now close the initial netlogon pipe. */
- cli_rpc_pipe_close(netlogon_pipe);
+ TALLOC_FREE(netlogon_pipe);
if (conn->netlogon_pipe == NULL) {
DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
* Try NetSamLogonEx for AD domains
*/
domain->can_do_samlogon_ex = domain->active_directory;
-
+
*cli = conn->netlogon_pipe;
return NT_STATUS_OK;
}