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