r13316: Let the carnage begin....
[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 = 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                           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         /* cache the server name for later connections */
362
363         saf_store( (*cli)->domain, (*cli)->desthost );
364
365         if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
366
367                 result = cli_nt_error(*cli);
368
369                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
370
371                 if (NT_STATUS_IS_OK(result))
372                         result = NT_STATUS_UNSUCCESSFUL;
373
374                 cli_shutdown(*cli);
375                 goto done;
376         }
377
378         secrets_named_mutex_release(controller);
379         got_mutex = False;
380         *retry = False;
381
382         /* set the domain if empty; needed for schannel connections */
383         if ( !*(*cli)->domain ) {
384                 fstrcpy( (*cli)->domain, domain->name );
385         }
386
387         result = NT_STATUS_OK;
388         add_failed_connection = False;
389
390  done:
391         if (got_mutex) {
392                 secrets_named_mutex_release(controller);
393         }
394
395         SAFE_FREE(machine_account);
396         SAFE_FREE(machine_password);
397         SAFE_FREE(machine_krb5_principal);
398         SAFE_FREE(ipc_username);
399         SAFE_FREE(ipc_domain);
400         SAFE_FREE(ipc_password);
401
402         if (add_failed_connection) {
403                 add_failed_connection_entry(domain->name, controller, result);
404         }
405
406         return result;
407 }
408
409 struct dc_name_ip {
410         fstring name;
411         struct in_addr ip;
412 };
413
414 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
415                               const char *dcname, struct in_addr ip,
416                               struct dc_name_ip **dcs, int *num)
417 {
418         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
419                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
420                 return False;
421         }
422
423         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
424
425         if (*dcs == NULL)
426                 return False;
427
428         fstrcpy((*dcs)[*num].name, dcname);
429         (*dcs)[*num].ip = ip;
430         *num += 1;
431         return True;
432 }
433
434 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
435                                   struct in_addr ip, uint16 port,
436                                   struct sockaddr_in **addrs, int *num)
437 {
438         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
439
440         if (*addrs == NULL)
441                 return False;
442
443         (*addrs)[*num].sin_family = PF_INET;
444         putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
445         (*addrs)[*num].sin_port = htons(port);
446
447         *num += 1;
448         return True;
449 }
450
451 static void mailslot_name(struct in_addr dc_ip, fstring name)
452 {
453         fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
454 }
455
456 static BOOL send_getdc_request(struct in_addr dc_ip,
457                                const char *domain_name,
458                                const DOM_SID *sid)
459 {
460         pstring outbuf;
461         char *p;
462         fstring my_acct_name;
463         fstring my_mailslot;
464
465         mailslot_name(dc_ip, my_mailslot);
466
467         memset(outbuf, '\0', sizeof(outbuf));
468
469         p = outbuf;
470
471         SCVAL(p, 0, SAMLOGON);
472         p++;
473
474         SCVAL(p, 0, 0); /* Count pointer ... */
475         p++;
476
477         SIVAL(p, 0, 0); /* The sender's token ... */
478         p += 2;
479
480         p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
481         fstr_sprintf(my_acct_name, "%s$", global_myname());
482         p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
483
484         memcpy(p, my_mailslot, strlen(my_mailslot)+1);
485         p += strlen(my_mailslot)+1;
486
487         SIVAL(p, 0, 0x80);
488         p+=4;
489
490         SIVAL(p, 0, sid_size(sid));
491         p+=4;
492
493         p = ALIGN4(p, outbuf);
494
495         sid_linearize(p, sid_size(sid), sid);
496         p += sid_size(sid);
497
498         SIVAL(p, 0, 1);
499         SSVAL(p, 4, 0xffff);
500         SSVAL(p, 6, 0xffff);
501         p+=8;
502
503         return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
504                                  outbuf, PTR_DIFF(p, outbuf),
505                                  global_myname(), 0, domain_name, 0x1c,
506                                  dc_ip);
507 }
508
509 static BOOL receive_getdc_response(struct in_addr dc_ip,
510                                    const char *domain_name,
511                                    fstring dc_name)
512 {
513         struct packet_struct *packet;
514         fstring my_mailslot;
515         char *buf, *p;
516         fstring dcname, user, domain;
517         int len;
518
519         mailslot_name(dc_ip, my_mailslot);
520
521         packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
522
523         if (packet == NULL) {
524                 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
525                 return False;
526         }
527
528         DEBUG(5, ("Received packet for %s\n", my_mailslot));
529
530         buf = packet->packet.dgram.data;
531         len = packet->packet.dgram.datasize;
532
533         if (len < 70) {
534                 /* 70 is a completely arbitrary value to make sure
535                    the SVAL below does not read uninitialized memory */
536                 DEBUG(3, ("GetDC got short response\n"));
537                 return False;
538         }
539
540         /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
541         p = buf+SVAL(buf, smb_vwv10);
542
543         if (CVAL(p,0) != SAMLOGON_R) {
544                 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
545                 return False;
546         }
547
548         p+=2;
549         pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
550                   STR_TERMINATE|STR_NOALIGN);
551         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
552         pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
553                   STR_TERMINATE|STR_NOALIGN);
554         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
555         pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
556                   STR_TERMINATE|STR_NOALIGN);
557         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
558
559         if (!strequal(domain, domain_name)) {
560                 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
561                           domain_name, domain));
562                 return False;
563         }
564
565         p = dcname;
566         if (*p == '\\') p += 1;
567         if (*p == '\\') p += 1;
568
569         fstrcpy(dc_name, p);
570
571         DEBUG(10, ("GetDC gave name %s for domain %s\n",
572                    dc_name, domain));
573
574         return True;
575 }
576
577 /*******************************************************************
578  convert an ip to a name
579 *******************************************************************/
580
581 static void dcip_to_name( const char *domainname, const char *realm, 
582                           const DOM_SID *sid, struct in_addr ip, fstring name )
583 {
584
585         /* try GETDC requests first */
586         
587         if (send_getdc_request(ip, domainname, sid)) {
588                 int i;
589                 smb_msleep(100);
590                 for (i=0; i<5; i++) {
591                         if (receive_getdc_response(ip, domainname, name))
592                                 return;
593                         smb_msleep(500);
594                 }
595         }
596
597         /* try node status request */
598
599         if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
600                 return;
601
602         /* backup in case the netbios stuff fails */
603
604         fstrcpy( name, inet_ntoa(ip) );
605
606 #ifdef WITH_ADS
607         /* for active directory servers, try to get the ldap server name.
608            None of these failure should be considered critical for now */
609
610         if ( lp_security() == SEC_ADS ) 
611         {
612                 ADS_STRUCT *ads;
613                 ADS_STATUS status;
614
615                 ads = ads_init( realm, domainname, NULL );
616                 ads->auth.flags |= ADS_AUTH_NO_BIND;
617
618                 if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) )  {
619                         ads_destroy( &ads );
620                         return;
621                 }
622
623                 status = ads_server_info(ads);
624                 if ( !ADS_ERR_OK(status) ) {
625                         ads_destroy( &ads );
626                         return;
627                 }
628
629                 fstrcpy(name, ads->config.ldap_server_name);
630
631                 ads_destroy( &ads );
632         }
633 #endif
634
635         return;
636 }
637
638 /*******************************************************************
639  Retreive a list of IP address for domain controllers.  Fill in 
640  the dcs[]  with results.
641 *******************************************************************/
642
643 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
644                     struct dc_name_ip **dcs, int *num_dcs)
645 {
646         fstring dcname;
647         struct  in_addr ip;
648         struct  ip_service *ip_list = NULL;
649         int     iplist_size = 0;
650         int     i;
651         BOOL    is_our_domain;
652
653
654         is_our_domain = strequal(domain->name, lp_workgroup());
655
656         if ( !is_our_domain 
657                 && get_dc_name_via_netlogon(domain, dcname, &ip) 
658                 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
659         {
660                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
661                            dcname, inet_ntoa(ip)));
662                 return True;
663         }
664
665         /* try standard netbios queries first */
666
667         get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
668
669         /* check for security = ads and use DNS if we can */
670
671         if ( iplist_size==0 && lp_security() == SEC_ADS ) 
672                 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
673
674         /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
675
676         /* now add to the dc array.  We'll wait until the last minute 
677            to look up the name of the DC.  But we fill in the char* for 
678            the ip now in to make the failed connection cache work */
679
680         for ( i=0; i<iplist_size; i++ ) {
681                 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip), 
682                         ip_list[i].ip, dcs, num_dcs);
683         }
684
685         SAFE_FREE( ip_list );
686
687         return True;
688 }
689
690 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
691                         const struct winbindd_domain *domain,
692                         fstring dcname, struct sockaddr_in *addr, int *fd)
693 {
694         struct dc_name_ip *dcs = NULL;
695         int num_dcs = 0;
696
697         const char **dcnames = NULL;
698         int num_dcnames = 0;
699
700         struct sockaddr_in *addrs = NULL;
701         int num_addrs = 0;
702
703         int i, fd_index;
704
705         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
706                 return False;
707
708         for (i=0; i<num_dcs; i++) {
709
710                 add_string_to_array(mem_ctx, dcs[i].name,
711                                     &dcnames, &num_dcnames);
712                 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
713                                       &addrs, &num_addrs);
714
715                 add_string_to_array(mem_ctx, dcs[i].name,
716                                     &dcnames, &num_dcnames);
717                 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
718                                       &addrs, &num_addrs);
719         }
720
721         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
722                 return False;
723
724         if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) ) 
725         {
726                 for (i=0; i<num_dcs; i++) {
727                         add_failed_connection_entry(domain->name,
728                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
729                 }
730                 return False;
731         }
732
733         *addr = addrs[fd_index];
734
735         /* if we have no name on the server or just an IP address for 
736            the name, now try to get the name */
737
738         if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
739                 dcip_to_name( domain->name, domain->alt_name, &domain->sid, addr->sin_addr, dcname );
740         else
741                 fstrcpy(dcname, dcnames[fd_index]);
742
743         return True;
744 }
745
746 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
747                                    struct winbindd_cm_conn *new_conn)
748 {
749         TALLOC_CTX *mem_ctx;
750         NTSTATUS result;
751         char *saf_servername = saf_fetch( domain->name );
752         int retries;
753
754         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
755                 return NT_STATUS_NO_MEMORY;
756
757         /* we have to check the server affinity cache here since 
758            later we selecte a DC based on response time and not preference */
759            
760         if ( saf_servername ) 
761         {
762                 /* convert an ip address to a name */
763                 if ( is_ipaddress( saf_servername ) )
764                 {
765                         fstring saf_name;
766                         struct in_addr ip;
767
768                         ip = *interpret_addr2( saf_servername );
769                         dcip_to_name( domain->name, domain->alt_name, &domain->sid, ip, saf_name );
770                         fstrcpy( domain->dcname, saf_name );
771                 } 
772                 else 
773                 {
774                         fstrcpy( domain->dcname, saf_servername );
775                 }
776
777                 SAFE_FREE( saf_servername );
778         }
779
780         for (retries = 0; retries < 3; retries++) {
781
782                 int fd = -1;
783                 BOOL retry = False;
784
785                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
786
787                 if ((strlen(domain->dcname) > 0)
788                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
789                         && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
790                 {
791                         struct sockaddr_in *addrs = NULL;
792                         int num_addrs = 0;
793                         int dummy = 0;
794
795                         add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
796                         add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
797
798                         if (!open_any_socket_out(addrs, num_addrs, 10000, &dummy, &fd)) {
799                                 domain->online = False;
800                                 fd = -1;
801                         }
802                 }
803
804                 if ((fd == -1) 
805                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
806                 {
807                         /* This is the one place where we will
808                            set the global winbindd offline state
809                            to true, if a "WINBINDD_OFFLINE" entry
810                            is found in the winbindd cache. */
811                         set_global_winbindd_state_offline();
812                         domain->online = False;
813                         break;
814                 }
815
816                 new_conn->cli = NULL;
817
818                 result = cm_prepare_connection(domain, fd, domain->dcname,
819                         &new_conn->cli, &retry);
820
821                 if (!retry)
822                         break;
823         }
824
825         if (NT_STATUS_IS_OK(result)) {
826                 if (domain->online == False) {
827                         /* We're changing state from offline to online. */
828                         set_global_winbindd_state_online();
829                 }
830                 domain->online = True;
831         }
832
833         talloc_destroy(mem_ctx);
834         return result;
835 }
836
837 /* Close down all open pipes on a connection. */
838
839 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
840 {
841         if (conn->samr_pipe != NULL) {
842                 cli_rpc_pipe_close(conn->samr_pipe);
843                 conn->samr_pipe = NULL;
844         }
845
846         if (conn->lsa_pipe != NULL) {
847                 cli_rpc_pipe_close(conn->lsa_pipe);
848                 conn->lsa_pipe = NULL;
849         }
850
851         if (conn->netlogon_pipe != NULL) {
852                 cli_rpc_pipe_close(conn->netlogon_pipe);
853                 conn->netlogon_pipe = NULL;
854         }
855
856         if (conn->cli) {
857                 cli_shutdown(conn->cli);
858         }
859
860         conn->cli = NULL;
861 }
862
863 void close_conns_after_fork(void)
864 {
865         struct winbindd_domain *domain;
866
867         for (domain = domain_list(); domain; domain = domain->next) {
868                 if (domain->conn.cli == NULL)
869                         continue;
870
871                 if (domain->conn.cli->fd == -1)
872                         continue;
873
874                 close(domain->conn.cli->fd);
875                 domain->conn.cli->fd = -1;
876         }
877 }
878
879 static BOOL connection_ok(struct winbindd_domain *domain)
880 {
881         if (domain->conn.cli == NULL) {
882                 DEBUG(8, ("Connection to %s for domain %s has NULL "
883                           "cli!\n", domain->dcname, domain->name));
884                 return False;
885         }
886
887         if (!domain->conn.cli->initialised) {
888                 DEBUG(3, ("Connection to %s for domain %s was never "
889                           "initialised!\n", domain->dcname, domain->name));
890                 return False;
891         }
892
893         if (domain->conn.cli->fd == -1) {
894                 DEBUG(3, ("Connection to %s for domain %s has died or was "
895                           "never started (fd == -1)\n", 
896                           domain->dcname, domain->name));
897                 return False;
898         }
899
900         return True;
901 }
902         
903 /* Initialize a new connection up to the RPC BIND. */
904
905 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
906 {
907         if (connection_ok(domain))
908                 return NT_STATUS_OK;
909
910         invalidate_cm_connection(&domain->conn);
911
912         return cm_open_connection(domain, &domain->conn);
913 }
914
915 /******************************************************************************
916  We can 'sense' certain things about the DC by it's replies to certain
917  questions.
918
919  This tells us if this particular remote server is Active Directory, and if it
920  is native mode.
921 ******************************************************************************/
922
923 void set_dc_type_and_flags( struct winbindd_domain *domain )
924 {
925         NTSTATUS                result;
926         DS_DOMINFO_CTR          ctr;
927         TALLOC_CTX              *mem_ctx = NULL;
928         struct rpc_pipe_client  *cli;
929         POLICY_HND pol;
930         
931         char *domain_name = NULL;
932         char *dns_name = NULL;
933         DOM_SID *dom_sid = NULL;
934
935         ZERO_STRUCT( ctr );
936         
937         domain->native_mode = False;
938         domain->active_directory = False;
939
940         if (domain->internal) {
941                 domain->initialized = True;
942                 return;
943         }
944
945         result = init_dc_connection(domain);
946         if (!NT_STATUS_IS_OK(result)) {
947                 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
948                           "to %s: (%s)\n", domain->name, nt_errstr(result)));
949                 domain->initialized = True;
950                 return;
951         }
952
953         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
954                                        &result);
955
956         if (cli == NULL) {
957                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
958                           "PI_LSARPC_DS on domain %s: (%s)\n",
959                           domain->name, nt_errstr(result)));
960                 domain->initialized = True;
961                 return;
962         }
963
964         result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
965                                              DsRolePrimaryDomainInfoBasic,
966                                              &ctr);
967         cli_rpc_pipe_close(cli);
968
969         if (!NT_STATUS_IS_OK(result)) {
970                 domain->initialized = True;
971                 return;
972         }
973         
974         if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
975             !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
976                 domain->native_mode = True;
977
978         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
979
980         if (cli == NULL) {
981                 domain->initialized = True;
982                 return;
983         }
984
985         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
986                               domain->name);
987         if (!mem_ctx) {
988                 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
989                 cli_rpc_pipe_close(cli);
990                 return;
991         }
992
993         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
994                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
995                 
996         if (NT_STATUS_IS_OK(result)) {
997                 /* This particular query is exactly what Win2k clients use 
998                    to determine that the DC is active directory */
999                 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1000                                                        12, &domain_name,
1001                                                        &dns_name, NULL,
1002                                                        NULL, &dom_sid);
1003         }
1004
1005         if (NT_STATUS_IS_OK(result)) {
1006                 if (domain_name)
1007                         fstrcpy(domain->name, domain_name);
1008
1009                 if (dns_name)
1010                         fstrcpy(domain->alt_name, dns_name);
1011
1012                 if (dom_sid) 
1013                         sid_copy(&domain->sid, dom_sid);
1014
1015                 domain->active_directory = True;
1016         } else {
1017                 
1018                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1019                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1020                                                 &pol);
1021                         
1022                 if (!NT_STATUS_IS_OK(result))
1023                         goto done;
1024                         
1025                 result = rpccli_lsa_query_info_policy(cli, mem_ctx, 
1026                                                       &pol, 5, &domain_name, 
1027                                                       &dom_sid);
1028                         
1029                 if (NT_STATUS_IS_OK(result)) {
1030                         if (domain_name)
1031                                 fstrcpy(domain->name, domain_name);
1032
1033                         if (dom_sid) 
1034                                 sid_copy(&domain->sid, dom_sid);
1035                 }
1036         }
1037 done:
1038
1039         cli_rpc_pipe_close(cli);
1040         
1041         talloc_destroy(mem_ctx);
1042
1043         domain->initialized = True;
1044         
1045         return;
1046 }
1047
1048 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1049                                    struct dcinfo **ppdc)
1050 {
1051         NTSTATUS result;
1052         struct rpc_pipe_client *netlogon_pipe;
1053
1054         if (lp_client_schannel() == False) {
1055                 return False;
1056         }
1057
1058         result = cm_connect_netlogon(domain, &netlogon_pipe);
1059         if (!NT_STATUS_IS_OK(result)) {
1060                 return False;
1061         }
1062
1063         /* Return a pointer to the struct dcinfo from the
1064            netlogon pipe. */
1065
1066         *ppdc = domain->conn.netlogon_pipe->dc;
1067         return True;
1068 }
1069
1070 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1071                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1072 {
1073         struct winbindd_cm_conn *conn;
1074         NTSTATUS result;
1075         fstring conn_pwd;
1076         struct dcinfo *p_dcinfo;
1077
1078         result = init_dc_connection(domain);
1079         if (!NT_STATUS_IS_OK(result)) {
1080                 return result;
1081         }
1082
1083         conn = &domain->conn;
1084
1085         if (conn->samr_pipe != NULL) {
1086                 goto done;
1087         }
1088
1089         /*
1090          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1091          * sign and sealed pipe using the machine account password by
1092          * preference. If we can't - try schannel, if that fails, try
1093          * anonymous.
1094          */
1095
1096         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1097         if ((conn->cli->user_name[0] == '\0') ||
1098             (conn->cli->domain[0] == '\0') || 
1099             (conn_pwd[0] == '\0')) {
1100                 DEBUG(10, ("cm_connect_sam: No no user available for "
1101                            "domain %s, trying schannel\n", conn->cli->domain));
1102                 goto schannel;
1103         }
1104
1105         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1106            authenticated SAMR pipe with sign & seal. */
1107         conn->samr_pipe =
1108                 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1109                                                  PIPE_AUTH_LEVEL_PRIVACY,
1110                                                  conn->cli->domain,
1111                                                  conn->cli->user_name,
1112                                                  conn_pwd, &result);
1113
1114         if (conn->samr_pipe == NULL) {
1115                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1116                           "pipe for domain %s using NTLMSSP "
1117                           "authenticated pipe: user %s\\%s. Error was "
1118                           "%s\n", domain->name, conn->cli->domain,
1119                           conn->cli->user_name, nt_errstr(result)));
1120                 goto schannel;
1121         }
1122
1123         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1124                   "domain %s using NTLMSSP authenticated "
1125                   "pipe: user %s\\%s\n", domain->name,
1126                   conn->cli->domain, conn->cli->user_name ));
1127
1128         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1129                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1130                                      &conn->sam_connect_handle);
1131         if (NT_STATUS_IS_OK(result)) {
1132                 goto open_domain;
1133         }
1134         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1135                   "failed for domain %s, error was %s. Trying schannel\n",
1136                   domain->name, nt_errstr(result) ));
1137         cli_rpc_pipe_close(conn->samr_pipe);
1138
1139  schannel:
1140
1141         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1142
1143         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1144                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1145                            "for domain %s, trying anon\n", conn->cli->domain));
1146                 goto anonymous;
1147         }
1148         conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1149                 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1150                  domain->name, p_dcinfo, &result);
1151
1152         if (conn->samr_pipe == NULL) {
1153                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1154                           "domain %s using schannel. Error was %s\n",
1155                           domain->name, nt_errstr(result) ));
1156                 goto anonymous;
1157         }
1158         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1159                   "schannel.\n", domain->name ));
1160
1161         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1162                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1163                                      &conn->sam_connect_handle);
1164         if (NT_STATUS_IS_OK(result)) {
1165                 goto open_domain;
1166         }
1167         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1168                   "for domain %s, error was %s. Trying anonymous\n",
1169                   domain->name, nt_errstr(result) ));
1170         cli_rpc_pipe_close(conn->samr_pipe);
1171
1172  anonymous:
1173
1174         /* Finally fall back to anonymous. */
1175         conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1176                                                    &result);
1177
1178         if (conn->samr_pipe == NULL) {
1179                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1180                 goto done;
1181         }
1182
1183         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1184                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1185                                      &conn->sam_connect_handle);
1186         if (!NT_STATUS_IS_OK(result)) {
1187                 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1188                           "for domain %s Error was %s\n",
1189                           domain->name, nt_errstr(result) ));
1190                 goto done;
1191         }
1192
1193  open_domain:
1194         result = rpccli_samr_open_domain(conn->samr_pipe,
1195                                          mem_ctx,
1196                                          &conn->sam_connect_handle,
1197                                          SEC_RIGHTS_MAXIMUM_ALLOWED,
1198                                          &domain->sid,
1199                                          &conn->sam_domain_handle);
1200
1201  done:
1202
1203         if (!NT_STATUS_IS_OK(result)) {
1204                 invalidate_cm_connection(conn);
1205                 return result;
1206         }
1207
1208         *cli = conn->samr_pipe;
1209         *sam_handle = conn->sam_domain_handle;
1210         return result;
1211 }
1212
1213 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1214                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1215 {
1216         struct winbindd_cm_conn *conn;
1217         NTSTATUS result;
1218         fstring conn_pwd;
1219         struct dcinfo *p_dcinfo;
1220
1221         result = init_dc_connection(domain);
1222         if (!NT_STATUS_IS_OK(result))
1223                 return result;
1224
1225         conn = &domain->conn;
1226
1227         if (conn->lsa_pipe != NULL) {
1228                 goto done;
1229         }
1230
1231         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1232         if ((conn->cli->user_name[0] == '\0') ||
1233             (conn->cli->domain[0] == '\0') || 
1234             (conn_pwd[0] == '\0')) {
1235                 DEBUG(10, ("cm_connect_lsa: No no user available for "
1236                            "domain %s, trying schannel\n", conn->cli->domain));
1237                 goto schannel;
1238         }
1239
1240         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1241          * authenticated LSA pipe with sign & seal. */
1242         conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1243                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1244                  conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1245
1246         if (conn->lsa_pipe == NULL) {
1247                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1248                           "domain %s using NTLMSSP authenticated pipe: user "
1249                           "%s\\%s. Error was %s. Trying schannel.\n",
1250                           domain->name, conn->cli->domain,
1251                           conn->cli->user_name, nt_errstr(result)));
1252                 goto schannel;
1253         }
1254
1255         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1256                   "NTLMSSP authenticated pipe: user %s\\%s\n",
1257                   domain->name, conn->cli->domain, conn->cli->user_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                   "schannel\n"));
1268
1269         cli_rpc_pipe_close(conn->lsa_pipe);
1270
1271  schannel:
1272
1273         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1274
1275         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1276                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1277                            "for domain %s, trying anon\n", conn->cli->domain));
1278                 goto anonymous;
1279         }
1280         conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1281                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1282                  domain->name, p_dcinfo, &result);
1283
1284         if (conn->lsa_pipe == NULL) {
1285                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1286                           "domain %s using schannel. Error was %s\n",
1287                           domain->name, nt_errstr(result) ));
1288                 goto anonymous;
1289         }
1290         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1291                   "schannel.\n", domain->name ));
1292
1293         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1294                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1295                                         &conn->lsa_policy);
1296         if (NT_STATUS_IS_OK(result)) {
1297                 goto done;
1298         }
1299
1300         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1301                   "anonymous\n"));
1302
1303         cli_rpc_pipe_close(conn->lsa_pipe);
1304
1305  anonymous:
1306
1307         conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1308                                                   &result);
1309         if (conn->lsa_pipe == NULL) {
1310                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1311                 goto done;
1312         }
1313
1314         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1315                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1316                                         &conn->lsa_policy);
1317  done:
1318         if (!NT_STATUS_IS_OK(result)) {
1319                 invalidate_cm_connection(conn);
1320                 return NT_STATUS_UNSUCCESSFUL;
1321         }
1322
1323         *cli = conn->lsa_pipe;
1324         *lsa_policy = conn->lsa_policy;
1325         return result;
1326 }
1327
1328 /****************************************************************************
1329  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1330  session key stored in conn->netlogon_pipe->dc->sess_key.
1331 ****************************************************************************/
1332
1333 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1334                              struct rpc_pipe_client **cli)
1335 {
1336         struct winbindd_cm_conn *conn;
1337         NTSTATUS result;
1338
1339         uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1340         uint8  mach_pwd[16];
1341         uint32  sec_chan_type;
1342         const char *account_name;
1343         struct rpc_pipe_client *netlogon_pipe = NULL;
1344
1345         *cli = NULL;
1346
1347         result = init_dc_connection(domain);
1348         if (!NT_STATUS_IS_OK(result)) {
1349                 return result;
1350         }
1351
1352         conn = &domain->conn;
1353
1354         if (conn->netlogon_pipe != NULL) {
1355                 *cli = conn->netlogon_pipe;
1356                 return NT_STATUS_OK;
1357         }
1358
1359         if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1360                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1361         }
1362
1363         netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1364                                                  &result);
1365         if (netlogon_pipe == NULL) {
1366                 return result;
1367         }
1368
1369         if (lp_client_schannel() != False) {
1370                 neg_flags |= NETLOGON_NEG_SCHANNEL;
1371         }
1372
1373         /* if we are a DC and this is a trusted domain, then we need to use our
1374            domain name in the net_req_auth2() request */
1375
1376         if ( IS_DC
1377                 && !strequal(domain->name, lp_workgroup())
1378                 && lp_allow_trusted_domains() ) 
1379         {
1380                 account_name = lp_workgroup();
1381         } else {
1382                 account_name = domain->primary ?
1383                         global_myname() : domain->name;
1384         }
1385
1386         if (account_name == NULL) {
1387                 cli_rpc_pipe_close(netlogon_pipe);
1388                 return NT_STATUS_NO_MEMORY;
1389         }
1390
1391         result = rpccli_netlogon_setup_creds(
1392                  netlogon_pipe,
1393                  domain->dcname, /* server name. */
1394                  domain->name,   /* domain name */
1395                  global_myname(), /* client name */
1396                  account_name,   /* machine account */
1397                  mach_pwd,       /* machine password */
1398                  sec_chan_type,  /* from get_trust_pw */
1399                  &neg_flags);
1400
1401         if (!NT_STATUS_IS_OK(result)) {
1402                 cli_rpc_pipe_close(netlogon_pipe);
1403                 return result;
1404         }
1405
1406         if ((lp_client_schannel() == True) &&
1407                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1408                 DEBUG(3, ("Server did not offer schannel\n"));
1409                 cli_rpc_pipe_close(netlogon_pipe);
1410                 return NT_STATUS_ACCESS_DENIED;
1411         }
1412
1413         if ((lp_client_schannel() == False) ||
1414                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1415                 /* We're done - just keep the existing connection to NETLOGON
1416                  * open */
1417                 conn->netlogon_pipe = netlogon_pipe;
1418                 *cli = conn->netlogon_pipe;
1419                 return NT_STATUS_OK;
1420         }
1421
1422         /* Using the credentials from the first pipe, open a signed and sealed
1423            second netlogon pipe. The session key is stored in the schannel
1424            part of the new pipe auth struct.
1425         */
1426
1427         conn->netlogon_pipe =
1428                 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1429                                                     PI_NETLOGON,
1430                                                     PIPE_AUTH_LEVEL_PRIVACY,
1431                                                     domain->name,
1432                                                     netlogon_pipe->dc,
1433                                                     &result);
1434
1435         /* We can now close the initial netlogon pipe. */
1436         cli_rpc_pipe_close(netlogon_pipe);
1437
1438         if (conn->netlogon_pipe == NULL) {
1439                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1440                           "was %s\n", nt_errstr(result)));
1441                 return result;
1442         }
1443
1444         *cli = conn->netlogon_pipe;
1445         return NT_STATUS_OK;
1446 }