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