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