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