2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 We need to manage connections to domain controllers without having to
29 mess up the main winbindd code with other issues. The aim of the
30 connection manager is to:
32 - make connections to domain controllers and cache them
33 - re-establish connections when networks or servers go down
34 - centralise the policy on connection timeouts, domain controller
36 - manage re-entrancy for when winbindd becomes able to handle
37 multiple outstanding rpc requests
39 Why not have connection management as part of the rpc layer like tng?
40 Good question. This code may morph into libsmb/rpc_cache.c or something
41 like that but at the moment it's simply staying as part of winbind. I
42 think the TNG architecture of forcing every user of the rpc layer to use
43 the connection caching system is a bad idea. It should be an optional
44 method of using the routines.
46 The TNG design is quite good but I disagree with some aspects of the
54 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
55 moved down into another function.
57 - Take care when destroying cli_structs as they can be shared between
66 #define DBGC_CLASS DBGC_WINBIND
68 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
69 static void set_dc_type_and_flags( struct winbindd_domain *domain );
71 /****************************************************************
72 If we're still offline, exponentially increase the timeout check.
73 ****************************************************************/
75 static void calc_new_online_timeout(struct winbindd_domain *domain)
77 if (domain->startup) {
78 domain->check_online_timeout = 10;
79 } else if (domain->check_online_timeout == 0) {
80 domain->check_online_timeout = lp_winbind_cache_time();
82 uint32 new_to = (domain->check_online_timeout * domain->check_online_timeout);
83 if (new_to < domain->check_online_timeout) {
86 domain->check_online_timeout = new_to;
90 /****************************************************************
91 Handler triggered if we're offline to try and detect a DC.
92 ****************************************************************/
94 static void check_domain_online_handler(struct timed_event *te,
95 const struct timeval *now,
98 struct winbindd_domain *domain =
99 (struct winbindd_domain *)private_data;
101 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
104 if (domain->check_online_event) {
105 TALLOC_FREE(domain->check_online_event);
108 /* Are we still in "startup" mode ? */
110 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
111 /* No longer in "startup" mode. */
112 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
114 domain->startup = False;
117 /* We've been told to stay offline, so stay
120 if (get_global_winbindd_state_offline()) {
121 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
126 /* This call takes care of setting the online
127 flag to true if we connected, or re-adding
128 the offline handler if false. Bypasses online
129 check so always does network calls. */
131 init_dc_connection_network(domain);
134 /****************************************************************
135 Set domain offline and also add handler to put us back online
137 ****************************************************************/
139 void set_domain_offline(struct winbindd_domain *domain)
141 DEBUG(10,("set_domain_offline: called for domain %s\n",
144 if (domain->check_online_event) {
145 TALLOC_FREE(domain->check_online_event);
148 if (domain->internal) {
149 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
154 domain->online = False;
156 /* Offline domains are always initialized. They're
157 re-initialized when they go back online. */
159 domain->initialized = True;
161 /* We only add the timeout handler that checks and
162 allows us to go back online when we've not
163 been told to remain offline. */
165 if (get_global_winbindd_state_offline()) {
166 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
171 /* If we're in statup mode, check again in 10 seconds, not in
172 lp_winbind_cache_time() seconds (which is 5 mins by default). */
174 if (domain->check_online_timeout == 0) {
175 calc_new_online_timeout(domain);
178 domain->check_online_event = add_timed_event( NULL,
179 timeval_current_ofs(domain->check_online_timeout,0),
180 "check_domain_online_handler",
181 check_domain_online_handler,
184 /* The above *has* to succeed for winbindd to work. */
185 if (!domain->check_online_event) {
186 smb_panic("set_domain_offline: failed to add online handler.\n");
189 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
193 /****************************************************************
194 Set domain online - if allowed.
195 ****************************************************************/
197 static void set_domain_online(struct winbindd_domain *domain)
199 extern struct winbindd_methods reconnect_methods;
202 DEBUG(10,("set_domain_online: called for domain %s\n",
205 if (domain->internal) {
206 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
211 if (get_global_winbindd_state_offline()) {
212 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
217 /* If we are waiting to get a krb5 ticket, trigger immediately. */
219 set_event_dispatch_time("krb5_ticket_gain_handler", now);
221 /* Ok, we're out of any startup mode now... */
222 domain->startup = False;
224 if (domain->online == False) {
225 /* We were offline - now we're online. We default to
226 using the MS-RPC backend if we started offline,
227 and if we're going online for the first time we
228 should really re-initialize the backends and the
229 checks to see if we're talking to an AD or NT domain.
232 domain->initialized = False;
234 /* 'reconnect_methods' is the MS-RPC backend. */
235 if (domain->backend == &reconnect_methods) {
236 domain->backend = NULL;
240 /* Ensure we have no online timeout checks. */
241 domain->check_online_timeout = 0;
242 if (domain->check_online_event) {
243 TALLOC_FREE(domain->check_online_event);
246 domain->online = True;
249 /****************************************************************
250 Requested to set a domain online.
251 ****************************************************************/
253 void set_domain_online_request(struct winbindd_domain *domain)
255 DEBUG(10,("set_domain_online_request: called for domain %s\n",
258 if (get_global_winbindd_state_offline()) {
259 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
264 /* We've been told it's safe to go online and
265 try and connect to a DC. But I don't believe it
266 because network manager seems to lie.
267 Wait at least 5 seconds. Heuristics suck... */
269 if (!domain->check_online_event) {
270 DEBUG(5,("set_domain_online_request: no check_domain_online_handler "
271 "registered. Were we online (%d) ?\n", (int)domain->online ));
277 /* Go into "startup" mode again. */
278 domain->startup_time = tev.tv_sec;
279 domain->startup = True;
282 set_event_dispatch_time("check_domain_online_handler", tev);
286 /****************************************************************
287 Add -ve connection cache entries for domain and realm.
288 ****************************************************************/
290 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
294 add_failed_connection_entry(domain->name, server, result);
295 /* If this was the saf name for the last thing we talked to,
297 saf_delete(domain->name);
298 if (*domain->alt_name) {
299 add_failed_connection_entry(domain->alt_name, server, result);
300 saf_delete(domain->alt_name);
304 /* Choose between anonymous or authenticated connections. We need to use
305 an authenticated connection if DCs have the RestrictAnonymous registry
306 entry set > 0, or the "Additional restrictions for anonymous
307 connections" set in the win2k Local Security Policy.
309 Caller to free() result in domain, username, password
312 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
314 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
315 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
316 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
318 if (*username && **username) {
320 if (!*domain || !**domain)
321 *domain = smb_xstrdup(lp_workgroup());
323 if (!*password || !**password)
324 *password = smb_xstrdup("");
326 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
327 *domain, *username));
330 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
331 *username = smb_xstrdup("");
332 *domain = smb_xstrdup("");
333 *password = smb_xstrdup("");
337 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
338 fstring dcname, struct in_addr *dc_ip)
340 struct winbindd_domain *our_domain = NULL;
341 struct rpc_pipe_client *netlogon_pipe = NULL;
345 unsigned int orig_timeout;
349 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
356 if (domain->primary) {
360 our_domain = find_our_domain();
362 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
366 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
367 if (!NT_STATUS_IS_OK(result)) {
371 /* This call can take a long time - allow the server to time out.
372 35 seconds should do it. */
374 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
376 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
379 /* And restore our original timeout. */
380 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
382 talloc_destroy(mem_ctx);
384 if (!W_ERROR_IS_OK(werr)) {
385 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
390 /* cli_netlogon_getdcname gives us a name with \\ */
401 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
403 if (!resolve_name(dcname, dc_ip, 0x20)) {
410 /************************************************************************
411 Given a fd with a just-connected TCP connection to a DC, open a connection
413 ************************************************************************/
415 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
417 const char *controller,
418 struct cli_state **cli,
421 char *machine_password, *machine_krb5_principal, *machine_account;
422 char *ipc_username, *ipc_domain, *ipc_password;
426 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
428 struct sockaddr peeraddr;
429 socklen_t peeraddr_len;
431 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
433 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
434 controller, domain->name ));
436 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
439 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
440 SAFE_FREE(machine_password);
441 return NT_STATUS_NO_MEMORY;
444 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
446 SAFE_FREE(machine_account);
447 SAFE_FREE(machine_password);
448 return NT_STATUS_NO_MEMORY;
451 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
455 got_mutex = secrets_named_mutex(controller,
456 WINBIND_SERVER_MUTEX_WAIT_TIME);
459 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
461 result = NT_STATUS_POSSIBLE_DEADLOCK;
465 if ((*cli = cli_initialise()) == NULL) {
466 DEBUG(1, ("Could not cli_initialize\n"));
467 result = NT_STATUS_NO_MEMORY;
471 (*cli)->timeout = 10000; /* 10 seconds */
473 fstrcpy((*cli)->desthost, controller);
474 (*cli)->use_kerberos = True;
476 peeraddr_len = sizeof(peeraddr);
478 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
479 (peeraddr_len != sizeof(struct sockaddr_in)) ||
480 (peeraddr_in->sin_family != PF_INET))
482 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
483 result = NT_STATUS_UNSUCCESSFUL;
487 if (ntohs(peeraddr_in->sin_port) == 139) {
488 struct nmb_name calling;
489 struct nmb_name called;
491 make_nmb_name(&calling, global_myname(), 0x0);
492 make_nmb_name(&called, "*SMBSERVER", 0x20);
494 if (!cli_session_request(*cli, &calling, &called)) {
495 DEBUG(8, ("cli_session_request failed for %s\n",
497 result = NT_STATUS_UNSUCCESSFUL;
502 cli_setup_signing_state(*cli, Undefined);
504 if (!cli_negprot(*cli)) {
505 DEBUG(1, ("cli_negprot failed\n"));
506 result = NT_STATUS_UNSUCCESSFUL;
510 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
511 ADS_STATUS ads_status;
513 if (lp_security() == SEC_ADS) {
515 /* Try a krb5 session */
517 (*cli)->use_kerberos = True;
518 DEBUG(5, ("connecting to %s from %s with kerberos principal "
519 "[%s]\n", controller, global_myname(),
520 machine_krb5_principal));
522 ads_status = cli_session_setup_spnego(*cli,
523 machine_krb5_principal,
527 if (!ADS_ERR_OK(ads_status)) {
528 DEBUG(4,("failed kerberos session setup with %s\n",
529 ads_errstr(ads_status)));
532 result = ads_ntstatus(ads_status);
533 if (NT_STATUS_IS_OK(result)) {
534 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
535 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
536 goto session_setup_done;
540 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
541 (*cli)->use_kerberos = False;
543 DEBUG(5, ("connecting to %s from %s with username "
544 "[%s]\\[%s]\n", controller, global_myname(),
545 lp_workgroup(), machine_account));
547 ads_status = cli_session_setup_spnego(*cli,
551 if (!ADS_ERR_OK(ads_status)) {
552 DEBUG(4, ("authenticated session setup failed with %s\n",
553 ads_errstr(ads_status)));
556 result = ads_ntstatus(ads_status);
557 if (NT_STATUS_IS_OK(result)) {
558 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
559 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
560 goto session_setup_done;
564 /* Fall back to non-kerberos session setup */
566 (*cli)->use_kerberos = False;
568 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
569 (strlen(ipc_username) > 0)) {
571 /* Only try authenticated if we have a username */
573 DEBUG(5, ("connecting to %s from %s with username "
574 "[%s]\\[%s]\n", controller, global_myname(),
575 ipc_domain, ipc_username));
577 if (NT_STATUS_IS_OK(cli_session_setup(
579 ipc_password, strlen(ipc_password)+1,
580 ipc_password, strlen(ipc_password)+1,
582 /* Successful logon with given username. */
583 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
584 goto session_setup_done;
586 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
587 ipc_domain, ipc_username ));
591 /* Fall back to anonymous connection, this might fail later */
593 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
595 DEBUG(5, ("Connected anonymously\n"));
596 cli_init_creds(*cli, "", "", "");
597 goto session_setup_done;
600 result = cli_nt_error(*cli);
602 if (NT_STATUS_IS_OK(result))
603 result = NT_STATUS_UNSUCCESSFUL;
605 /* We can't session setup */
611 /* cache the server name for later connections */
613 saf_store( domain->name, (*cli)->desthost );
614 if (domain->alt_name && (*cli)->use_kerberos) {
615 saf_store( domain->alt_name, (*cli)->desthost );
618 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
620 result = cli_nt_error(*cli);
622 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
624 if (NT_STATUS_IS_OK(result))
625 result = NT_STATUS_UNSUCCESSFUL;
630 secrets_named_mutex_release(controller);
634 /* set the domain if empty; needed for schannel connections */
635 if ( !*(*cli)->domain ) {
636 fstrcpy( (*cli)->domain, domain->name );
639 result = NT_STATUS_OK;
643 secrets_named_mutex_release(controller);
646 SAFE_FREE(machine_account);
647 SAFE_FREE(machine_password);
648 SAFE_FREE(machine_krb5_principal);
649 SAFE_FREE(ipc_username);
650 SAFE_FREE(ipc_domain);
651 SAFE_FREE(ipc_password);
653 if (!NT_STATUS_IS_OK(result)) {
654 winbind_add_failed_connection_entry(domain, controller, result);
655 if ((*cli) != NULL) {
669 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
670 const char *dcname, struct in_addr ip,
671 struct dc_name_ip **dcs, int *num)
673 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
674 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
678 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
683 fstrcpy((*dcs)[*num].name, dcname);
684 (*dcs)[*num].ip = ip;
689 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
690 struct in_addr ip, uint16 port,
691 struct sockaddr_in **addrs, int *num)
693 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
698 (*addrs)[*num].sin_family = PF_INET;
699 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
700 (*addrs)[*num].sin_port = htons(port);
706 static void mailslot_name(struct in_addr dc_ip, fstring name)
708 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
711 static BOOL send_getdc_request(struct in_addr dc_ip,
712 const char *domain_name,
717 fstring my_acct_name;
720 mailslot_name(dc_ip, my_mailslot);
722 memset(outbuf, '\0', sizeof(outbuf));
726 SCVAL(p, 0, SAMLOGON);
729 SCVAL(p, 0, 0); /* Count pointer ... */
732 SIVAL(p, 0, 0); /* The sender's token ... */
735 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
736 fstr_sprintf(my_acct_name, "%s$", global_myname());
737 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
739 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
740 p += strlen(my_mailslot)+1;
745 SIVAL(p, 0, sid_size(sid));
748 p = ALIGN4(p, outbuf);
750 sid_linearize(p, sid_size(sid), sid);
758 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
759 outbuf, PTR_DIFF(p, outbuf),
760 global_myname(), 0, domain_name, 0x1c,
764 static BOOL receive_getdc_response(struct in_addr dc_ip,
765 const char *domain_name,
768 struct packet_struct *packet;
771 fstring dcname, user, domain;
774 mailslot_name(dc_ip, my_mailslot);
776 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
778 if (packet == NULL) {
779 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
783 DEBUG(5, ("Received packet for %s\n", my_mailslot));
785 buf = packet->packet.dgram.data;
786 len = packet->packet.dgram.datasize;
789 /* 70 is a completely arbitrary value to make sure
790 the SVAL below does not read uninitialized memory */
791 DEBUG(3, ("GetDC got short response\n"));
795 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
796 p = buf+SVAL(buf, smb_vwv10);
798 if (CVAL(p,0) != SAMLOGON_R) {
799 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
804 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
805 STR_TERMINATE|STR_NOALIGN);
806 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
807 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
808 STR_TERMINATE|STR_NOALIGN);
809 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
810 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
811 STR_TERMINATE|STR_NOALIGN);
812 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
814 if (!strequal(domain, domain_name)) {
815 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
816 domain_name, domain));
821 if (*p == '\\') p += 1;
822 if (*p == '\\') p += 1;
826 DEBUG(10, ("GetDC gave name %s for domain %s\n",
832 /*******************************************************************
833 convert an ip to a name
834 *******************************************************************/
836 static BOOL dcip_to_name( const char *domainname, const char *realm,
837 const DOM_SID *sid, struct in_addr ip, fstring name )
839 struct ip_service ip_list;
845 /* For active directory servers, try to get the ldap server name.
846 None of these failures should be considered critical for now */
848 if (lp_security() == SEC_ADS) {
851 ads = ads_init(realm, domainname, NULL);
852 ads->auth.flags |= ADS_AUTH_NO_BIND;
854 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
855 /* We got a cldap packet. */
856 fstrcpy(name, ads->config.ldap_server_name);
857 namecache_store(name, 0x20, 1, &ip_list);
859 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
861 if ((ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
862 /* We're going to use this KDC for this realm/domain.
863 If we are using sites, then force the krb5 libs
866 create_local_private_krb5_conf_for_domain(realm,
870 /* Ensure we contact this DC also. */
871 saf_store( domainname, name);
872 saf_store( realm, name);
883 /* try GETDC requests next */
885 if (send_getdc_request(ip, domainname, sid)) {
888 for (i=0; i<5; i++) {
889 if (receive_getdc_response(ip, domainname, name)) {
890 namecache_store(name, 0x20, 1, &ip_list);
897 /* try node status request */
899 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
900 namecache_store(name, 0x20, 1, &ip_list);
906 /*******************************************************************
907 Retreive a list of IP address for domain controllers. Fill in
908 the dcs[] with results.
909 *******************************************************************/
911 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
912 struct dc_name_ip **dcs, int *num_dcs)
916 struct ip_service *ip_list = NULL;
920 enum security_types sec = (enum security_types)lp_security();
922 is_our_domain = strequal(domain->name, lp_workgroup());
925 && get_dc_name_via_netlogon(domain, dcname, &ip)
926 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
928 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
929 dcname, inet_ntoa(ip)));
933 if (sec == SEC_ADS) {
934 /* We need to make sure we know the local site before
935 doing any DNS queries, as this will restrict the
936 get_sorted_dc_list() call below to only fetching
937 DNS records for the correct site. */
939 /* Find any DC to get the site record.
940 We deliberately don't care about the
942 get_dc_name(domain->name, lp_realm(), dcname, &ip);
944 /* Now do the site-specific AD dns lookup. */
945 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
948 /* try standard netbios queries if no ADS */
951 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
953 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
955 /* now add to the dc array. We'll wait until the last minute
956 to look up the name of the DC. But we fill in the char* for
957 the ip now in to make the failed connection cache work */
959 for ( i=0; i<iplist_size; i++ ) {
960 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
961 ip_list[i].ip, dcs, num_dcs);
964 SAFE_FREE( ip_list );
969 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
970 const struct winbindd_domain *domain,
971 fstring dcname, struct sockaddr_in *addr, int *fd)
973 struct dc_name_ip *dcs = NULL;
976 const char **dcnames = NULL;
979 struct sockaddr_in *addrs = NULL;
985 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
988 for (i=0; i<num_dcs; i++) {
990 add_string_to_array(mem_ctx, dcs[i].name,
991 &dcnames, &num_dcnames);
992 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
995 add_string_to_array(mem_ctx, dcs[i].name,
996 &dcnames, &num_dcnames);
997 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1001 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1004 if ((addrs == NULL) || (dcnames == NULL))
1007 /* 5 second timeout. */
1008 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1010 for (i=0; i<num_dcs; i++) {
1011 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1012 "domain %s address %s. Error was %s\n",
1013 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1014 winbind_add_failed_connection_entry(domain,
1015 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1020 *addr = addrs[fd_index];
1022 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1023 /* Ok, we've got a name for the DC */
1024 fstrcpy(dcname, dcnames[fd_index]);
1028 /* Try to figure out the name */
1029 if (dcip_to_name( domain->name, domain->alt_name, &domain->sid,
1030 addr->sin_addr, dcname )) {
1034 /* We can not continue without the DC's name */
1035 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1036 NT_STATUS_UNSUCCESSFUL);
1040 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1041 struct winbindd_cm_conn *new_conn)
1043 TALLOC_CTX *mem_ctx;
1045 char *saf_servername = saf_fetch( domain->name );
1048 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1049 SAFE_FREE(saf_servername);
1050 set_domain_offline(domain);
1051 return NT_STATUS_NO_MEMORY;
1054 /* we have to check the server affinity cache here since
1055 later we selecte a DC based on response time and not preference */
1057 /* Check the negative connection cache
1058 before talking to it. It going down may have
1059 triggered the reconnection. */
1061 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1063 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1064 saf_servername, domain->name ));
1066 /* convert an ip address to a name */
1067 if ( is_ipaddress( saf_servername ) ) {
1071 ip = *interpret_addr2( saf_servername );
1072 if (dcip_to_name( domain->name, domain->alt_name,
1073 &domain->sid, ip, saf_name )) {
1074 fstrcpy( domain->dcname, saf_name );
1076 winbind_add_failed_connection_entry(
1077 domain, saf_servername,
1078 NT_STATUS_UNSUCCESSFUL);
1081 fstrcpy( domain->dcname, saf_servername );
1084 SAFE_FREE( saf_servername );
1087 for (retries = 0; retries < 3; retries++) {
1092 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1094 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1095 domain->dcname, domain->name ));
1098 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1099 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1101 struct sockaddr_in *addrs = NULL;
1105 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
1106 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
1108 /* 5 second timeout. */
1109 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1115 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1117 /* This is the one place where we will
1118 set the global winbindd offline state
1119 to true, if a "WINBINDD_OFFLINE" entry
1120 is found in the winbindd cache. */
1121 set_global_winbindd_state_offline();
1125 new_conn->cli = NULL;
1127 result = cm_prepare_connection(domain, fd, domain->dcname,
1128 &new_conn->cli, &retry);
1134 if (NT_STATUS_IS_OK(result)) {
1135 if (domain->online == False) {
1136 /* We're changing state from offline to online. */
1137 set_global_winbindd_state_online();
1139 set_domain_online(domain);
1141 /* Ensure we setup the retry handler. */
1142 set_domain_offline(domain);
1145 talloc_destroy(mem_ctx);
1149 /* Close down all open pipes on a connection. */
1151 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1153 /* We're closing down a possibly dead
1154 connection. Don't have impossibly long (10s) timeouts. */
1157 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1160 if (conn->samr_pipe != NULL) {
1161 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1162 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1164 cli_set_timeout(conn->cli, 500);
1167 conn->samr_pipe = NULL;
1170 if (conn->lsa_pipe != NULL) {
1171 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1172 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1174 cli_set_timeout(conn->cli, 500);
1177 conn->lsa_pipe = NULL;
1180 if (conn->netlogon_pipe != NULL) {
1181 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1182 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1184 cli_set_timeout(conn->cli, 500);
1187 conn->netlogon_pipe = NULL;
1191 cli_shutdown(conn->cli);
1197 void close_conns_after_fork(void)
1199 struct winbindd_domain *domain;
1201 for (domain = domain_list(); domain; domain = domain->next) {
1202 if (domain->conn.cli == NULL)
1205 if (domain->conn.cli->fd == -1)
1208 close(domain->conn.cli->fd);
1209 domain->conn.cli->fd = -1;
1213 static BOOL connection_ok(struct winbindd_domain *domain)
1215 if (domain->conn.cli == NULL) {
1216 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1217 "cli!\n", domain->dcname, domain->name));
1221 if (!domain->conn.cli->initialised) {
1222 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1223 "initialised!\n", domain->dcname, domain->name));
1227 if (domain->conn.cli->fd == -1) {
1228 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1229 "never started (fd == -1)\n",
1230 domain->dcname, domain->name));
1234 if (domain->online == False) {
1235 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1242 /* Initialize a new connection up to the RPC BIND.
1243 Bypass online status check so always does network calls. */
1245 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1249 /* Internal connections never use the network. */
1250 if (domain->internal) {
1251 domain->initialized = True;
1252 return NT_STATUS_OK;
1255 if (connection_ok(domain)) {
1256 if (!domain->initialized) {
1257 set_dc_type_and_flags(domain);
1259 return NT_STATUS_OK;
1262 invalidate_cm_connection(&domain->conn);
1264 result = cm_open_connection(domain, &domain->conn);
1266 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1267 set_dc_type_and_flags(domain);
1273 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1275 if (domain->initialized && !domain->online) {
1276 /* We check for online status elsewhere. */
1277 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1280 return init_dc_connection_network(domain);
1283 /******************************************************************************
1284 We can 'sense' certain things about the DC by it's replies to certain
1287 This tells us if this particular remote server is Active Directory, and if it
1289 ******************************************************************************/
1291 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1295 TALLOC_CTX *mem_ctx = NULL;
1296 struct rpc_pipe_client *cli;
1299 char *domain_name = NULL;
1300 char *dns_name = NULL;
1301 DOM_SID *dom_sid = NULL;
1305 if (!connection_ok(domain)) {
1309 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1311 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1315 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1316 "PI_LSARPC_DS on domain %s: (%s)\n",
1317 domain->name, nt_errstr(result)));
1321 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1322 DsRolePrimaryDomainInfoBasic,
1324 cli_rpc_pipe_close(cli);
1326 if (!NT_STATUS_IS_OK(result)) {
1327 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1328 "on domain %s failed: (%s)\n",
1329 domain->name, nt_errstr(result)));
1333 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1334 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1335 domain->native_mode = True;
1337 domain->native_mode = False;
1340 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1343 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1344 "PI_LSARPC on domain %s: (%s)\n",
1345 domain->name, nt_errstr(result)));
1346 cli_rpc_pipe_close(cli);
1350 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1353 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1354 cli_rpc_pipe_close(cli);
1358 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1359 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1361 if (NT_STATUS_IS_OK(result)) {
1362 /* This particular query is exactly what Win2k clients use
1363 to determine that the DC is active directory */
1364 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1370 if (NT_STATUS_IS_OK(result)) {
1371 domain->active_directory = True;
1374 fstrcpy(domain->name, domain_name);
1377 fstrcpy(domain->alt_name, dns_name);
1380 sid_copy(&domain->sid, dom_sid);
1382 domain->active_directory = False;
1384 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1385 SEC_RIGHTS_MAXIMUM_ALLOWED,
1388 if (!NT_STATUS_IS_OK(result))
1391 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1392 &pol, 5, &domain_name,
1395 if (NT_STATUS_IS_OK(result)) {
1397 fstrcpy(domain->name, domain_name);
1400 sid_copy(&domain->sid, dom_sid);
1405 DEBUG(5, ("set_dc_type_and_flags: domain %s is %snative mode.\n",
1406 domain->name, domain->native_mode ? "" : "NOT "));
1408 DEBUG(5,("set_dc_type_and_flags: domain %s is %sactive directory.\n",
1409 domain->name, domain->active_directory ? "" : "NOT "));
1411 cli_rpc_pipe_close(cli);
1413 talloc_destroy(mem_ctx);
1415 domain->initialized = True;
1418 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1419 struct dcinfo **ppdc)
1422 struct rpc_pipe_client *netlogon_pipe;
1424 if (lp_client_schannel() == False) {
1428 result = cm_connect_netlogon(domain, &netlogon_pipe);
1429 if (!NT_STATUS_IS_OK(result)) {
1433 /* Return a pointer to the struct dcinfo from the
1436 *ppdc = domain->conn.netlogon_pipe->dc;
1440 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1441 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1443 struct winbindd_cm_conn *conn;
1446 struct dcinfo *p_dcinfo;
1448 result = init_dc_connection(domain);
1449 if (!NT_STATUS_IS_OK(result)) {
1453 conn = &domain->conn;
1455 if (conn->samr_pipe != NULL) {
1460 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1461 * sign and sealed pipe using the machine account password by
1462 * preference. If we can't - try schannel, if that fails, try
1466 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1467 if ((conn->cli->user_name[0] == '\0') ||
1468 (conn->cli->domain[0] == '\0') ||
1469 (conn_pwd[0] == '\0')) {
1470 DEBUG(10, ("cm_connect_sam: No no user available for "
1471 "domain %s, trying schannel\n", conn->cli->domain));
1475 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1476 authenticated SAMR pipe with sign & seal. */
1478 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1479 PIPE_AUTH_LEVEL_PRIVACY,
1481 conn->cli->user_name,
1484 if (conn->samr_pipe == NULL) {
1485 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1486 "pipe for domain %s using NTLMSSP "
1487 "authenticated pipe: user %s\\%s. Error was "
1488 "%s\n", domain->name, conn->cli->domain,
1489 conn->cli->user_name, nt_errstr(result)));
1493 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1494 "domain %s using NTLMSSP authenticated "
1495 "pipe: user %s\\%s\n", domain->name,
1496 conn->cli->domain, conn->cli->user_name ));
1498 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1499 SEC_RIGHTS_MAXIMUM_ALLOWED,
1500 &conn->sam_connect_handle);
1501 if (NT_STATUS_IS_OK(result)) {
1504 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1505 "failed for domain %s, error was %s. Trying schannel\n",
1506 domain->name, nt_errstr(result) ));
1507 cli_rpc_pipe_close(conn->samr_pipe);
1511 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1513 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1514 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1515 "for domain %s, trying anon\n", conn->cli->domain));
1518 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1519 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1520 domain->name, p_dcinfo, &result);
1522 if (conn->samr_pipe == NULL) {
1523 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1524 "domain %s using schannel. Error was %s\n",
1525 domain->name, nt_errstr(result) ));
1528 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1529 "schannel.\n", domain->name ));
1531 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1532 SEC_RIGHTS_MAXIMUM_ALLOWED,
1533 &conn->sam_connect_handle);
1534 if (NT_STATUS_IS_OK(result)) {
1537 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1538 "for domain %s, error was %s. Trying anonymous\n",
1539 domain->name, nt_errstr(result) ));
1540 cli_rpc_pipe_close(conn->samr_pipe);
1544 /* Finally fall back to anonymous. */
1545 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1548 if (conn->samr_pipe == NULL) {
1549 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1553 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1554 SEC_RIGHTS_MAXIMUM_ALLOWED,
1555 &conn->sam_connect_handle);
1556 if (!NT_STATUS_IS_OK(result)) {
1557 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1558 "for domain %s Error was %s\n",
1559 domain->name, nt_errstr(result) ));
1564 result = rpccli_samr_open_domain(conn->samr_pipe,
1566 &conn->sam_connect_handle,
1567 SEC_RIGHTS_MAXIMUM_ALLOWED,
1569 &conn->sam_domain_handle);
1573 if (!NT_STATUS_IS_OK(result)) {
1574 invalidate_cm_connection(conn);
1578 *cli = conn->samr_pipe;
1579 *sam_handle = conn->sam_domain_handle;
1583 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1584 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1586 struct winbindd_cm_conn *conn;
1589 struct dcinfo *p_dcinfo;
1591 result = init_dc_connection(domain);
1592 if (!NT_STATUS_IS_OK(result))
1595 conn = &domain->conn;
1597 if (conn->lsa_pipe != NULL) {
1601 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1602 if ((conn->cli->user_name[0] == '\0') ||
1603 (conn->cli->domain[0] == '\0') ||
1604 (conn_pwd[0] == '\0')) {
1605 DEBUG(10, ("cm_connect_lsa: No no user available for "
1606 "domain %s, trying schannel\n", conn->cli->domain));
1610 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1611 * authenticated LSA pipe with sign & seal. */
1612 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1613 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1614 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1616 if (conn->lsa_pipe == NULL) {
1617 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1618 "domain %s using NTLMSSP authenticated pipe: user "
1619 "%s\\%s. Error was %s. Trying schannel.\n",
1620 domain->name, conn->cli->domain,
1621 conn->cli->user_name, nt_errstr(result)));
1625 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1626 "NTLMSSP authenticated pipe: user %s\\%s\n",
1627 domain->name, conn->cli->domain, conn->cli->user_name ));
1629 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1630 SEC_RIGHTS_MAXIMUM_ALLOWED,
1632 if (NT_STATUS_IS_OK(result)) {
1636 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1639 cli_rpc_pipe_close(conn->lsa_pipe);
1643 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1645 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1646 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1647 "for domain %s, trying anon\n", conn->cli->domain));
1650 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1651 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1652 domain->name, p_dcinfo, &result);
1654 if (conn->lsa_pipe == NULL) {
1655 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1656 "domain %s using schannel. Error was %s\n",
1657 domain->name, nt_errstr(result) ));
1660 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1661 "schannel.\n", domain->name ));
1663 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1664 SEC_RIGHTS_MAXIMUM_ALLOWED,
1666 if (NT_STATUS_IS_OK(result)) {
1670 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1673 cli_rpc_pipe_close(conn->lsa_pipe);
1677 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1679 if (conn->lsa_pipe == NULL) {
1680 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1684 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1685 SEC_RIGHTS_MAXIMUM_ALLOWED,
1688 if (!NT_STATUS_IS_OK(result)) {
1689 invalidate_cm_connection(conn);
1690 return NT_STATUS_UNSUCCESSFUL;
1693 *cli = conn->lsa_pipe;
1694 *lsa_policy = conn->lsa_policy;
1698 /****************************************************************************
1699 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1700 session key stored in conn->netlogon_pipe->dc->sess_key.
1701 ****************************************************************************/
1703 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1704 struct rpc_pipe_client **cli)
1706 struct winbindd_cm_conn *conn;
1709 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1711 uint32 sec_chan_type;
1712 const char *account_name;
1713 struct rpc_pipe_client *netlogon_pipe = NULL;
1717 result = init_dc_connection(domain);
1718 if (!NT_STATUS_IS_OK(result)) {
1722 conn = &domain->conn;
1724 if (conn->netlogon_pipe != NULL) {
1725 *cli = conn->netlogon_pipe;
1726 return NT_STATUS_OK;
1729 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1730 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1733 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1735 if (netlogon_pipe == NULL) {
1739 if (lp_client_schannel() != False) {
1740 neg_flags |= NETLOGON_NEG_SCHANNEL;
1743 /* if we are a DC and this is a trusted domain, then we need to use our
1744 domain name in the net_req_auth2() request */
1747 && !strequal(domain->name, lp_workgroup())
1748 && lp_allow_trusted_domains() )
1750 account_name = lp_workgroup();
1752 account_name = domain->primary ?
1753 global_myname() : domain->name;
1756 if (account_name == NULL) {
1757 cli_rpc_pipe_close(netlogon_pipe);
1758 return NT_STATUS_NO_MEMORY;
1761 result = rpccli_netlogon_setup_creds(
1763 domain->dcname, /* server name. */
1764 domain->name, /* domain name */
1765 global_myname(), /* client name */
1766 account_name, /* machine account */
1767 mach_pwd, /* machine password */
1768 sec_chan_type, /* from get_trust_pw */
1771 if (!NT_STATUS_IS_OK(result)) {
1772 cli_rpc_pipe_close(netlogon_pipe);
1776 if ((lp_client_schannel() == True) &&
1777 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1778 DEBUG(3, ("Server did not offer schannel\n"));
1779 cli_rpc_pipe_close(netlogon_pipe);
1780 return NT_STATUS_ACCESS_DENIED;
1783 if ((lp_client_schannel() == False) ||
1784 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1785 /* We're done - just keep the existing connection to NETLOGON
1787 conn->netlogon_pipe = netlogon_pipe;
1788 *cli = conn->netlogon_pipe;
1789 return NT_STATUS_OK;
1792 /* Using the credentials from the first pipe, open a signed and sealed
1793 second netlogon pipe. The session key is stored in the schannel
1794 part of the new pipe auth struct.
1797 conn->netlogon_pipe =
1798 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1800 PIPE_AUTH_LEVEL_PRIVACY,
1805 /* We can now close the initial netlogon pipe. */
1806 cli_rpc_pipe_close(netlogon_pipe);
1808 if (conn->netlogon_pipe == NULL) {
1809 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1810 "was %s\n", nt_errstr(result)));
1812 /* make sure we return something besides OK */
1813 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
1816 *cli = conn->netlogon_pipe;
1817 return NT_STATUS_OK;