r11328: Actually verify that the bind on a pipe succeeded with a samr_connect or
[tprouty/samba.git] / source / nsswitch / winbindd_cm.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon connection manager
5
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    
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.
15    
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.
20    
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.
24 */
25
26 /*
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:
30   
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
34          selection etc
35        - manage re-entrancy for when winbindd becomes able to handle
36          multiple outstanding rpc requests
37   
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.
44
45    The TNG design is quite good but I disagree with some aspects of the
46    implementation. -tpot
47
48  */
49
50 /*
51    TODO:
52
53      - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
54        moved down into another function.
55
56      - Take care when destroying cli_structs as they can be shared between
57        various sam handles.
58
59  */
60
61 #include "includes.h"
62 #include "winbindd.h"
63
64 #undef DBGC_CLASS
65 #define DBGC_CLASS DBGC_WINBIND
66
67
68 /* Choose between anonymous or authenticated connections.  We need to use
69    an authenticated connection if DCs have the RestrictAnonymous registry
70    entry set > 0, or the "Additional restrictions for anonymous
71    connections" set in the win2k Local Security Policy. 
72    
73    Caller to free() result in domain, username, password
74 */
75
76 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
77 {
78         *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
79         *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
80         *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
81         
82         if (*username && **username) {
83
84                 if (!*domain || !**domain)
85                         *domain = smb_xstrdup(lp_workgroup());
86                 
87                 if (!*password || !**password)
88                         *password = smb_xstrdup("");
89
90                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
91                           *domain, *username));
92
93         } else {
94                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
95                 *username = smb_xstrdup("");
96                 *domain = smb_xstrdup("");
97                 *password = smb_xstrdup("");
98         }
99 }
100
101 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
102                                      fstring dcname, struct in_addr *dc_ip)
103 {
104         struct winbindd_domain *our_domain;
105         struct rpc_pipe_client *netlogon_pipe;
106         NTSTATUS result;
107         TALLOC_CTX *mem_ctx;
108         const char *server_name;
109
110         fstring tmp;
111         char *p;
112
113         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
114          * moment.... */
115
116         if (IS_DC) {
117                 return False;
118         }
119
120         if (domain->primary) {
121                 return False;
122         }
123
124         our_domain = find_our_domain();
125
126         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
127                 return False;
128         }
129
130         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
131         if (!NT_STATUS_IS_OK(result)) {
132                 return False;
133         }
134
135         server_name = talloc_asprintf(mem_ctx, "\\\\%s", our_domain->dcname);
136         if (server_name == NULL) {
137                 return False;
138         }
139
140         result = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, server_name,
141                                            domain->name, tmp);
142
143         talloc_destroy(mem_ctx);
144
145         if (!NT_STATUS_IS_OK(result)) {
146                 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
147                            nt_errstr(result)));
148                 return False;
149         }
150
151         /* cli_netlogon_getdcname gives us a name with \\ */
152         p = tmp;
153         if (*p == '\\') {
154                 p+=1;
155         }
156         if (*p == '\\') {
157                 p+=1;
158         }
159
160         fstrcpy(dcname, p);
161
162         DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
163
164         if (!resolve_name(dcname, dc_ip, 0x20)) {
165                 return False;
166         }
167
168         return True;
169 }
170
171 /************************************************************************
172  Given a fd with a just-connected TCP connection to a DC, open a connection
173  to the pipe.
174 ************************************************************************/
175
176 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
177                                       const int sockfd,
178                                       const char *controller,
179                                       struct cli_state **cli,
180                                       BOOL *retry)
181 {
182         char *machine_password, *machine_krb5_principal, *machine_account;
183         char *ipc_username, *ipc_domain, *ipc_password;
184
185         BOOL got_mutex;
186         BOOL add_failed_connection = True;
187
188         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
189
190         struct sockaddr peeraddr;
191         socklen_t peeraddr_len;
192
193         struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
194
195         machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
196                                                           NULL);
197         
198         if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
199                 SAFE_FREE(machine_password);
200                 return NT_STATUS_NO_MEMORY;
201         }
202
203         if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
204                      lp_realm()) == -1) {
205                 SAFE_FREE(machine_account);
206                 SAFE_FREE(machine_password);
207                 return NT_STATUS_NO_MEMORY;
208         }
209
210         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
211
212         *retry = True;
213
214         got_mutex = secrets_named_mutex(controller,
215                                         WINBIND_SERVER_MUTEX_WAIT_TIME);
216
217         if (!got_mutex) {
218                 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n",
219                          controller));
220                 result = NT_STATUS_POSSIBLE_DEADLOCK;
221                 goto done;
222         }
223
224         if ((*cli = cli_initialise(NULL)) == NULL) {
225                 DEBUG(1, ("Could not cli_initialize\n"));
226                 result = NT_STATUS_NO_MEMORY;
227                 goto done;
228         }
229
230         (*cli)->timeout = 10000;        /* 10 seconds */
231         (*cli)->fd = sockfd;
232         fstrcpy((*cli)->desthost, controller);
233         (*cli)->use_kerberos = True;
234
235         peeraddr_len = sizeof(peeraddr);
236
237         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
238             (peeraddr_len != sizeof(struct sockaddr_in)) ||
239             (peeraddr_in->sin_family != PF_INET))
240         {
241                 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
242                 goto done;
243         }
244
245         if (ntohs(peeraddr_in->sin_port) == 139) {
246                 struct nmb_name calling;
247                 struct nmb_name called;
248
249                 make_nmb_name(&calling, global_myname(), 0x0);
250                 make_nmb_name(&called, "*SMBSERVER", 0x20);
251
252                 if (!cli_session_request(*cli, &calling, &called)) {
253                         DEBUG(8, ("cli_session_request failed for %s\n",
254                                   controller));
255                         goto done;
256                 }
257         }
258
259         cli_setup_signing_state(*cli, Undefined);
260
261         if (!cli_negprot(*cli)) {
262                 DEBUG(1, ("cli_negprot failed\n"));
263                 cli_shutdown(*cli);
264                 goto done;
265         }
266
267                         
268         if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
269                 ADS_STATUS ads_status;
270
271                 if (lp_security() == SEC_ADS) {
272
273                         /* Try a krb5 session */
274
275                         (*cli)->use_kerberos = True;
276                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
277                                   "[%s]\n", controller, global_myname(),
278                                   machine_krb5_principal));
279
280                         ads_status = cli_session_setup_spnego(*cli,
281                                                               machine_krb5_principal, 
282                                                               machine_password, 
283                                                               lp_workgroup());
284
285                         if (!ADS_ERR_OK(ads_status)) {
286                                 DEBUG(4,("failed kerberos session setup with %s\n",
287                                          ads_errstr(ads_status)));
288                         }
289
290                         result = ads_ntstatus(ads_status);
291                         if (NT_STATUS_IS_OK(result)) {
292                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
293                                 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
294                                 goto session_setup_done;
295                         }
296                 }
297
298                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
299                 (*cli)->use_kerberos = False;
300
301                 DEBUG(5, ("connecting to %s from %s with username "
302                           "[%s]\\[%s]\n",  controller, global_myname(),
303                           machine_account, machine_password));
304
305                 ads_status = cli_session_setup_spnego(*cli,
306                                                       machine_account, 
307                                                       machine_password, 
308                                                       lp_workgroup());
309                 if (!ADS_ERR_OK(ads_status)) {
310                         DEBUG(4, ("authenticated session setup failed with %s\n",
311                                 ads_errstr(ads_status)));
312                 }
313
314                 result = ads_ntstatus(ads_status);
315                 if (NT_STATUS_IS_OK(result)) {
316                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
317                         cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
318                         goto session_setup_done;
319                 }
320         }
321
322         /* Fall back to non-kerberos session setup */
323
324         (*cli)->use_kerberos = False;
325
326         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
327             (strlen(ipc_username) > 0)) {
328
329                 /* Only try authenticated if we have a username */
330
331                 DEBUG(5, ("connecting to %s from %s with username "
332                           "[%s]\\[%s]\n",  controller, global_myname(),
333                           ipc_domain, ipc_username));
334
335                 if (cli_session_setup(*cli, ipc_username,
336                                       ipc_password, strlen(ipc_password)+1,
337                                       ipc_password, strlen(ipc_password)+1,
338                                       ipc_domain)) {
339                         /* Successful logon with given username. */
340                         cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
341                         goto session_setup_done;
342                 } else {
343                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
344                                 ipc_domain, ipc_username ));
345                 }
346         }
347
348         /* Fall back to anonymous connection, this might fail later */
349
350         if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
351                 DEBUG(5, ("Connected anonymously\n"));
352                 cli_init_creds(*cli, "", "", "");
353                 goto session_setup_done;
354         }
355
356         result = cli_nt_error(*cli);
357
358         if (NT_STATUS_IS_OK(result))
359                 result = NT_STATUS_UNSUCCESSFUL;
360
361         /* We can't session setup */
362
363         goto done;
364
365  session_setup_done:
366
367         if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
368
369                 result = cli_nt_error(*cli);
370
371                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
372
373                 if (NT_STATUS_IS_OK(result))
374                         result = NT_STATUS_UNSUCCESSFUL;
375
376                 cli_shutdown(*cli);
377                 goto done;
378         }
379
380         secrets_named_mutex_release(controller);
381         got_mutex = False;
382         *retry = False;
383
384         /* set the domain if empty; needed for schannel connections */
385         if ( !*(*cli)->domain ) {
386                 fstrcpy( (*cli)->domain, domain->name );
387         }
388
389         result = NT_STATUS_OK;
390         add_failed_connection = False;
391
392  done:
393         if (got_mutex) {
394                 secrets_named_mutex_release(controller);
395         }
396
397         SAFE_FREE(machine_account);
398         SAFE_FREE(machine_password);
399         SAFE_FREE(machine_krb5_principal);
400         SAFE_FREE(ipc_username);
401         SAFE_FREE(ipc_domain);
402         SAFE_FREE(ipc_password);
403
404         if (add_failed_connection) {
405                 add_failed_connection_entry(domain->name, controller, result);
406         }
407
408         return result;
409 }
410
411 struct dc_name_ip {
412         fstring name;
413         struct in_addr ip;
414 };
415
416 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
417                               const char *dcname, struct in_addr ip,
418                               struct dc_name_ip **dcs, int *num)
419 {
420         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
421                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
422                 return False;
423         }
424
425         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
426
427         if (*dcs == NULL)
428                 return False;
429
430         fstrcpy((*dcs)[*num].name, dcname);
431         (*dcs)[*num].ip = ip;
432         *num += 1;
433         return True;
434 }
435
436 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
437                                   struct in_addr ip, uint16 port,
438                                   struct sockaddr_in **addrs, int *num)
439 {
440         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
441
442         if (*addrs == NULL)
443                 return False;
444
445         (*addrs)[*num].sin_family = PF_INET;
446         putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
447         (*addrs)[*num].sin_port = htons(port);
448
449         *num += 1;
450         return True;
451 }
452
453 static void mailslot_name(struct in_addr dc_ip, fstring name)
454 {
455         fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
456 }
457
458 static BOOL send_getdc_request(struct in_addr dc_ip,
459                                const char *domain_name,
460                                const DOM_SID *sid)
461 {
462         pstring outbuf;
463         char *p;
464         fstring my_acct_name;
465         fstring my_mailslot;
466
467         mailslot_name(dc_ip, my_mailslot);
468
469         memset(outbuf, '\0', sizeof(outbuf));
470
471         p = outbuf;
472
473         SCVAL(p, 0, SAMLOGON);
474         p++;
475
476         SCVAL(p, 0, 0); /* Count pointer ... */
477         p++;
478
479         SIVAL(p, 0, 0); /* The sender's token ... */
480         p += 2;
481
482         p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
483         fstr_sprintf(my_acct_name, "%s$", global_myname());
484         p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
485
486         memcpy(p, my_mailslot, strlen(my_mailslot)+1);
487         p += strlen(my_mailslot)+1;
488
489         SIVAL(p, 0, 0x80);
490         p+=4;
491
492         SIVAL(p, 0, sid_size(sid));
493         p+=4;
494
495         p = ALIGN4(p, outbuf);
496
497         sid_linearize(p, sid_size(sid), sid);
498         p += sid_size(sid);
499
500         SIVAL(p, 0, 1);
501         SSVAL(p, 4, 0xffff);
502         SSVAL(p, 6, 0xffff);
503         p+=8;
504
505         return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
506                                  outbuf, PTR_DIFF(p, outbuf),
507                                  global_myname(), 0, domain_name, 0x1c,
508                                  dc_ip);
509 }
510
511 static BOOL receive_getdc_response(struct in_addr dc_ip,
512                                    const char *domain_name,
513                                    fstring dc_name)
514 {
515         struct packet_struct *packet;
516         fstring my_mailslot;
517         char *buf, *p;
518         fstring dcname, user, domain;
519         int len;
520
521         mailslot_name(dc_ip, my_mailslot);
522
523         packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
524
525         if (packet == NULL) {
526                 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
527                 return False;
528         }
529
530         DEBUG(5, ("Received packet for %s\n", my_mailslot));
531
532         buf = packet->packet.dgram.data;
533         len = packet->packet.dgram.datasize;
534
535         if (len < 70) {
536                 /* 70 is a completely arbitrary value to make sure
537                    the SVAL below does not read uninitialized memory */
538                 DEBUG(3, ("GetDC got short response\n"));
539                 return False;
540         }
541
542         /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
543         p = buf+SVAL(buf, smb_vwv10);
544
545         if (CVAL(p,0) != SAMLOGON_R) {
546                 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
547                 return False;
548         }
549
550         p+=2;
551         pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
552                   STR_TERMINATE|STR_NOALIGN);
553         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
554         pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
555                   STR_TERMINATE|STR_NOALIGN);
556         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
557         pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
558                   STR_TERMINATE|STR_NOALIGN);
559         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
560
561         if (!strequal(domain, domain_name)) {
562                 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
563                           domain_name, domain));
564                 return False;
565         }
566
567         p = dcname;
568         if (*p == '\\') p += 1;
569         if (*p == '\\') p += 1;
570
571         fstrcpy(dc_name, p);
572
573         DEBUG(10, ("GetDC gave name %s for domain %s\n",
574                    dc_name, domain));
575
576         return True;
577 }
578
579 /*******************************************************************
580  convert an ip to a name
581 *******************************************************************/
582
583 static void dcip_to_name( const char *domainname, const char *realm, 
584                           const DOM_SID *sid, struct in_addr ip, fstring name )
585 {
586
587         /* try GETDC requests first */
588         
589         if (send_getdc_request(ip, domainname, sid)) {
590                 int i;
591                 smb_msleep(100);
592                 for (i=0; i<5; i++) {
593                         if (receive_getdc_response(ip, domainname, name))
594                                 return;
595                         smb_msleep(500);
596                 }
597         }
598
599         /* try node status request */
600
601         if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
602                 return;
603
604         /* backup in case the netbios stuff fails */
605
606         fstrcpy( name, inet_ntoa(ip) );
607
608 #ifdef WITH_ADS
609         /* for active directory servers, try to get the ldap server name.
610            None of these failure should be considered critical for now */
611
612         if ( lp_security() == SEC_ADS ) 
613         {
614                 ADS_STRUCT *ads;
615                 ADS_STATUS status;
616
617                 ads = ads_init( realm, domainname, NULL );
618                 ads->auth.flags |= ADS_AUTH_NO_BIND;
619
620                 if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) )  {
621                         ads_destroy( &ads );
622                         return;
623                 }
624
625                 status = ads_server_info(ads);
626                 if ( !ADS_ERR_OK(status) ) {
627                         ads_destroy( &ads );
628                         return;
629                 }
630
631                 fstrcpy(name, ads->config.ldap_server_name);
632
633                 ads_destroy( &ads );
634         }
635 #endif
636
637         return;
638 }
639
640 /*******************************************************************
641  Retreive a list of IP address for domain controllers.  Fill in 
642  the dcs[]  with results.
643 *******************************************************************/
644
645 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
646                     struct dc_name_ip **dcs, int *num_dcs)
647 {
648         fstring dcname;
649         struct  in_addr ip;
650         struct  ip_service *ip_list = NULL;
651         int     iplist_size = 0;
652         int     i;
653         BOOL    is_our_domain;
654
655
656         is_our_domain = strequal(domain->name, lp_workgroup());
657
658         if ( !is_our_domain 
659                 && get_dc_name_via_netlogon(domain, dcname, &ip) 
660                 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
661         {
662                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
663                            dcname, inet_ntoa(ip)));
664                 return True;
665         }
666
667         if ( is_our_domain 
668                 && must_use_pdc(domain->name) 
669                 && get_pdc_ip(domain->name, &ip)) 
670         {
671                 if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs)) 
672                         return True;
673         }
674
675         /* try standard netbios queries first */
676
677         get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
678
679         /* check for security = ads and use DNS if we can */
680
681         if ( iplist_size==0 && lp_security() == SEC_ADS ) 
682                 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
683
684         /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
685
686         /* now add to the dc array.  We'll wait until the last minute 
687            to look up the name of the DC.  But we fill in the char* for 
688            the ip now in to make the failed connection cache work */
689
690         for ( i=0; i<iplist_size; i++ ) {
691                 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip), 
692                         ip_list[i].ip, dcs, num_dcs);
693         }
694
695         SAFE_FREE( ip_list );
696
697         return True;
698 }
699
700 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
701                         const struct winbindd_domain *domain,
702                         fstring dcname, struct sockaddr_in *addr, int *fd)
703 {
704         struct dc_name_ip *dcs = NULL;
705         int num_dcs = 0;
706
707         const char **dcnames = NULL;
708         int num_dcnames = 0;
709
710         struct sockaddr_in *addrs = NULL;
711         int num_addrs = 0;
712
713         int i, fd_index;
714
715         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
716                 return False;
717
718         for (i=0; i<num_dcs; i++) {
719
720                 add_string_to_array(mem_ctx, dcs[i].name,
721                                     &dcnames, &num_dcnames);
722                 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
723                                       &addrs, &num_addrs);
724
725                 add_string_to_array(mem_ctx, dcs[i].name,
726                                     &dcnames, &num_dcnames);
727                 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
728                                       &addrs, &num_addrs);
729         }
730
731         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
732                 return False;
733
734         if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) ) 
735         {
736                 for (i=0; i<num_dcs; i++) {
737                         add_failed_connection_entry(domain->name,
738                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
739                 }
740                 return False;
741         }
742
743         *addr = addrs[fd_index];
744
745         /* if we have no name on the server or just an IP address for 
746            the name, now try to get the name */
747
748         if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
749                 dcip_to_name( domain->name, domain->alt_name, &domain->sid, addr->sin_addr, dcname );
750         else
751                 fstrcpy(dcname, dcnames[fd_index]);
752
753         return True;
754 }
755
756 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
757                                    struct winbindd_cm_conn *new_conn)
758 {
759         TALLOC_CTX *mem_ctx;
760         NTSTATUS result;
761
762         int retries;
763
764         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
765                 return NT_STATUS_NO_MEMORY;
766
767         for (retries = 0; retries < 3; retries++) {
768
769                 int fd = -1;
770                 BOOL retry = False;
771
772                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
773
774                 if ((strlen(domain->dcname) > 0) &&
775                     NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
776                                                               domain->dcname))) {
777                         int dummy;
778                         if (!open_any_socket_out(&domain->dcaddr, 1, 10000,
779                                                  &dummy, &fd)) {
780                                 fd = -1;
781                         }
782                 }
783
784                 if ((fd == -1) &&
785                     !find_new_dc(mem_ctx, domain, domain->dcname,
786                                  &domain->dcaddr, &fd))
787                         break;
788
789                 new_conn->cli = NULL;
790
791                 result = cm_prepare_connection(domain, fd, domain->dcname,
792                         &new_conn->cli, &retry);
793
794                 if (!retry)
795                         break;
796         }
797
798         talloc_destroy(mem_ctx);
799         return result;
800 }
801
802 /* Return true if a connection is still alive */
803
804 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
805 {
806         if (conn->samr_pipe != NULL) {
807                 cli_rpc_pipe_close(conn->samr_pipe);
808                 conn->samr_pipe = NULL;
809         }
810
811         if (conn->lsa_pipe != NULL) {
812                 cli_rpc_pipe_close(conn->lsa_pipe);
813                 conn->lsa_pipe = NULL;
814         }
815
816         if (conn->netlogon_pipe != NULL) {
817                 cli_rpc_pipe_close(conn->netlogon_pipe);
818                 conn->netlogon_pipe = NULL;
819         }
820
821         if (conn->cli) {
822                 cli_shutdown(conn->cli);
823         }
824
825         conn->cli = NULL;
826 }
827
828 void close_conns_after_fork(void)
829 {
830         struct winbindd_domain *domain;
831
832         for (domain = domain_list(); domain; domain = domain->next) {
833                 if (domain->conn.cli == NULL)
834                         continue;
835
836                 if (domain->conn.cli->fd == -1)
837                         continue;
838
839                 close(domain->conn.cli->fd);
840                 domain->conn.cli->fd = -1;
841         }
842 }
843
844 static BOOL connection_ok(struct winbindd_domain *domain)
845 {
846         if (domain->conn.cli == NULL) {
847                 DEBUG(8, ("Connection to %s for domain %s has NULL "
848                           "cli!\n", domain->dcname, domain->name));
849                 return False;
850         }
851
852         if (!domain->conn.cli->initialised) {
853                 DEBUG(3, ("Connection to %s for domain %s was never "
854                           "initialised!\n", domain->dcname, domain->name));
855                 return False;
856         }
857
858         if (domain->conn.cli->fd == -1) {
859                 DEBUG(3, ("Connection to %s for domain %s has died or was "
860                           "never started (fd == -1)\n", 
861                           domain->dcname, domain->name));
862                 return False;
863         }
864
865         return True;
866 }
867         
868 /* Initialize a new connection up to the RPC BIND. */
869
870 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
871 {
872         if (connection_ok(domain))
873                 return NT_STATUS_OK;
874
875         invalidate_cm_connection(&domain->conn);
876
877         return cm_open_connection(domain, &domain->conn);
878 }
879
880 /******************************************************************************
881  We can 'sense' certain things about the DC by it's replies to certain
882  questions.
883
884  This tells us if this particular remote server is Active Directory, and if it
885  is native mode.
886 ******************************************************************************/
887
888 void set_dc_type_and_flags( struct winbindd_domain *domain )
889 {
890         NTSTATUS                result;
891         DS_DOMINFO_CTR          ctr;
892         TALLOC_CTX              *mem_ctx = NULL;
893         struct rpc_pipe_client  *cli;
894         POLICY_HND pol;
895         
896         char *domain_name = NULL;
897         char *dns_name = NULL;
898         DOM_SID *dom_sid = NULL;
899
900         ZERO_STRUCT( ctr );
901         
902         domain->native_mode = False;
903         domain->active_directory = False;
904
905         if (domain->internal) {
906                 domain->initialized = True;
907                 return;
908         }
909
910         result = init_dc_connection(domain);
911         if (!NT_STATUS_IS_OK(result)) {
912                 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
913                           "to %s: (%s)\n", domain->name, nt_errstr(result)));
914                 domain->initialized = True;
915                 return;
916         }
917
918         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
919                                        &result);
920
921         if (cli == NULL) {
922                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
923                           "PI_LSARPC_DS on domain %s: (%s)\n",
924                           domain->name, nt_errstr(result)));
925                 domain->initialized = True;
926                 return;
927         }
928
929         result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
930                                              DsRolePrimaryDomainInfoBasic,
931                                              &ctr);
932         cli_rpc_pipe_close(cli);
933
934         if (!NT_STATUS_IS_OK(result)) {
935                 domain->initialized = True;
936                 return;
937         }
938         
939         if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
940             !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
941                 domain->native_mode = True;
942
943         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
944
945         if (cli == NULL) {
946                 domain->initialized = True;
947                 return;
948         }
949
950         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
951                               domain->name);
952         if (!mem_ctx) {
953                 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
954                 cli_rpc_pipe_close(cli);
955                 return;
956         }
957
958         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
959                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
960                 
961         if (NT_STATUS_IS_OK(result)) {
962                 /* This particular query is exactly what Win2k clients use 
963                    to determine that the DC is active directory */
964                 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
965                                                        12, &domain_name,
966                                                        &dns_name, NULL,
967                                                        NULL, &dom_sid);
968         }
969
970         if (NT_STATUS_IS_OK(result)) {
971                 if (domain_name)
972                         fstrcpy(domain->name, domain_name);
973
974                 if (dns_name)
975                         fstrcpy(domain->alt_name, dns_name);
976
977                 if (dom_sid) 
978                         sid_copy(&domain->sid, dom_sid);
979
980                 domain->active_directory = True;
981         } else {
982                 
983                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
984                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
985                                                 &pol);
986                         
987                 if (!NT_STATUS_IS_OK(result))
988                         goto done;
989                         
990                 result = rpccli_lsa_query_info_policy(cli, mem_ctx, 
991                                                       &pol, 5, &domain_name, 
992                                                       &dom_sid);
993                         
994                 if (NT_STATUS_IS_OK(result)) {
995                         if (domain_name)
996                                 fstrcpy(domain->name, domain_name);
997
998                         if (dom_sid) 
999                                 sid_copy(&domain->sid, dom_sid);
1000                 }
1001         }
1002 done:
1003
1004         cli_rpc_pipe_close(cli);
1005         
1006         talloc_destroy(mem_ctx);
1007
1008         domain->initialized = True;
1009         
1010         return;
1011 }
1012
1013 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1014                                    struct dcinfo **ppdc)
1015 {
1016         NTSTATUS result;
1017         struct rpc_pipe_client *netlogon_pipe;
1018
1019         if (lp_client_schannel() == False) {
1020                 return False;
1021         }
1022
1023         result = cm_connect_netlogon(domain, &netlogon_pipe);
1024         if (!NT_STATUS_IS_OK(result)) {
1025                 return False;
1026         }
1027
1028         /* Return a pointer to the struct dcinfo from the
1029            netlogon pipe. */
1030
1031         *ppdc = domain->conn.netlogon_pipe->dc;
1032         return True;
1033 }
1034
1035 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1036                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1037 {
1038         struct winbindd_cm_conn *conn;
1039         NTSTATUS result;
1040         fstring conn_pwd;
1041         struct dcinfo *p_dcinfo;
1042
1043         result = init_dc_connection(domain);
1044         if (!NT_STATUS_IS_OK(result)) {
1045                 return result;
1046         }
1047
1048         conn = &domain->conn;
1049
1050         if (conn->samr_pipe != NULL) {
1051                 goto done;
1052         }
1053
1054         /*
1055          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1056          * sign and sealed pipe using the machine account password by
1057          * preference. If we can't - try schannel, if that fails, try
1058          * anonymous.
1059          */
1060
1061         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1062         if ((conn->cli->user_name[0] == '\0') ||
1063             (conn->cli->domain[0] == '\0') || 
1064             (conn_pwd[0] == '\0')) {
1065                 DEBUG(10, ("cm_connect_sam: No no user available for "
1066                            "domain %s, trying schannel\n", conn->cli->domain));
1067                 goto schannel;
1068         }
1069
1070         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1071            authenticated SAMR pipe with sign & seal. */
1072         conn->samr_pipe =
1073                 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1074                                                  PIPE_AUTH_LEVEL_PRIVACY,
1075                                                  conn->cli->domain,
1076                                                  conn->cli->user_name,
1077                                                  conn_pwd, &result);
1078
1079         if (conn->samr_pipe == NULL) {
1080                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1081                           "pipe for domain %s using NTLMSSP "
1082                           "authenticated pipe: user %s\\%s. Error was "
1083                           "%s\n", domain->name, conn->cli->domain,
1084                           conn->cli->user_name, nt_errstr(result)));
1085                 goto schannel;
1086         }
1087
1088         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1089                   "domain %s using NTLMSSP authenticated "
1090                   "pipe: user %s\\%s\n", domain->name,
1091                   conn->cli->domain, conn->cli->user_name ));
1092
1093         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1094                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1095                                      &conn->sam_connect_handle);
1096         if (NT_STATUS_IS_OK(result)) {
1097                 goto open_domain;
1098         }
1099         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1100                   "failed for domain %s, error was %s. Trying schannel\n",
1101                   domain->name, nt_errstr(result) ));
1102         cli_rpc_pipe_close(conn->samr_pipe);
1103
1104  schannel:
1105
1106         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1107
1108         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1109                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1110                            "for domain %s, trying anon\n", conn->cli->domain));
1111                 goto anonymous;
1112         }
1113         conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1114                 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1115                  domain->name, p_dcinfo, &result);
1116
1117         if (conn->samr_pipe == NULL) {
1118                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1119                           "domain %s using schannel. Error was %s\n",
1120                           domain->name, nt_errstr(result) ));
1121                 goto anonymous;
1122         }
1123         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1124                   "schannel.\n", domain->name ));
1125
1126         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1127                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1128                                      &conn->sam_connect_handle);
1129         if (NT_STATUS_IS_OK(result)) {
1130                 goto open_domain;
1131         }
1132         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1133                   "for domain %s, error was %s. Trying anonymous\n",
1134                   domain->name, nt_errstr(result) ));
1135         cli_rpc_pipe_close(conn->samr_pipe);
1136
1137  anonymous:
1138
1139         /* Finally fall back to anonymous. */
1140         conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1141                                                    &result);
1142
1143         if (conn->samr_pipe == NULL) {
1144                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1145                 goto done;
1146         }
1147
1148         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1149                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1150                                      &conn->sam_connect_handle);
1151         if (!NT_STATUS_IS_OK(result)) {
1152                 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1153                           "for domain %s Error was %s\n",
1154                           domain->name, nt_errstr(result) ));
1155                 goto done;
1156         }
1157
1158  open_domain:
1159         result = rpccli_samr_open_domain(conn->samr_pipe,
1160                                          mem_ctx,
1161                                          &conn->sam_connect_handle,
1162                                          SEC_RIGHTS_MAXIMUM_ALLOWED,
1163                                          &domain->sid,
1164                                          &conn->sam_domain_handle);
1165
1166  done:
1167
1168         if (!NT_STATUS_IS_OK(result)) {
1169                 invalidate_cm_connection(conn);
1170                 return result;
1171         }
1172
1173         *cli = conn->samr_pipe;
1174         *sam_handle = conn->sam_domain_handle;
1175         return result;
1176 }
1177
1178 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1179                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1180 {
1181         struct winbindd_cm_conn *conn;
1182         NTSTATUS result;
1183         fstring conn_pwd;
1184         struct dcinfo *p_dcinfo;
1185
1186         result = init_dc_connection(domain);
1187         if (!NT_STATUS_IS_OK(result))
1188                 return result;
1189
1190         conn = &domain->conn;
1191
1192         if (conn->lsa_pipe != NULL) {
1193                 goto done;
1194         }
1195
1196         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1197         if ((conn->cli->user_name[0] == '\0') ||
1198             (conn->cli->domain[0] == '\0') || 
1199             (conn_pwd[0] == '\0')) {
1200                 DEBUG(10, ("cm_connect_lsa: No no user available for "
1201                            "domain %s, trying schannel\n", conn->cli->domain));
1202                 goto schannel;
1203         }
1204
1205         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1206          * authenticated LSA pipe with sign & seal. */
1207         conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1208                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1209                  conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1210
1211         if (conn->lsa_pipe == NULL) {
1212                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1213                           "domain %s using NTLMSSP authenticated pipe: user "
1214                           "%s\\%s. Error was %s. Trying schannel.\n",
1215                           domain->name, conn->cli->domain,
1216                           conn->cli->user_name, nt_errstr(result)));
1217                 goto schannel;
1218         }
1219
1220         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1221                   "NTLMSSP authenticated pipe: user %s\\%s\n",
1222                   domain->name, conn->cli->domain, conn->cli->user_name ));
1223
1224         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1225                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1226                                         &conn->lsa_policy);
1227         if (NT_STATUS_IS_OK(result)) {
1228                 goto done;
1229         }
1230
1231         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1232                   "schannel\n"));
1233
1234         cli_rpc_pipe_close(conn->lsa_pipe);
1235
1236  schannel:
1237
1238         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1239
1240         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1241                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1242                            "for domain %s, trying anon\n", conn->cli->domain));
1243                 goto anonymous;
1244         }
1245         conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1246                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1247                  domain->name, p_dcinfo, &result);
1248
1249         if (conn->lsa_pipe == NULL) {
1250                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1251                           "domain %s using schannel. Error was %s\n",
1252                           domain->name, nt_errstr(result) ));
1253                 goto anonymous;
1254         }
1255         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1256                   "schannel.\n", domain->name ));
1257
1258         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1259                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1260                                         &conn->lsa_policy);
1261         if (NT_STATUS_IS_OK(result)) {
1262                 goto done;
1263         }
1264
1265         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1266                   "anonymous\n"));
1267
1268         cli_rpc_pipe_close(conn->lsa_pipe);
1269
1270  anonymous:
1271
1272         conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1273                                                   &result);
1274         if (conn->lsa_pipe == NULL) {
1275                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1276                 goto done;
1277         }
1278
1279         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1280                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1281                                         &conn->lsa_policy);
1282  done:
1283         if (!NT_STATUS_IS_OK(result)) {
1284                 invalidate_cm_connection(conn);
1285                 return NT_STATUS_UNSUCCESSFUL;
1286         }
1287
1288         *cli = conn->lsa_pipe;
1289         *lsa_policy = conn->lsa_policy;
1290         return result;
1291 }
1292
1293 /****************************************************************************
1294  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1295  session key stored in conn->netlogon_pipe->dc->sess_key.
1296 ****************************************************************************/
1297
1298 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1299                              struct rpc_pipe_client **cli)
1300 {
1301         struct winbindd_cm_conn *conn;
1302         NTSTATUS result;
1303
1304         uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1305         uint8  mach_pwd[16];
1306         uint32  sec_chan_type;
1307         const char *account_name;
1308         struct rpc_pipe_client *netlogon_pipe;
1309
1310         result = init_dc_connection(domain);
1311         if (!NT_STATUS_IS_OK(result)) {
1312                 return result;
1313         }
1314
1315         conn = &domain->conn;
1316
1317         if (conn->netlogon_pipe != NULL) {
1318                 *cli = conn->netlogon_pipe;
1319                 return NT_STATUS_OK;
1320         }
1321
1322         if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1323                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1324         }
1325
1326         netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1327                                                  &result);
1328         if (netlogon_pipe == NULL) {
1329                 return result;
1330         }
1331
1332         if (lp_client_schannel() != False) {
1333                 neg_flags |= NETLOGON_NEG_SCHANNEL;
1334         }
1335
1336         /* if we are a DC and this is a trusted domain, then we need to use our
1337            domain name in the net_req_auth2() request */
1338
1339         if ( IS_DC
1340                 && !strequal(domain->name, lp_workgroup())
1341                 && lp_allow_trusted_domains() ) 
1342         {
1343                 account_name = lp_workgroup();
1344         } else {
1345                 account_name = domain->primary ?
1346                         global_myname() : domain->name;
1347         }
1348
1349         if (account_name == NULL) {
1350                 cli_rpc_pipe_close(netlogon_pipe);
1351                 return NT_STATUS_NO_MEMORY;
1352         }
1353
1354         result = rpccli_netlogon_setup_creds
1355                 (netlogon_pipe,
1356                  domain->dcname, /* server name. */
1357                  domain->name,   /* domain name */
1358                  account_name,   /* machine account */
1359                  mach_pwd,       /* machine password */
1360                  sec_chan_type,  /* from get_trust_pw */
1361                  &neg_flags);
1362
1363         if (!NT_STATUS_IS_OK(result)) {
1364                 cli_rpc_pipe_close(netlogon_pipe);
1365                 return result;
1366         }
1367
1368         if ((lp_client_schannel() == True) &&
1369                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1370                 DEBUG(3, ("Server did not offer schannel\n"));
1371                 cli_rpc_pipe_close(netlogon_pipe);
1372                 return NT_STATUS_ACCESS_DENIED;
1373         }
1374
1375         if ((lp_client_schannel() == False) ||
1376                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1377                 /* We're done - just keep the existing connection to NETLOGON
1378                  * open */
1379                 conn->netlogon_pipe = netlogon_pipe;
1380                 *cli = conn->netlogon_pipe;
1381                 return NT_STATUS_OK;
1382         }
1383
1384         /* Using the credentials from the first pipe, open a signed and sealed
1385            second netlogon pipe. The session key is stored in the schannel
1386            part of the new pipe auth struct.
1387         */
1388
1389         conn->netlogon_pipe =
1390                 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1391                                                     PI_NETLOGON,
1392                                                     PIPE_AUTH_LEVEL_PRIVACY,
1393                                                     domain->name,
1394                                                     netlogon_pipe->dc,
1395                                                     &result);
1396
1397         /* We can now close the initial netlogon pipe. */
1398         cli_rpc_pipe_close(netlogon_pipe);
1399
1400         if (conn->netlogon_pipe == NULL) {
1401                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1402                           "was %s\n", nt_errstr(result)));
1403                 return result;
1404         }
1405
1406         *cli = conn->netlogon_pipe;
1407         return NT_STATUS_OK;
1408 }