Initial import
[samba] / 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 = NULL;
105         struct rpc_pipe_client *netlogon_pipe = NULL;
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_prepare_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                           lp_workgroup(), machine_account));
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(
770                                             domain->name, domain->dcname)) &&
771                     (resolve_name(domain->dcname, &domain->dcaddr.sin_addr,
772                                   0x20))) {
773                         int dummy;
774                         struct sockaddr_in addrs[2];
775                         addrs[0] = domain->dcaddr;
776                         addrs[0].sin_port = htons(445);
777                         addrs[1] = domain->dcaddr;
778                         addrs[1].sin_port = htons(139);
779                         if (!open_any_socket_out(addrs, 2, 10000,
780                                                  &dummy, &fd)) {
781                                 fd = -1;
782                         }
783                 }
784
785                 if ((fd == -1) &&
786                     !find_new_dc(mem_ctx, domain, domain->dcname,
787                                  &domain->dcaddr, &fd))
788                         break;
789
790                 new_conn->cli = NULL;
791
792                 result = cm_prepare_connection(domain, fd, domain->dcname,
793                         &new_conn->cli, &retry);
794
795                 if (!retry)
796                         break;
797         }
798
799         talloc_destroy(mem_ctx);
800         return result;
801 }
802
803 /* Return true if a connection is still alive */
804
805 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
806 {
807         if (conn->samr_pipe != NULL) {
808                 cli_rpc_pipe_close(conn->samr_pipe);
809                 conn->samr_pipe = NULL;
810         }
811
812         if (conn->lsa_pipe != NULL) {
813                 cli_rpc_pipe_close(conn->lsa_pipe);
814                 conn->lsa_pipe = NULL;
815         }
816
817         if (conn->netlogon_pipe != NULL) {
818                 cli_rpc_pipe_close(conn->netlogon_pipe);
819                 conn->netlogon_pipe = NULL;
820         }
821
822         if (conn->cli) {
823                 cli_shutdown(conn->cli);
824         }
825
826         conn->cli = NULL;
827 }
828
829 void close_conns_after_fork(void)
830 {
831         struct winbindd_domain *domain;
832
833         for (domain = domain_list(); domain; domain = domain->next) {
834                 if (domain->conn.cli == NULL)
835                         continue;
836
837                 if (domain->conn.cli->fd == -1)
838                         continue;
839
840                 close(domain->conn.cli->fd);
841                 domain->conn.cli->fd = -1;
842         }
843 }
844
845 static BOOL connection_ok(struct winbindd_domain *domain)
846 {
847         if (domain->conn.cli == NULL) {
848                 DEBUG(8, ("Connection to %s for domain %s has NULL "
849                           "cli!\n", domain->dcname, domain->name));
850                 return False;
851         }
852
853         if (!domain->conn.cli->initialised) {
854                 DEBUG(3, ("Connection to %s for domain %s was never "
855                           "initialised!\n", domain->dcname, domain->name));
856                 return False;
857         }
858
859         if (domain->conn.cli->fd == -1) {
860                 DEBUG(3, ("Connection to %s for domain %s has died or was "
861                           "never started (fd == -1)\n", 
862                           domain->dcname, domain->name));
863                 return False;
864         }
865
866         return True;
867 }
868         
869 /* Initialize a new connection up to the RPC BIND. */
870
871 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
872 {
873         if (connection_ok(domain))
874                 return NT_STATUS_OK;
875
876         invalidate_cm_connection(&domain->conn);
877
878         return cm_open_connection(domain, &domain->conn);
879 }
880
881 /******************************************************************************
882  We can 'sense' certain things about the DC by it's replies to certain
883  questions.
884
885  This tells us if this particular remote server is Active Directory, and if it
886  is native mode.
887 ******************************************************************************/
888
889 void set_dc_type_and_flags( struct winbindd_domain *domain )
890 {
891         NTSTATUS                result;
892         DS_DOMINFO_CTR          ctr;
893         TALLOC_CTX              *mem_ctx = NULL;
894         struct rpc_pipe_client  *cli;
895         POLICY_HND pol;
896         
897         char *domain_name = NULL;
898         char *dns_name = NULL;
899         DOM_SID *dom_sid = NULL;
900
901         ZERO_STRUCT( ctr );
902         
903         domain->native_mode = False;
904         domain->active_directory = False;
905
906         if (domain->internal) {
907                 domain->initialized = True;
908                 return;
909         }
910
911         result = init_dc_connection(domain);
912         if (!NT_STATUS_IS_OK(result)) {
913                 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
914                           "to %s: (%s)\n", domain->name, nt_errstr(result)));
915                 domain->initialized = True;
916                 return;
917         }
918
919         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
920                                        &result);
921
922         if (cli == NULL) {
923                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
924                           "PI_LSARPC_DS on domain %s: (%s)\n",
925                           domain->name, nt_errstr(result)));
926                 domain->initialized = True;
927                 return;
928         }
929
930         result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
931                                              DsRolePrimaryDomainInfoBasic,
932                                              &ctr);
933         cli_rpc_pipe_close(cli);
934
935         if (!NT_STATUS_IS_OK(result)) {
936                 domain->initialized = True;
937                 return;
938         }
939         
940         if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
941             !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
942                 domain->native_mode = True;
943
944         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
945
946         if (cli == NULL) {
947                 domain->initialized = True;
948                 return;
949         }
950
951         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
952                               domain->name);
953         if (!mem_ctx) {
954                 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
955                 cli_rpc_pipe_close(cli);
956                 return;
957         }
958
959         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
960                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
961                 
962         if (NT_STATUS_IS_OK(result)) {
963                 /* This particular query is exactly what Win2k clients use 
964                    to determine that the DC is active directory */
965                 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
966                                                        12, &domain_name,
967                                                        &dns_name, NULL,
968                                                        NULL, &dom_sid);
969         }
970
971         if (NT_STATUS_IS_OK(result)) {
972                 if (domain_name)
973                         fstrcpy(domain->name, domain_name);
974
975                 if (dns_name)
976                         fstrcpy(domain->alt_name, dns_name);
977
978                 if (dom_sid) 
979                         sid_copy(&domain->sid, dom_sid);
980
981                 domain->active_directory = True;
982         } else {
983                 
984                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
985                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
986                                                 &pol);
987                         
988                 if (!NT_STATUS_IS_OK(result))
989                         goto done;
990                         
991                 result = rpccli_lsa_query_info_policy(cli, mem_ctx, 
992                                                       &pol, 5, &domain_name, 
993                                                       &dom_sid);
994                         
995                 if (NT_STATUS_IS_OK(result)) {
996                         if (domain_name)
997                                 fstrcpy(domain->name, domain_name);
998
999                         if (dom_sid) 
1000                                 sid_copy(&domain->sid, dom_sid);
1001                 }
1002         }
1003 done:
1004
1005         cli_rpc_pipe_close(cli);
1006         
1007         talloc_destroy(mem_ctx);
1008
1009         domain->initialized = True;
1010         
1011         return;
1012 }
1013
1014 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1015                                    struct dcinfo **ppdc)
1016 {
1017         NTSTATUS result;
1018         struct rpc_pipe_client *netlogon_pipe;
1019
1020         if (lp_client_schannel() == False) {
1021                 return False;
1022         }
1023
1024         result = cm_connect_netlogon(domain, &netlogon_pipe);
1025         if (!NT_STATUS_IS_OK(result)) {
1026                 return False;
1027         }
1028
1029         /* Return a pointer to the struct dcinfo from the
1030            netlogon pipe. */
1031
1032         *ppdc = domain->conn.netlogon_pipe->dc;
1033         return True;
1034 }
1035
1036 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1037                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1038 {
1039         struct winbindd_cm_conn *conn;
1040         NTSTATUS result;
1041         fstring conn_pwd;
1042         struct dcinfo *p_dcinfo;
1043
1044         result = init_dc_connection(domain);
1045         if (!NT_STATUS_IS_OK(result)) {
1046                 return result;
1047         }
1048
1049         conn = &domain->conn;
1050
1051         if (conn->samr_pipe != NULL) {
1052                 goto done;
1053         }
1054
1055         /*
1056          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1057          * sign and sealed pipe using the machine account password by
1058          * preference. If we can't - try schannel, if that fails, try
1059          * anonymous.
1060          */
1061
1062         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1063         if ((conn->cli->user_name[0] == '\0') ||
1064             (conn->cli->domain[0] == '\0') || 
1065             (conn_pwd[0] == '\0')) {
1066                 DEBUG(10, ("cm_connect_sam: No no user available for "
1067                            "domain %s, trying schannel\n", conn->cli->domain));
1068                 goto schannel;
1069         }
1070
1071         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1072            authenticated SAMR pipe with sign & seal. */
1073         conn->samr_pipe =
1074                 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1075                                                  PIPE_AUTH_LEVEL_PRIVACY,
1076                                                  conn->cli->domain,
1077                                                  conn->cli->user_name,
1078                                                  conn_pwd, &result);
1079
1080         if (conn->samr_pipe == NULL) {
1081                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1082                           "pipe for domain %s using NTLMSSP "
1083                           "authenticated pipe: user %s\\%s. Error was "
1084                           "%s\n", domain->name, conn->cli->domain,
1085                           conn->cli->user_name, nt_errstr(result)));
1086                 goto schannel;
1087         }
1088
1089         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1090                   "domain %s using NTLMSSP authenticated "
1091                   "pipe: user %s\\%s\n", domain->name,
1092                   conn->cli->domain, conn->cli->user_name ));
1093
1094         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1095                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1096                                      &conn->sam_connect_handle);
1097         if (NT_STATUS_IS_OK(result)) {
1098                 goto open_domain;
1099         }
1100         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1101                   "failed for domain %s, error was %s. Trying schannel\n",
1102                   domain->name, nt_errstr(result) ));
1103         cli_rpc_pipe_close(conn->samr_pipe);
1104
1105  schannel:
1106
1107         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1108
1109         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1110                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1111                            "for domain %s, trying anon\n", conn->cli->domain));
1112                 goto anonymous;
1113         }
1114         conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1115                 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1116                  domain->name, p_dcinfo, &result);
1117
1118         if (conn->samr_pipe == NULL) {
1119                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1120                           "domain %s using schannel. Error was %s\n",
1121                           domain->name, nt_errstr(result) ));
1122                 goto anonymous;
1123         }
1124         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1125                   "schannel.\n", domain->name ));
1126
1127         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1128                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1129                                      &conn->sam_connect_handle);
1130         if (NT_STATUS_IS_OK(result)) {
1131                 goto open_domain;
1132         }
1133         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1134                   "for domain %s, error was %s. Trying anonymous\n",
1135                   domain->name, nt_errstr(result) ));
1136         cli_rpc_pipe_close(conn->samr_pipe);
1137
1138  anonymous:
1139
1140         /* Finally fall back to anonymous. */
1141         conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1142                                                    &result);
1143
1144         if (conn->samr_pipe == NULL) {
1145                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1146                 goto done;
1147         }
1148
1149         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1150                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1151                                      &conn->sam_connect_handle);
1152         if (!NT_STATUS_IS_OK(result)) {
1153                 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1154                           "for domain %s Error was %s\n",
1155                           domain->name, nt_errstr(result) ));
1156                 goto done;
1157         }
1158
1159  open_domain:
1160         result = rpccli_samr_open_domain(conn->samr_pipe,
1161                                          mem_ctx,
1162                                          &conn->sam_connect_handle,
1163                                          SEC_RIGHTS_MAXIMUM_ALLOWED,
1164                                          &domain->sid,
1165                                          &conn->sam_domain_handle);
1166
1167  done:
1168
1169         if (!NT_STATUS_IS_OK(result)) {
1170                 invalidate_cm_connection(conn);
1171                 return result;
1172         }
1173
1174         *cli = conn->samr_pipe;
1175         *sam_handle = conn->sam_domain_handle;
1176         return result;
1177 }
1178
1179 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1180                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1181 {
1182         struct winbindd_cm_conn *conn;
1183         NTSTATUS result;
1184         fstring conn_pwd;
1185         struct dcinfo *p_dcinfo;
1186
1187         result = init_dc_connection(domain);
1188         if (!NT_STATUS_IS_OK(result))
1189                 return result;
1190
1191         conn = &domain->conn;
1192
1193         if (conn->lsa_pipe != NULL) {
1194                 goto done;
1195         }
1196
1197         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1198         if ((conn->cli->user_name[0] == '\0') ||
1199             (conn->cli->domain[0] == '\0') || 
1200             (conn_pwd[0] == '\0')) {
1201                 DEBUG(10, ("cm_connect_lsa: No no user available for "
1202                            "domain %s, trying schannel\n", conn->cli->domain));
1203                 goto schannel;
1204         }
1205
1206         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1207          * authenticated LSA pipe with sign & seal. */
1208         conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1209                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1210                  conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1211
1212         if (conn->lsa_pipe == NULL) {
1213                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1214                           "domain %s using NTLMSSP authenticated pipe: user "
1215                           "%s\\%s. Error was %s. Trying schannel.\n",
1216                           domain->name, conn->cli->domain,
1217                           conn->cli->user_name, nt_errstr(result)));
1218                 goto schannel;
1219         }
1220
1221         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1222                   "NTLMSSP authenticated pipe: user %s\\%s\n",
1223                   domain->name, conn->cli->domain, conn->cli->user_name ));
1224
1225         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1226                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1227                                         &conn->lsa_policy);
1228         if (NT_STATUS_IS_OK(result)) {
1229                 goto done;
1230         }
1231
1232         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1233                   "schannel\n"));
1234
1235         cli_rpc_pipe_close(conn->lsa_pipe);
1236
1237  schannel:
1238
1239         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1240
1241         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1242                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1243                            "for domain %s, trying anon\n", conn->cli->domain));
1244                 goto anonymous;
1245         }
1246         conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1247                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1248                  domain->name, p_dcinfo, &result);
1249
1250         if (conn->lsa_pipe == NULL) {
1251                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1252                           "domain %s using schannel. Error was %s\n",
1253                           domain->name, nt_errstr(result) ));
1254                 goto anonymous;
1255         }
1256         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1257                   "schannel.\n", domain->name ));
1258
1259         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1260                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1261                                         &conn->lsa_policy);
1262         if (NT_STATUS_IS_OK(result)) {
1263                 goto done;
1264         }
1265
1266         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1267                   "anonymous\n"));
1268
1269         cli_rpc_pipe_close(conn->lsa_pipe);
1270
1271  anonymous:
1272
1273         conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1274                                                   &result);
1275         if (conn->lsa_pipe == NULL) {
1276                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1277                 goto done;
1278         }
1279
1280         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1281                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1282                                         &conn->lsa_policy);
1283  done:
1284         if (!NT_STATUS_IS_OK(result)) {
1285                 invalidate_cm_connection(conn);
1286                 return NT_STATUS_UNSUCCESSFUL;
1287         }
1288
1289         *cli = conn->lsa_pipe;
1290         *lsa_policy = conn->lsa_policy;
1291         return result;
1292 }
1293
1294 /****************************************************************************
1295  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1296  session key stored in conn->netlogon_pipe->dc->sess_key.
1297 ****************************************************************************/
1298
1299 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1300                              struct rpc_pipe_client **cli)
1301 {
1302         struct winbindd_cm_conn *conn;
1303         NTSTATUS result;
1304
1305         uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1306         uint8  mach_pwd[16];
1307         uint32  sec_chan_type;
1308         const char *account_name;
1309         struct rpc_pipe_client *netlogon_pipe = NULL;
1310
1311         *cli = NULL;
1312
1313         result = init_dc_connection(domain);
1314         if (!NT_STATUS_IS_OK(result)) {
1315                 return result;
1316         }
1317
1318         conn = &domain->conn;
1319
1320         if (conn->netlogon_pipe != NULL) {
1321                 *cli = conn->netlogon_pipe;
1322                 return NT_STATUS_OK;
1323         }
1324
1325         if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1326                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1327         }
1328
1329         netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1330                                                  &result);
1331         if (netlogon_pipe == NULL) {
1332                 return result;
1333         }
1334
1335         if (lp_client_schannel() != False) {
1336                 neg_flags |= NETLOGON_NEG_SCHANNEL;
1337         }
1338
1339         /* if we are a DC and this is a trusted domain, then we need to use our
1340            domain name in the net_req_auth2() request */
1341
1342         if ( IS_DC
1343                 && !strequal(domain->name, lp_workgroup())
1344                 && lp_allow_trusted_domains() ) 
1345         {
1346                 account_name = lp_workgroup();
1347         } else {
1348                 account_name = domain->primary ?
1349                         global_myname() : domain->name;
1350         }
1351
1352         if (account_name == NULL) {
1353                 cli_rpc_pipe_close(netlogon_pipe);
1354                 return NT_STATUS_NO_MEMORY;
1355         }
1356
1357         result = rpccli_netlogon_setup_creds(
1358                  netlogon_pipe,
1359                  domain->dcname, /* server name. */
1360                  domain->name,   /* domain name */
1361                  global_myname(), /* client name */
1362                  account_name,   /* machine account */
1363                  mach_pwd,       /* machine password */
1364                  sec_chan_type,  /* from get_trust_pw */
1365                  &neg_flags);
1366
1367         if (!NT_STATUS_IS_OK(result)) {
1368                 cli_rpc_pipe_close(netlogon_pipe);
1369                 return result;
1370         }
1371
1372         if ((lp_client_schannel() == True) &&
1373                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1374                 DEBUG(3, ("Server did not offer schannel\n"));
1375                 cli_rpc_pipe_close(netlogon_pipe);
1376                 return NT_STATUS_ACCESS_DENIED;
1377         }
1378
1379         if ((lp_client_schannel() == False) ||
1380                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1381                 /* We're done - just keep the existing connection to NETLOGON
1382                  * open */
1383                 conn->netlogon_pipe = netlogon_pipe;
1384                 *cli = conn->netlogon_pipe;
1385                 return NT_STATUS_OK;
1386         }
1387
1388         /* Using the credentials from the first pipe, open a signed and sealed
1389            second netlogon pipe. The session key is stored in the schannel
1390            part of the new pipe auth struct.
1391         */
1392
1393         conn->netlogon_pipe =
1394                 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1395                                                     PI_NETLOGON,
1396                                                     PIPE_AUTH_LEVEL_PRIVACY,
1397                                                     domain->name,
1398                                                     netlogon_pipe->dc,
1399                                                     &result);
1400
1401         /* We can now close the initial netlogon pipe. */
1402         cli_rpc_pipe_close(netlogon_pipe);
1403
1404         if (conn->netlogon_pipe == NULL) {
1405                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1406                           "was %s\n", nt_errstr(result)));
1407                 return result;
1408         }
1409
1410         *cli = conn->netlogon_pipe;
1411         return NT_STATUS_OK;
1412 }