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
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
65 #define DBGC_CLASS DBGC_WINBIND
67 static void set_dc_type_and_flags( struct winbindd_domain *domain );
69 /****************************************************************
70 Handler triggered if we're offline to try and detect a DC.
71 ****************************************************************/
73 static void check_domain_online_handler(struct timed_event *te,
74 const struct timeval *now,
77 struct winbindd_domain *domain =
78 (struct winbindd_domain *)private_data;
80 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
83 if (domain->check_online_event) {
84 TALLOC_FREE(domain->check_online_event);
87 /* Are we still in "startup" mode ? */
89 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
90 /* No longer in "startup" mode. */
91 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
93 domain->startup = False;
96 /* We've been told to stay offline, so stay
99 if (get_global_winbindd_state_offline()) {
100 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
105 /* This call takes care of setting the online
106 flag to true if we connected, or re-adding
107 the offline handler if false. */
108 init_dc_connection(domain);
111 /****************************************************************
112 Set domain offline and also add handler to put us back online
114 ****************************************************************/
116 void set_domain_offline(struct winbindd_domain *domain)
118 DEBUG(10,("set_domain_offline: called for domain %s\n",
121 if (domain->check_online_event) {
122 TALLOC_FREE(domain->check_online_event);
125 if (domain->internal) {
126 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
131 domain->online = False;
133 /* We only add the timeout handler that checks and
134 allows us to go back online when we've not
135 been told to remain offline. */
137 if (get_global_winbindd_state_offline()) {
138 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
143 /* If we're in statup mode, check again in 10 seconds, not in
144 lp_winbind_cache_time() seconds (which is 5 mins by default). */
146 domain->check_online_event = add_timed_event( NULL,
148 timeval_current_ofs(10,0) :
149 timeval_current_ofs(lp_winbind_cache_time(), 0),
150 "check_domain_online_handler",
151 check_domain_online_handler,
154 /* The above *has* to succeed for winbindd to work. */
155 if (!domain->check_online_event) {
156 smb_panic("set_domain_offline: failed to add online handler.\n");
159 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
163 /****************************************************************
164 Set domain online - if allowed.
165 ****************************************************************/
167 static void set_domain_online(struct winbindd_domain *domain)
169 extern struct winbindd_methods reconnect_methods;
172 DEBUG(10,("set_domain_online: called for domain %s\n",
175 if (domain->internal) {
176 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
181 if (get_global_winbindd_state_offline()) {
182 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
187 /* If we are waiting to get a krb5 ticket, trigger immediately. */
189 set_event_dispatch_time("krb5_ticket_gain_handler", now);
191 /* Ok, we're out of any startup mode now... */
192 domain->startup = False;
194 if (domain->online == False) {
195 /* We were offline - now we're online. We default to
196 using the MS-RPC backend if we started offline,
197 and if we're going online for the first time we
198 should really re-initialize the backends and the
199 checks to see if we're talking to an AD or NT domain.
202 domain->initialized = False;
204 /* 'reconnect_methods' is the MS-RPC backend. */
205 if (domain->backend == &reconnect_methods) {
206 domain->backend = NULL;
210 domain->online = True;
213 /****************************************************************
214 Requested to set a domain online.
215 ****************************************************************/
217 void set_domain_online_request(struct winbindd_domain *domain)
219 DEBUG(10,("set_domain_online_request: called for domain %s\n",
222 if (get_global_winbindd_state_offline()) {
223 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
228 /* We've been told it's safe to go online and
229 try and connect to a DC. But I don't believe it
230 because network manager seems to lie.
231 Wait at least 5 seconds. Heuristics suck... */
233 if (!domain->check_online_event) {
234 DEBUG(5,("set_domain_online_request: no check_domain_online_handler "
235 "registered. Were we online (%d) ?\n", (int)domain->online ));
241 /* Go into "startup" mode again. */
242 domain->startup_time = tev.tv_sec;
243 domain->startup = True;
246 set_event_dispatch_time("check_domain_online_handler", tev);
250 /****************************************************************
251 Add -ve connection cache entries for domain and realm.
252 ****************************************************************/
254 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
258 add_failed_connection_entry(domain->name, server, result);
259 /* If this was the saf name for the last thing we talked to,
261 saf_delete(domain->name, server);
262 if (*domain->alt_name) {
263 add_failed_connection_entry(domain->alt_name, server, result);
264 saf_delete(domain->alt_name, server);
268 /* Choose between anonymous or authenticated connections. We need to use
269 an authenticated connection if DCs have the RestrictAnonymous registry
270 entry set > 0, or the "Additional restrictions for anonymous
271 connections" set in the win2k Local Security Policy.
273 Caller to free() result in domain, username, password
276 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
278 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
279 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
280 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
282 if (*username && **username) {
284 if (!*domain || !**domain)
285 *domain = smb_xstrdup(lp_workgroup());
287 if (!*password || !**password)
288 *password = smb_xstrdup("");
290 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
291 *domain, *username));
294 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
295 *username = smb_xstrdup("");
296 *domain = smb_xstrdup("");
297 *password = smb_xstrdup("");
301 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
302 fstring dcname, struct in_addr *dc_ip)
304 struct winbindd_domain *our_domain = NULL;
305 struct rpc_pipe_client *netlogon_pipe = NULL;
309 unsigned int orig_timeout;
313 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
320 if (domain->primary) {
324 our_domain = find_our_domain();
326 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
330 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
331 if (!NT_STATUS_IS_OK(result)) {
335 /* This call can take a long time - allow the server to time out.
336 35 seconds should do it. */
338 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
340 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
343 /* And restore our original timeout. */
344 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
346 talloc_destroy(mem_ctx);
348 if (!W_ERROR_IS_OK(werr)) {
349 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
354 /* cli_netlogon_getdcname gives us a name with \\ */
365 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
367 if (!resolve_name(dcname, dc_ip, 0x20)) {
374 /************************************************************************
375 Given a fd with a just-connected TCP connection to a DC, open a connection
377 ************************************************************************/
379 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
381 const char *controller,
382 struct cli_state **cli,
385 char *machine_password, *machine_krb5_principal, *machine_account;
386 char *ipc_username, *ipc_domain, *ipc_password;
390 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
392 struct sockaddr peeraddr;
393 socklen_t peeraddr_len;
395 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
397 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
398 controller, domain->name ));
400 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
403 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
404 SAFE_FREE(machine_password);
405 return NT_STATUS_NO_MEMORY;
408 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
410 SAFE_FREE(machine_account);
411 SAFE_FREE(machine_password);
412 return NT_STATUS_NO_MEMORY;
415 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
419 got_mutex = secrets_named_mutex(controller,
420 WINBIND_SERVER_MUTEX_WAIT_TIME);
423 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
425 result = NT_STATUS_POSSIBLE_DEADLOCK;
429 if ((*cli = cli_initialise()) == NULL) {
430 DEBUG(1, ("Could not cli_initialize\n"));
431 result = NT_STATUS_NO_MEMORY;
435 (*cli)->timeout = 10000; /* 10 seconds */
437 fstrcpy((*cli)->desthost, controller);
438 (*cli)->use_kerberos = True;
440 peeraddr_len = sizeof(peeraddr);
442 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
443 (peeraddr_len != sizeof(struct sockaddr_in)) ||
444 (peeraddr_in->sin_family != PF_INET))
446 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
447 result = NT_STATUS_UNSUCCESSFUL;
451 if (ntohs(peeraddr_in->sin_port) == 139) {
452 struct nmb_name calling;
453 struct nmb_name called;
455 make_nmb_name(&calling, global_myname(), 0x0);
456 make_nmb_name(&called, "*SMBSERVER", 0x20);
458 if (!cli_session_request(*cli, &calling, &called)) {
459 DEBUG(8, ("cli_session_request failed for %s\n",
461 result = NT_STATUS_UNSUCCESSFUL;
466 cli_setup_signing_state(*cli, Undefined);
468 if (!cli_negprot(*cli)) {
469 DEBUG(1, ("cli_negprot failed\n"));
470 result = NT_STATUS_UNSUCCESSFUL;
474 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
475 ADS_STATUS ads_status;
477 if (lp_security() == SEC_ADS) {
479 /* Try a krb5 session */
481 (*cli)->use_kerberos = True;
482 DEBUG(5, ("connecting to %s from %s with kerberos principal "
483 "[%s]\n", controller, global_myname(),
484 machine_krb5_principal));
486 ads_status = cli_session_setup_spnego(*cli,
487 machine_krb5_principal,
491 if (!ADS_ERR_OK(ads_status)) {
492 DEBUG(4,("failed kerberos session setup with %s\n",
493 ads_errstr(ads_status)));
496 result = ads_ntstatus(ads_status);
497 if (NT_STATUS_IS_OK(result)) {
498 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
499 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
500 goto session_setup_done;
504 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
505 (*cli)->use_kerberos = False;
507 DEBUG(5, ("connecting to %s from %s with username "
508 "[%s]\\[%s]\n", controller, global_myname(),
509 lp_workgroup(), machine_account));
511 ads_status = cli_session_setup_spnego(*cli,
515 if (!ADS_ERR_OK(ads_status)) {
516 DEBUG(4, ("authenticated session setup failed with %s\n",
517 ads_errstr(ads_status)));
520 result = ads_ntstatus(ads_status);
521 if (NT_STATUS_IS_OK(result)) {
522 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
523 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
524 goto session_setup_done;
528 /* Fall back to non-kerberos session setup */
530 (*cli)->use_kerberos = False;
532 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
533 (strlen(ipc_username) > 0)) {
535 /* Only try authenticated if we have a username */
537 DEBUG(5, ("connecting to %s from %s with username "
538 "[%s]\\[%s]\n", controller, global_myname(),
539 ipc_domain, ipc_username));
541 if (NT_STATUS_IS_OK(cli_session_setup(
543 ipc_password, strlen(ipc_password)+1,
544 ipc_password, strlen(ipc_password)+1,
546 /* Successful logon with given username. */
547 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
548 goto session_setup_done;
550 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
551 ipc_domain, ipc_username ));
555 /* Fall back to anonymous connection, this might fail later */
557 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
559 DEBUG(5, ("Connected anonymously\n"));
560 cli_init_creds(*cli, "", "", "");
561 goto session_setup_done;
564 result = cli_nt_error(*cli);
566 if (NT_STATUS_IS_OK(result))
567 result = NT_STATUS_UNSUCCESSFUL;
569 /* We can't session setup */
575 /* cache the server name for later connections */
577 saf_store( domain->name, (*cli)->desthost );
578 if (domain->alt_name && (*cli)->use_kerberos) {
579 saf_store( domain->alt_name, (*cli)->desthost );
582 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
584 result = cli_nt_error(*cli);
586 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
588 if (NT_STATUS_IS_OK(result))
589 result = NT_STATUS_UNSUCCESSFUL;
594 secrets_named_mutex_release(controller);
598 /* set the domain if empty; needed for schannel connections */
599 if ( !*(*cli)->domain ) {
600 fstrcpy( (*cli)->domain, domain->name );
603 result = NT_STATUS_OK;
607 secrets_named_mutex_release(controller);
610 SAFE_FREE(machine_account);
611 SAFE_FREE(machine_password);
612 SAFE_FREE(machine_krb5_principal);
613 SAFE_FREE(ipc_username);
614 SAFE_FREE(ipc_domain);
615 SAFE_FREE(ipc_password);
617 if (!NT_STATUS_IS_OK(result)) {
618 winbind_add_failed_connection_entry(domain, controller, result);
619 if ((*cli) != NULL) {
633 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
634 const char *dcname, struct in_addr ip,
635 struct dc_name_ip **dcs, int *num)
637 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
638 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
642 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
647 fstrcpy((*dcs)[*num].name, dcname);
648 (*dcs)[*num].ip = ip;
653 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
654 struct in_addr ip, uint16 port,
655 struct sockaddr_in **addrs, int *num)
657 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
662 (*addrs)[*num].sin_family = PF_INET;
663 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
664 (*addrs)[*num].sin_port = htons(port);
670 static void mailslot_name(struct in_addr dc_ip, fstring name)
672 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
675 static BOOL send_getdc_request(struct in_addr dc_ip,
676 const char *domain_name,
681 fstring my_acct_name;
684 mailslot_name(dc_ip, my_mailslot);
686 memset(outbuf, '\0', sizeof(outbuf));
690 SCVAL(p, 0, SAMLOGON);
693 SCVAL(p, 0, 0); /* Count pointer ... */
696 SIVAL(p, 0, 0); /* The sender's token ... */
699 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
700 fstr_sprintf(my_acct_name, "%s$", global_myname());
701 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
703 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
704 p += strlen(my_mailslot)+1;
709 SIVAL(p, 0, sid_size(sid));
712 p = ALIGN4(p, outbuf);
714 sid_linearize(p, sid_size(sid), sid);
722 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
723 outbuf, PTR_DIFF(p, outbuf),
724 global_myname(), 0, domain_name, 0x1c,
728 static BOOL receive_getdc_response(struct in_addr dc_ip,
729 const char *domain_name,
732 struct packet_struct *packet;
735 fstring dcname, user, domain;
738 mailslot_name(dc_ip, my_mailslot);
740 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
742 if (packet == NULL) {
743 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
747 DEBUG(5, ("Received packet for %s\n", my_mailslot));
749 buf = packet->packet.dgram.data;
750 len = packet->packet.dgram.datasize;
753 /* 70 is a completely arbitrary value to make sure
754 the SVAL below does not read uninitialized memory */
755 DEBUG(3, ("GetDC got short response\n"));
759 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
760 p = buf+SVAL(buf, smb_vwv10);
762 if (CVAL(p,0) != SAMLOGON_R) {
763 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
768 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
769 STR_TERMINATE|STR_NOALIGN);
770 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
771 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
772 STR_TERMINATE|STR_NOALIGN);
773 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
774 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
775 STR_TERMINATE|STR_NOALIGN);
776 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
778 if (!strequal(domain, domain_name)) {
779 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
780 domain_name, domain));
785 if (*p == '\\') p += 1;
786 if (*p == '\\') p += 1;
790 DEBUG(10, ("GetDC gave name %s for domain %s\n",
796 /*******************************************************************
797 convert an ip to a name
798 *******************************************************************/
800 static BOOL dcip_to_name( const char *domainname, const char *realm,
801 const DOM_SID *sid, struct in_addr ip, fstring name )
803 struct ip_service ip_list;
809 /* For active directory servers, try to get the ldap server name.
810 None of these failures should be considered critical for now */
812 if (lp_security() == SEC_ADS) {
815 ads = ads_init(realm, domainname, NULL);
816 ads->auth.flags |= ADS_AUTH_NO_BIND;
818 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
819 /* We got a cldap packet. */
820 fstrcpy(name, ads->config.ldap_server_name);
821 namecache_store(name, 0x20, 1, &ip_list);
823 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
825 if ((ads->config.flags & ADS_KDC) && ads_sitename_match(ads)) {
826 /* We're going to use this KDC for this realm/domain.
827 If we are using sites, then force the krb5 libs
830 create_local_private_krb5_conf_for_domain(realm,
834 /* Ensure we contact this DC also. */
835 saf_store( domainname, name);
836 saf_store( realm, name);
847 /* try GETDC requests next */
849 if (send_getdc_request(ip, domainname, sid)) {
852 for (i=0; i<5; i++) {
853 if (receive_getdc_response(ip, domainname, name)) {
854 namecache_store(name, 0x20, 1, &ip_list);
861 /* try node status request */
863 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
864 namecache_store(name, 0x20, 1, &ip_list);
870 /*******************************************************************
871 Retreive a list of IP address for domain controllers. Fill in
872 the dcs[] with results.
873 *******************************************************************/
875 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
876 struct dc_name_ip **dcs, int *num_dcs)
880 struct ip_service *ip_list = NULL;
884 enum security_types sec = (enum security_types)lp_security();
886 is_our_domain = strequal(domain->name, lp_workgroup());
889 && get_dc_name_via_netlogon(domain, dcname, &ip)
890 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
892 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
893 dcname, inet_ntoa(ip)));
897 if (sec == SEC_ADS) {
898 /* We need to make sure we know the local site before
899 doing any DNS queries, as this will restrict the
900 get_sorted_dc_list() call below to only fetching
901 DNS records for the correct site. */
903 /* Find any DC to get the site record.
904 We deliberately don't care about the
906 get_dc_name(domain->name, lp_realm(), dcname, &ip);
908 /* Now do the site-specific AD dns lookup. */
909 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
912 /* try standard netbios queries if no ADS */
915 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
917 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
919 /* now add to the dc array. We'll wait until the last minute
920 to look up the name of the DC. But we fill in the char* for
921 the ip now in to make the failed connection cache work */
923 for ( i=0; i<iplist_size; i++ ) {
924 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
925 ip_list[i].ip, dcs, num_dcs);
928 SAFE_FREE( ip_list );
933 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
934 const struct winbindd_domain *domain,
935 fstring dcname, struct sockaddr_in *addr, int *fd)
937 struct dc_name_ip *dcs = NULL;
940 const char **dcnames = NULL;
943 struct sockaddr_in *addrs = NULL;
949 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
952 for (i=0; i<num_dcs; i++) {
954 add_string_to_array(mem_ctx, dcs[i].name,
955 &dcnames, &num_dcnames);
956 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
959 add_string_to_array(mem_ctx, dcs[i].name,
960 &dcnames, &num_dcnames);
961 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
965 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
968 if ((addrs == NULL) || (dcnames == NULL))
971 /* 5 second timeout. */
972 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
974 for (i=0; i<num_dcs; i++) {
975 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
976 "domain %s address %s. Error was %s\n",
977 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
978 winbind_add_failed_connection_entry(domain,
979 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
984 *addr = addrs[fd_index];
986 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
987 /* Ok, we've got a name for the DC */
988 fstrcpy(dcname, dcnames[fd_index]);
992 /* Try to figure out the name */
993 if (dcip_to_name( domain->name, domain->alt_name, &domain->sid,
994 addr->sin_addr, dcname )) {
998 /* We can not continue without the DC's name */
999 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1000 NT_STATUS_UNSUCCESSFUL);
1004 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1005 struct winbindd_cm_conn *new_conn)
1007 TALLOC_CTX *mem_ctx;
1009 char *saf_servername = saf_fetch( domain->name );
1012 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1013 SAFE_FREE(saf_servername);
1014 set_domain_offline(domain);
1015 return NT_STATUS_NO_MEMORY;
1018 /* we have to check the server affinity cache here since
1019 later we selecte a DC based on response time and not preference */
1021 /* Check the negative connection cache
1022 before talking to it. It going down may have
1023 triggered the reconnection. */
1025 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1027 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1028 saf_servername, domain->name ));
1030 /* convert an ip address to a name */
1031 if ( is_ipaddress( saf_servername ) ) {
1035 ip = *interpret_addr2( saf_servername );
1036 if (dcip_to_name( domain->name, domain->alt_name,
1037 &domain->sid, ip, saf_name )) {
1038 fstrcpy( domain->dcname, saf_name );
1040 winbind_add_failed_connection_entry(
1041 domain, saf_servername,
1042 NT_STATUS_UNSUCCESSFUL);
1045 fstrcpy( domain->dcname, saf_servername );
1048 SAFE_FREE( saf_servername );
1051 for (retries = 0; retries < 3; retries++) {
1056 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1058 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1059 domain->dcname, domain->name ));
1062 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1063 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1065 struct sockaddr_in *addrs = NULL;
1069 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
1070 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
1072 /* 5 second timeout. */
1073 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1079 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1081 /* This is the one place where we will
1082 set the global winbindd offline state
1083 to true, if a "WINBINDD_OFFLINE" entry
1084 is found in the winbindd cache. */
1085 set_global_winbindd_state_offline();
1089 new_conn->cli = NULL;
1091 result = cm_prepare_connection(domain, fd, domain->dcname,
1092 &new_conn->cli, &retry);
1098 if (NT_STATUS_IS_OK(result)) {
1099 if (domain->online == False) {
1100 /* We're changing state from offline to online. */
1101 set_global_winbindd_state_online();
1103 set_domain_online(domain);
1105 /* Ensure we setup the retry handler. */
1106 set_domain_offline(domain);
1109 talloc_destroy(mem_ctx);
1113 /* Close down all open pipes on a connection. */
1115 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1117 /* We're closing down a possibly dead
1118 connection. Don't have impossibly long (10s) timeouts. */
1121 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1124 if (conn->samr_pipe != NULL) {
1125 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1126 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1128 cli_set_timeout(conn->cli, 500);
1131 conn->samr_pipe = NULL;
1134 if (conn->lsa_pipe != NULL) {
1135 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1136 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1138 cli_set_timeout(conn->cli, 500);
1141 conn->lsa_pipe = NULL;
1144 if (conn->netlogon_pipe != NULL) {
1145 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1146 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1148 cli_set_timeout(conn->cli, 500);
1151 conn->netlogon_pipe = NULL;
1155 cli_shutdown(conn->cli);
1161 void close_conns_after_fork(void)
1163 struct winbindd_domain *domain;
1165 for (domain = domain_list(); domain; domain = domain->next) {
1166 if (domain->conn.cli == NULL)
1169 if (domain->conn.cli->fd == -1)
1172 close(domain->conn.cli->fd);
1173 domain->conn.cli->fd = -1;
1177 static BOOL connection_ok(struct winbindd_domain *domain)
1179 if (domain->conn.cli == NULL) {
1180 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1181 "cli!\n", domain->dcname, domain->name));
1185 if (!domain->conn.cli->initialised) {
1186 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1187 "initialised!\n", domain->dcname, domain->name));
1191 if (domain->conn.cli->fd == -1) {
1192 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1193 "never started (fd == -1)\n",
1194 domain->dcname, domain->name));
1198 if (domain->online == False) {
1199 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1206 /* Initialize a new connection up to the RPC BIND. */
1208 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1212 /* Internal connections never use the network. */
1213 if (domain->internal) {
1214 domain->initialized = True;
1215 return NT_STATUS_OK;
1218 if (connection_ok(domain)) {
1219 if (!domain->initialized) {
1220 set_dc_type_and_flags(domain);
1222 return NT_STATUS_OK;
1225 invalidate_cm_connection(&domain->conn);
1227 result = cm_open_connection(domain, &domain->conn);
1229 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1230 set_dc_type_and_flags(domain);
1236 /******************************************************************************
1237 We can 'sense' certain things about the DC by it's replies to certain
1240 This tells us if this particular remote server is Active Directory, and if it
1242 ******************************************************************************/
1244 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1248 TALLOC_CTX *mem_ctx = NULL;
1249 struct rpc_pipe_client *cli;
1252 char *domain_name = NULL;
1253 char *dns_name = NULL;
1254 DOM_SID *dom_sid = NULL;
1258 if (!connection_ok(domain)) {
1262 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1264 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1268 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1269 "PI_LSARPC_DS on domain %s: (%s)\n",
1270 domain->name, nt_errstr(result)));
1274 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1275 DsRolePrimaryDomainInfoBasic,
1277 cli_rpc_pipe_close(cli);
1279 if (!NT_STATUS_IS_OK(result)) {
1280 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1281 "on domain %s failed: (%s)\n",
1282 domain->name, nt_errstr(result)));
1286 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1287 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1288 domain->native_mode = True;
1290 domain->native_mode = False;
1293 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1296 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1297 "PI_LSARPC on domain %s: (%s)\n",
1298 domain->name, nt_errstr(result)));
1299 cli_rpc_pipe_close(cli);
1303 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1306 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1307 cli_rpc_pipe_close(cli);
1311 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1312 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1314 if (NT_STATUS_IS_OK(result)) {
1315 /* This particular query is exactly what Win2k clients use
1316 to determine that the DC is active directory */
1317 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1323 if (NT_STATUS_IS_OK(result)) {
1324 domain->active_directory = True;
1327 fstrcpy(domain->name, domain_name);
1330 fstrcpy(domain->alt_name, dns_name);
1333 sid_copy(&domain->sid, dom_sid);
1335 domain->active_directory = False;
1337 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1338 SEC_RIGHTS_MAXIMUM_ALLOWED,
1341 if (!NT_STATUS_IS_OK(result))
1344 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1345 &pol, 5, &domain_name,
1348 if (NT_STATUS_IS_OK(result)) {
1350 fstrcpy(domain->name, domain_name);
1353 sid_copy(&domain->sid, dom_sid);
1358 DEBUG(5, ("set_dc_type_and_flags: domain %s is %snative mode.\n",
1359 domain->name, domain->native_mode ? "" : "NOT "));
1361 DEBUG(5,("set_dc_type_and_flags: domain %s is %sactive directory.\n",
1362 domain->name, domain->active_directory ? "" : "NOT "));
1364 cli_rpc_pipe_close(cli);
1366 talloc_destroy(mem_ctx);
1368 domain->initialized = True;
1371 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1372 struct dcinfo **ppdc)
1375 struct rpc_pipe_client *netlogon_pipe;
1377 if (lp_client_schannel() == False) {
1381 result = cm_connect_netlogon(domain, &netlogon_pipe);
1382 if (!NT_STATUS_IS_OK(result)) {
1386 /* Return a pointer to the struct dcinfo from the
1389 *ppdc = domain->conn.netlogon_pipe->dc;
1393 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1394 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1396 struct winbindd_cm_conn *conn;
1399 struct dcinfo *p_dcinfo;
1401 result = init_dc_connection(domain);
1402 if (!NT_STATUS_IS_OK(result)) {
1406 conn = &domain->conn;
1408 if (conn->samr_pipe != NULL) {
1413 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1414 * sign and sealed pipe using the machine account password by
1415 * preference. If we can't - try schannel, if that fails, try
1419 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1420 if ((conn->cli->user_name[0] == '\0') ||
1421 (conn->cli->domain[0] == '\0') ||
1422 (conn_pwd[0] == '\0')) {
1423 DEBUG(10, ("cm_connect_sam: No no user available for "
1424 "domain %s, trying schannel\n", conn->cli->domain));
1428 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1429 authenticated SAMR pipe with sign & seal. */
1431 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1432 PIPE_AUTH_LEVEL_PRIVACY,
1434 conn->cli->user_name,
1437 if (conn->samr_pipe == NULL) {
1438 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1439 "pipe for domain %s using NTLMSSP "
1440 "authenticated pipe: user %s\\%s. Error was "
1441 "%s\n", domain->name, conn->cli->domain,
1442 conn->cli->user_name, nt_errstr(result)));
1446 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1447 "domain %s using NTLMSSP authenticated "
1448 "pipe: user %s\\%s\n", domain->name,
1449 conn->cli->domain, conn->cli->user_name ));
1451 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1452 SEC_RIGHTS_MAXIMUM_ALLOWED,
1453 &conn->sam_connect_handle);
1454 if (NT_STATUS_IS_OK(result)) {
1457 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1458 "failed for domain %s, error was %s. Trying schannel\n",
1459 domain->name, nt_errstr(result) ));
1460 cli_rpc_pipe_close(conn->samr_pipe);
1464 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1466 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1467 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1468 "for domain %s, trying anon\n", conn->cli->domain));
1471 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1472 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1473 domain->name, p_dcinfo, &result);
1475 if (conn->samr_pipe == NULL) {
1476 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1477 "domain %s using schannel. Error was %s\n",
1478 domain->name, nt_errstr(result) ));
1481 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1482 "schannel.\n", domain->name ));
1484 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1485 SEC_RIGHTS_MAXIMUM_ALLOWED,
1486 &conn->sam_connect_handle);
1487 if (NT_STATUS_IS_OK(result)) {
1490 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1491 "for domain %s, error was %s. Trying anonymous\n",
1492 domain->name, nt_errstr(result) ));
1493 cli_rpc_pipe_close(conn->samr_pipe);
1497 /* Finally fall back to anonymous. */
1498 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1501 if (conn->samr_pipe == NULL) {
1502 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1506 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1507 SEC_RIGHTS_MAXIMUM_ALLOWED,
1508 &conn->sam_connect_handle);
1509 if (!NT_STATUS_IS_OK(result)) {
1510 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1511 "for domain %s Error was %s\n",
1512 domain->name, nt_errstr(result) ));
1517 result = rpccli_samr_open_domain(conn->samr_pipe,
1519 &conn->sam_connect_handle,
1520 SEC_RIGHTS_MAXIMUM_ALLOWED,
1522 &conn->sam_domain_handle);
1526 if (!NT_STATUS_IS_OK(result)) {
1527 invalidate_cm_connection(conn);
1531 *cli = conn->samr_pipe;
1532 *sam_handle = conn->sam_domain_handle;
1536 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1537 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1539 struct winbindd_cm_conn *conn;
1542 struct dcinfo *p_dcinfo;
1544 result = init_dc_connection(domain);
1545 if (!NT_STATUS_IS_OK(result))
1548 conn = &domain->conn;
1550 if (conn->lsa_pipe != NULL) {
1554 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1555 if ((conn->cli->user_name[0] == '\0') ||
1556 (conn->cli->domain[0] == '\0') ||
1557 (conn_pwd[0] == '\0')) {
1558 DEBUG(10, ("cm_connect_lsa: No no user available for "
1559 "domain %s, trying schannel\n", conn->cli->domain));
1563 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1564 * authenticated LSA pipe with sign & seal. */
1565 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1566 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1567 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1569 if (conn->lsa_pipe == NULL) {
1570 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1571 "domain %s using NTLMSSP authenticated pipe: user "
1572 "%s\\%s. Error was %s. Trying schannel.\n",
1573 domain->name, conn->cli->domain,
1574 conn->cli->user_name, nt_errstr(result)));
1578 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1579 "NTLMSSP authenticated pipe: user %s\\%s\n",
1580 domain->name, conn->cli->domain, conn->cli->user_name ));
1582 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1583 SEC_RIGHTS_MAXIMUM_ALLOWED,
1585 if (NT_STATUS_IS_OK(result)) {
1589 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1592 cli_rpc_pipe_close(conn->lsa_pipe);
1596 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1598 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1599 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1600 "for domain %s, trying anon\n", conn->cli->domain));
1603 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1604 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1605 domain->name, p_dcinfo, &result);
1607 if (conn->lsa_pipe == NULL) {
1608 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1609 "domain %s using schannel. Error was %s\n",
1610 domain->name, nt_errstr(result) ));
1613 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1614 "schannel.\n", domain->name ));
1616 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1617 SEC_RIGHTS_MAXIMUM_ALLOWED,
1619 if (NT_STATUS_IS_OK(result)) {
1623 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1626 cli_rpc_pipe_close(conn->lsa_pipe);
1630 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1632 if (conn->lsa_pipe == NULL) {
1633 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1637 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1638 SEC_RIGHTS_MAXIMUM_ALLOWED,
1641 if (!NT_STATUS_IS_OK(result)) {
1642 invalidate_cm_connection(conn);
1643 return NT_STATUS_UNSUCCESSFUL;
1646 *cli = conn->lsa_pipe;
1647 *lsa_policy = conn->lsa_policy;
1651 /****************************************************************************
1652 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1653 session key stored in conn->netlogon_pipe->dc->sess_key.
1654 ****************************************************************************/
1656 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1657 struct rpc_pipe_client **cli)
1659 struct winbindd_cm_conn *conn;
1662 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1664 uint32 sec_chan_type;
1665 const char *account_name;
1666 struct rpc_pipe_client *netlogon_pipe = NULL;
1670 result = init_dc_connection(domain);
1671 if (!NT_STATUS_IS_OK(result)) {
1675 conn = &domain->conn;
1677 if (conn->netlogon_pipe != NULL) {
1678 *cli = conn->netlogon_pipe;
1679 return NT_STATUS_OK;
1682 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1683 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1686 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1688 if (netlogon_pipe == NULL) {
1692 if (lp_client_schannel() != False) {
1693 neg_flags |= NETLOGON_NEG_SCHANNEL;
1696 /* if we are a DC and this is a trusted domain, then we need to use our
1697 domain name in the net_req_auth2() request */
1700 && !strequal(domain->name, lp_workgroup())
1701 && lp_allow_trusted_domains() )
1703 account_name = lp_workgroup();
1705 account_name = domain->primary ?
1706 global_myname() : domain->name;
1709 if (account_name == NULL) {
1710 cli_rpc_pipe_close(netlogon_pipe);
1711 return NT_STATUS_NO_MEMORY;
1714 result = rpccli_netlogon_setup_creds(
1716 domain->dcname, /* server name. */
1717 domain->name, /* domain name */
1718 global_myname(), /* client name */
1719 account_name, /* machine account */
1720 mach_pwd, /* machine password */
1721 sec_chan_type, /* from get_trust_pw */
1724 if (!NT_STATUS_IS_OK(result)) {
1725 cli_rpc_pipe_close(netlogon_pipe);
1729 if ((lp_client_schannel() == True) &&
1730 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1731 DEBUG(3, ("Server did not offer schannel\n"));
1732 cli_rpc_pipe_close(netlogon_pipe);
1733 return NT_STATUS_ACCESS_DENIED;
1736 if ((lp_client_schannel() == False) ||
1737 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1738 /* We're done - just keep the existing connection to NETLOGON
1740 conn->netlogon_pipe = netlogon_pipe;
1741 *cli = conn->netlogon_pipe;
1742 return NT_STATUS_OK;
1745 /* Using the credentials from the first pipe, open a signed and sealed
1746 second netlogon pipe. The session key is stored in the schannel
1747 part of the new pipe auth struct.
1750 conn->netlogon_pipe =
1751 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1753 PIPE_AUTH_LEVEL_PRIVACY,
1758 /* We can now close the initial netlogon pipe. */
1759 cli_rpc_pipe_close(netlogon_pipe);
1761 if (conn->netlogon_pipe == NULL) {
1762 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1763 "was %s\n", nt_errstr(result)));
1765 /* make sure we return something besides OK */
1766 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
1769 *cli = conn->netlogon_pipe;
1770 return NT_STATUS_OK;