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