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