f7b7410ba236bc7b1cdd9be7d47a3b84ecdeb90d
[nivanova/samba-autobuild/.git] / source3 / 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    Copyright (C) Jeremy Allison            2006
11    
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27 /*
28    We need to manage connections to domain controllers without having to
29    mess up the main winbindd code with other issues.  The aim of the
30    connection manager is to:
31   
32        - make connections to domain controllers and cache them
33        - re-establish connections when networks or servers go down
34        - centralise the policy on connection timeouts, domain controller
35          selection etc
36        - manage re-entrancy for when winbindd becomes able to handle
37          multiple outstanding rpc requests
38   
39    Why not have connection management as part of the rpc layer like tng?
40    Good question.  This code may morph into libsmb/rpc_cache.c or something
41    like that but at the moment it's simply staying as part of winbind.  I
42    think the TNG architecture of forcing every user of the rpc layer to use
43    the connection caching system is a bad idea.  It should be an optional
44    method of using the routines.
45
46    The TNG design is quite good but I disagree with some aspects of the
47    implementation. -tpot
48
49  */
50
51 /*
52    TODO:
53
54      - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
55        moved down into another function.
56
57      - Take care when destroying cli_structs as they can be shared between
58        various sam handles.
59
60  */
61
62 #include "includes.h"
63 #include "winbindd.h"
64
65 #undef DBGC_CLASS
66 #define DBGC_CLASS DBGC_WINBIND
67
68 struct dc_name_ip {
69         fstring name;
70         struct in_addr ip;
71 };
72
73 extern struct winbindd_methods reconnect_methods;
74 extern BOOL override_logfile;
75
76 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
77 static void set_dc_type_and_flags( struct winbindd_domain *domain );
78 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
79                     struct dc_name_ip **dcs, int *num_dcs);
80
81 /****************************************************************
82  Child failed to find DC's. Reschedule check.
83 ****************************************************************/
84
85 static void msg_failed_to_go_online(int msg_type, struct process_id src,
86                                     void *buf, size_t len, void *private_data)
87 {
88         struct winbindd_domain *domain;
89         const char *domainname = (const char *)buf;
90
91         if (buf == NULL || len == 0) {
92                 return;
93         }
94
95         DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
96
97         for (domain = domain_list(); domain; domain = domain->next) {
98                 if (domain->internal) {
99                         continue;
100                 }
101
102                 if (strequal(domain->name, domainname)) {
103                         if (domain->online) {
104                                 /* We're already online, ignore. */
105                                 DEBUG(5,("msg_fail_to_go_online: domain %s "
106                                         "already online.\n", domainname));
107                                 continue;
108                         }
109
110                         /* Reschedule the online check. */
111                         set_domain_offline(domain);
112                         break;
113                 }
114         }
115 }
116
117 /****************************************************************
118  Actually cause a reconnect from a message.
119 ****************************************************************/
120
121 static void msg_try_to_go_online(int msg_type, struct process_id src,
122                                  void *buf, size_t len, void *private_data)
123 {
124         struct winbindd_domain *domain;
125         const char *domainname = (const char *)buf;
126
127         if (buf == NULL || len == 0) {
128                 return;
129         }
130
131         DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
132
133         for (domain = domain_list(); domain; domain = domain->next) {
134                 if (domain->internal) {
135                         continue;
136                 }
137
138                 if (strequal(domain->name, domainname)) {
139
140                         if (domain->online) {
141                                 /* We're already online, ignore. */
142                                 DEBUG(5,("msg_try_to_go_online: domain %s "
143                                         "already online.\n", domainname));
144                                 continue;
145                         }
146
147                         /* This call takes care of setting the online
148                            flag to true if we connected, or re-adding
149                            the offline handler if false. Bypasses online
150                            check so always does network calls. */
151
152                         init_dc_connection_network(domain);
153                         break;
154                 }
155         }
156 }
157
158 /****************************************************************
159  Fork a child to try and contact a DC. Do this as contacting a
160  DC requires blocking lookups and we don't want to block our
161  parent.
162 ****************************************************************/
163
164 static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
165 {
166         struct dc_name_ip *dcs = NULL;
167         int num_dcs = 0;
168         TALLOC_CTX *mem_ctx = NULL;
169         pid_t child_pid;
170         pid_t parent_pid = sys_getpid();
171
172         /* Stop zombies */
173         CatchChild();
174
175         message_block();
176
177         child_pid = sys_fork();
178
179         if (child_pid == -1) {
180                 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
181                 message_unblock();
182                 return False;
183         }
184
185         if (child_pid != 0) {
186                 /* Parent */
187                 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,
188                                  msg_try_to_go_online, NULL);
189                 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,
190                                  msg_failed_to_go_online, NULL);
191                 message_unblock();
192                 return True;
193         }
194
195         /* Child. */
196
197         /* Leave messages blocked - we will never process one. */
198
199         /* tdb needs special fork handling */
200         if (tdb_reopen_all(1) == -1) {
201                 DEBUG(0,("tdb_reopen_all failed.\n"));
202                 _exit(0);
203         }
204
205         close_conns_after_fork();
206
207         if (!override_logfile) {
208                 pstring logfile;
209                 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
210                 lp_set_logfile(logfile);
211                 reopen_logs();
212         }
213
214         mem_ctx = talloc_init("fork_child_dc_connect");
215         if (!mem_ctx) {
216                 DEBUG(0,("talloc_init failed.\n"));
217                 _exit(0);
218         }
219
220         if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
221                 /* Still offline ? Can't find DC's. */
222                 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
223                                 domain->name,
224                                 strlen(domain->name)+1, False);
225                 _exit(0);
226         }
227
228         /* We got a DC. Send a message to our parent to get it to
229            try and do the same. */
230
231         message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
232                                 domain->name,
233                                 strlen(domain->name)+1, False);
234         _exit(0);
235 }
236
237 /****************************************************************
238  Handler triggered if we're offline to try and detect a DC.
239 ****************************************************************/
240
241 static void check_domain_online_handler(struct event_context *ctx,
242                                         struct timed_event *te,
243                                         const struct timeval *now,
244                                         void *private_data)
245 {
246         struct winbindd_domain *domain =
247                 (struct winbindd_domain *)private_data;
248
249         DEBUG(10,("check_domain_online_handler: called for domain %s\n",
250                 domain->name ));
251
252         if (domain->check_online_event) {
253                 TALLOC_FREE(domain->check_online_event);
254         }
255
256         /* Are we still in "startup" mode ? */
257
258         if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
259                 /* No longer in "startup" mode. */
260                 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
261                         domain->name ));
262                 domain->startup = False;
263         }
264
265         /* We've been told to stay offline, so stay
266            that way. */
267
268         if (get_global_winbindd_state_offline()) {
269                 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
270                         domain->name ));
271                 return;
272         }
273
274         /* Fork a child to test if it can contact a DC. 
275            If it can then send ourselves a message to
276            cause a reconnect. */
277
278         fork_child_dc_connect(domain);
279 }
280
281 /****************************************************************
282  If we're still offline setup the timeout check.
283 ****************************************************************/
284
285 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
286 {
287         int wbc = lp_winbind_cache_time();
288
289         if (domain->startup) {
290                 domain->check_online_timeout = 10;
291         } else if (domain->check_online_timeout < wbc) {
292                 domain->check_online_timeout = wbc;
293         }
294 }
295
296 /****************************************************************
297  Set domain offline and also add handler to put us back online
298  if we detect a DC.
299 ****************************************************************/
300
301 void set_domain_offline(struct winbindd_domain *domain)
302 {
303         DEBUG(10,("set_domain_offline: called for domain %s\n",
304                 domain->name ));
305
306         if (domain->check_online_event) {
307                 TALLOC_FREE(domain->check_online_event);
308         }
309
310         if (domain->internal) {
311                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
312                         domain->name ));
313                 return;
314         }
315
316         domain->online = False;
317
318         /* Offline domains are always initialized. They're
319            re-initialized when they go back online. */
320
321         domain->initialized = True;
322
323         /* We only add the timeout handler that checks and
324            allows us to go back online when we've not
325            been told to remain offline. */
326
327         if (get_global_winbindd_state_offline()) {
328                 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
329                         domain->name ));
330                 return;
331         }
332
333         /* If we're in statup mode, check again in 10 seconds, not in
334            lp_winbind_cache_time() seconds (which is 5 mins by default). */
335
336         calc_new_online_timeout_check(domain);
337
338         domain->check_online_event = event_add_timed(winbind_event_context(),
339                                                 NULL,
340                                                 timeval_current_ofs(domain->check_online_timeout,0),
341                                                 "check_domain_online_handler",
342                                                 check_domain_online_handler,
343                                                 domain);
344
345         /* The above *has* to succeed for winbindd to work. */
346         if (!domain->check_online_event) {
347                 smb_panic("set_domain_offline: failed to add online handler.\n");
348         }
349
350         DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
351                 domain->name ));
352 }
353
354 /****************************************************************
355  Set domain online - if allowed.
356 ****************************************************************/
357
358 static void set_domain_online(struct winbindd_domain *domain)
359 {
360         struct timeval now;
361
362         DEBUG(10,("set_domain_online: called for domain %s\n",
363                 domain->name ));
364
365         if (domain->internal) {
366                 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
367                         domain->name ));
368                 return;
369         }
370
371         if (get_global_winbindd_state_offline()) {
372                 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
373                         domain->name ));
374                 return;
375         }
376
377         /* If we are waiting to get a krb5 ticket, trigger immediately. */
378         GetTimeOfDay(&now);
379         set_event_dispatch_time(winbind_event_context(),
380                                 "krb5_ticket_gain_handler", now);
381
382         /* Ok, we're out of any startup mode now... */
383         domain->startup = False;
384
385         if (domain->online == False) {
386                 /* We were offline - now we're online. We default to
387                    using the MS-RPC backend if we started offline,
388                    and if we're going online for the first time we
389                    should really re-initialize the backends and the
390                    checks to see if we're talking to an AD or NT domain.
391                 */
392
393                 domain->initialized = False;
394
395                 /* 'reconnect_methods' is the MS-RPC backend. */
396                 if (domain->backend == &reconnect_methods) {
397                         domain->backend = NULL;
398                 }
399         }
400
401         /* Ensure we have no online timeout checks. */
402         domain->check_online_timeout = 0;
403         if (domain->check_online_event) {
404                 TALLOC_FREE(domain->check_online_event);
405         }
406
407         /* Ensure we ignore any pending child messages. */
408         message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
409         message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
410
411         domain->online = True;
412 }
413
414 /****************************************************************
415  Requested to set a domain online.
416 ****************************************************************/
417
418 void set_domain_online_request(struct winbindd_domain *domain)
419 {
420         struct timeval tev;
421
422         DEBUG(10,("set_domain_online_request: called for domain %s\n",
423                 domain->name ));
424
425         if (get_global_winbindd_state_offline()) {
426                 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
427                         domain->name ));
428                 return;
429         }
430
431         /* We've been told it's safe to go online and
432            try and connect to a DC. But I don't believe it
433            because network manager seems to lie.
434            Wait at least 5 seconds. Heuristics suck... */
435
436         if (!domain->check_online_event) {
437                 /* If we've come from being globally offline we
438                    don't have a check online event handler set.
439                    We need to add one now we're trying to go
440                    back online. */
441
442                 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
443                         domain->name ));
444
445                 domain->check_online_event = event_add_timed(winbind_event_context(),
446                                                                 NULL,
447                                                                 timeval_current_ofs(5, 0),
448                                                                 "check_domain_online_handler",
449                                                                 check_domain_online_handler,
450                                                                 domain);
451
452                 /* The above *has* to succeed for winbindd to work. */
453                 if (!domain->check_online_event) {
454                         smb_panic("set_domain_online_request: failed to add online handler.\n");
455                 }
456         }
457
458         GetTimeOfDay(&tev);
459
460         /* Go into "startup" mode again. */
461         domain->startup_time = tev.tv_sec;
462         domain->startup = True;
463
464         tev.tv_sec += 5;
465
466         set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
467 }
468
469 /****************************************************************
470  Add -ve connection cache entries for domain and realm.
471 ****************************************************************/
472
473 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
474                                         const char *server,
475                                         NTSTATUS result)
476 {
477         add_failed_connection_entry(domain->name, server, result);
478         /* If this was the saf name for the last thing we talked to,
479            remove it. */
480         saf_delete(domain->name);
481         if (*domain->alt_name) {
482                 add_failed_connection_entry(domain->alt_name, server, result);
483                 saf_delete(domain->alt_name);
484         }
485 }
486
487 /* Choose between anonymous or authenticated connections.  We need to use
488    an authenticated connection if DCs have the RestrictAnonymous registry
489    entry set > 0, or the "Additional restrictions for anonymous
490    connections" set in the win2k Local Security Policy. 
491    
492    Caller to free() result in domain, username, password
493 */
494
495 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
496 {
497         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
498         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
499         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
500         
501         if (*username && **username) {
502
503                 if (!*domain || !**domain)
504                         *domain = smb_xstrdup(lp_workgroup());
505                 
506                 if (!*password || !**password)
507                         *password = smb_xstrdup("");
508
509                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
510                           *domain, *username));
511
512         } else {
513                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
514                 *username = smb_xstrdup("");
515                 *domain = smb_xstrdup("");
516                 *password = smb_xstrdup("");
517         }
518 }
519
520 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
521                                      fstring dcname, struct in_addr *dc_ip)
522 {
523         struct winbindd_domain *our_domain = NULL;
524         struct rpc_pipe_client *netlogon_pipe = NULL;
525         NTSTATUS result;
526         WERROR werr;
527         TALLOC_CTX *mem_ctx;
528         unsigned int orig_timeout;
529         fstring tmp;
530         char *p;
531
532         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
533          * moment.... */
534
535         if (IS_DC) {
536                 return False;
537         }
538
539         if (domain->primary) {
540                 return False;
541         }
542
543         our_domain = find_our_domain();
544
545         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
546                 return False;
547         }
548
549         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
550         if (!NT_STATUS_IS_OK(result)) {
551                 talloc_destroy(mem_ctx);
552                 return False;
553         }
554
555         /* This call can take a long time - allow the server to time out.
556            35 seconds should do it. */
557
558         orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
559         
560         werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
561                                            domain->name, tmp);
562
563         /* And restore our original timeout. */
564         cli_set_timeout(netlogon_pipe->cli, orig_timeout);
565
566         talloc_destroy(mem_ctx);
567
568         if (!W_ERROR_IS_OK(werr)) {
569                 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
570                            dos_errstr(werr)));
571                 return False;
572         }
573
574         /* cli_netlogon_getdcname gives us a name with \\ */
575         p = tmp;
576         if (*p == '\\') {
577                 p+=1;
578         }
579         if (*p == '\\') {
580                 p+=1;
581         }
582
583         fstrcpy(dcname, p);
584
585         DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
586
587         if (!resolve_name(dcname, dc_ip, 0x20)) {
588                 return False;
589         }
590
591         return True;
592 }
593
594 /************************************************************************
595  Given a fd with a just-connected TCP connection to a DC, open a connection
596  to the pipe.
597 ************************************************************************/
598
599 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
600                                       const int sockfd,
601                                       const char *controller,
602                                       struct cli_state **cli,
603                                       BOOL *retry)
604 {
605         char *machine_password, *machine_krb5_principal, *machine_account;
606         char *ipc_username, *ipc_domain, *ipc_password;
607
608         BOOL got_mutex;
609
610         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
611
612         struct sockaddr peeraddr;
613         socklen_t peeraddr_len;
614
615         struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
616
617         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
618                 controller, domain->name ));
619
620         machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
621                                                           NULL);
622         
623         if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
624                 SAFE_FREE(machine_password);
625                 return NT_STATUS_NO_MEMORY;
626         }
627
628         if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
629                      lp_realm()) == -1) {
630                 SAFE_FREE(machine_account);
631                 SAFE_FREE(machine_password);
632                 return NT_STATUS_NO_MEMORY;
633         }
634
635         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
636
637         *retry = True;
638
639         got_mutex = secrets_named_mutex(controller,
640                                         WINBIND_SERVER_MUTEX_WAIT_TIME);
641
642         if (!got_mutex) {
643                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
644                          controller));
645                 result = NT_STATUS_POSSIBLE_DEADLOCK;
646                 goto done;
647         }
648
649         if ((*cli = cli_initialise()) == NULL) {
650                 DEBUG(1, ("Could not cli_initialize\n"));
651                 result = NT_STATUS_NO_MEMORY;
652                 goto done;
653         }
654
655         (*cli)->timeout = 10000;        /* 10 seconds */
656         (*cli)->fd = sockfd;
657         fstrcpy((*cli)->desthost, controller);
658         (*cli)->use_kerberos = True;
659
660         peeraddr_len = sizeof(peeraddr);
661
662         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
663             (peeraddr_len != sizeof(struct sockaddr_in)) ||
664             (peeraddr_in->sin_family != PF_INET))
665         {
666                 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
667                 result = NT_STATUS_UNSUCCESSFUL;
668                 goto done;
669         }
670
671         if (ntohs(peeraddr_in->sin_port) == 139) {
672                 struct nmb_name calling;
673                 struct nmb_name called;
674
675                 make_nmb_name(&calling, global_myname(), 0x0);
676                 make_nmb_name(&called, "*SMBSERVER", 0x20);
677
678                 if (!cli_session_request(*cli, &calling, &called)) {
679                         DEBUG(8, ("cli_session_request failed for %s\n",
680                                   controller));
681                         result = NT_STATUS_UNSUCCESSFUL;
682                         goto done;
683                 }
684         }
685
686         cli_setup_signing_state(*cli, Undefined);
687
688         if (!cli_negprot(*cli)) {
689                 DEBUG(1, ("cli_negprot failed\n"));
690                 result = NT_STATUS_UNSUCCESSFUL;
691                 goto done;
692         }
693                         
694         if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
695                 ADS_STATUS ads_status;
696
697                 if (lp_security() == SEC_ADS) {
698
699                         /* Try a krb5 session */
700
701                         (*cli)->use_kerberos = True;
702                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
703                                   "[%s]\n", controller, global_myname(),
704                                   machine_krb5_principal));
705
706                         ads_status = cli_session_setup_spnego(*cli,
707                                                               machine_krb5_principal, 
708                                                               machine_password, 
709                                                               lp_workgroup());
710
711                         if (!ADS_ERR_OK(ads_status)) {
712                                 DEBUG(4,("failed kerberos session setup with %s\n",
713                                          ads_errstr(ads_status)));
714                         }
715
716                         result = ads_ntstatus(ads_status);
717                         if (NT_STATUS_IS_OK(result)) {
718                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
719                                 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
720                                 goto session_setup_done;
721                         }
722                 }
723
724                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
725                 (*cli)->use_kerberos = False;
726
727                 DEBUG(5, ("connecting to %s from %s with username "
728                           "[%s]\\[%s]\n",  controller, global_myname(),
729                           lp_workgroup(), machine_account));
730
731                 ads_status = cli_session_setup_spnego(*cli,
732                                                       machine_account, 
733                                                       machine_password, 
734                                                       lp_workgroup());
735                 if (!ADS_ERR_OK(ads_status)) {
736                         DEBUG(4, ("authenticated session setup failed with %s\n",
737                                 ads_errstr(ads_status)));
738                 }
739
740                 result = ads_ntstatus(ads_status);
741                 if (NT_STATUS_IS_OK(result)) {
742                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
743                         cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
744                         goto session_setup_done;
745                 }
746         }
747
748         /* Fall back to non-kerberos session setup */
749
750         (*cli)->use_kerberos = False;
751
752         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
753             (strlen(ipc_username) > 0)) {
754
755                 /* Only try authenticated if we have a username */
756
757                 DEBUG(5, ("connecting to %s from %s with username "
758                           "[%s]\\[%s]\n",  controller, global_myname(),
759                           ipc_domain, ipc_username));
760
761                 if (NT_STATUS_IS_OK(cli_session_setup(
762                                             *cli, ipc_username,
763                                             ipc_password, strlen(ipc_password)+1,
764                                             ipc_password, strlen(ipc_password)+1,
765                                             ipc_domain))) {
766                         /* Successful logon with given username. */
767                         cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
768                         goto session_setup_done;
769                 } else {
770                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
771                                 ipc_domain, ipc_username ));
772                 }
773         }
774
775         /* Fall back to anonymous connection, this might fail later */
776
777         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
778                                               NULL, 0, ""))) {
779                 DEBUG(5, ("Connected anonymously\n"));
780                 cli_init_creds(*cli, "", "", "");
781                 goto session_setup_done;
782         }
783
784         result = cli_nt_error(*cli);
785
786         if (NT_STATUS_IS_OK(result))
787                 result = NT_STATUS_UNSUCCESSFUL;
788
789         /* We can't session setup */
790
791         goto done;
792
793  session_setup_done:
794
795         /* cache the server name for later connections */
796
797         saf_store( domain->name, (*cli)->desthost );
798         if (domain->alt_name && (*cli)->use_kerberos) {
799                 saf_store( domain->alt_name, (*cli)->desthost );
800         }
801
802         if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
803
804                 result = cli_nt_error(*cli);
805
806                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
807
808                 if (NT_STATUS_IS_OK(result))
809                         result = NT_STATUS_UNSUCCESSFUL;
810
811                 goto done;
812         }
813
814         secrets_named_mutex_release(controller);
815         got_mutex = False;
816         *retry = False;
817
818         /* set the domain if empty; needed for schannel connections */
819         if ( !*(*cli)->domain ) {
820                 fstrcpy( (*cli)->domain, domain->name );
821         }
822
823         result = NT_STATUS_OK;
824
825  done:
826         if (got_mutex) {
827                 secrets_named_mutex_release(controller);
828         }
829
830         SAFE_FREE(machine_account);
831         SAFE_FREE(machine_password);
832         SAFE_FREE(machine_krb5_principal);
833         SAFE_FREE(ipc_username);
834         SAFE_FREE(ipc_domain);
835         SAFE_FREE(ipc_password);
836
837         if (!NT_STATUS_IS_OK(result)) {
838                 winbind_add_failed_connection_entry(domain, controller, result);
839                 if ((*cli) != NULL) {
840                         cli_shutdown(*cli);
841                         *cli = NULL;
842                 }
843         }
844
845         return result;
846 }
847
848 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
849                               const char *dcname, struct in_addr ip,
850                               struct dc_name_ip **dcs, int *num)
851 {
852         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
853                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
854                 return False;
855         }
856
857         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
858
859         if (*dcs == NULL)
860                 return False;
861
862         fstrcpy((*dcs)[*num].name, dcname);
863         (*dcs)[*num].ip = ip;
864         *num += 1;
865         return True;
866 }
867
868 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
869                                   struct in_addr ip, uint16 port,
870                                   struct sockaddr_in **addrs, int *num)
871 {
872         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
873
874         if (*addrs == NULL) {
875                 *num = 0;
876                 return False;
877         }
878
879         (*addrs)[*num].sin_family = PF_INET;
880         putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
881         (*addrs)[*num].sin_port = htons(port);
882
883         *num += 1;
884         return True;
885 }
886
887 static void mailslot_name(struct in_addr dc_ip, fstring name)
888 {
889         fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
890 }
891
892 static BOOL send_getdc_request(struct in_addr dc_ip,
893                                const char *domain_name,
894                                const DOM_SID *sid)
895 {
896         pstring outbuf;
897         char *p;
898         fstring my_acct_name;
899         fstring my_mailslot;
900
901         mailslot_name(dc_ip, my_mailslot);
902
903         memset(outbuf, '\0', sizeof(outbuf));
904
905         p = outbuf;
906
907         SCVAL(p, 0, SAMLOGON);
908         p++;
909
910         SCVAL(p, 0, 0); /* Count pointer ... */
911         p++;
912
913         SIVAL(p, 0, 0); /* The sender's token ... */
914         p += 2;
915
916         p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
917         fstr_sprintf(my_acct_name, "%s$", global_myname());
918         p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
919
920         memcpy(p, my_mailslot, strlen(my_mailslot)+1);
921         p += strlen(my_mailslot)+1;
922
923         SIVAL(p, 0, 0x80);
924         p+=4;
925
926         SIVAL(p, 0, sid_size(sid));
927         p+=4;
928
929         p = ALIGN4(p, outbuf);
930
931         sid_linearize(p, sid_size(sid), sid);
932         p += sid_size(sid);
933
934         SIVAL(p, 0, 1);
935         SSVAL(p, 4, 0xffff);
936         SSVAL(p, 6, 0xffff);
937         p+=8;
938
939         return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
940                                  outbuf, PTR_DIFF(p, outbuf),
941                                  global_myname(), 0, domain_name, 0x1c,
942                                  dc_ip);
943 }
944
945 static BOOL receive_getdc_response(struct in_addr dc_ip,
946                                    const char *domain_name,
947                                    fstring dc_name)
948 {
949         struct packet_struct *packet;
950         fstring my_mailslot;
951         char *buf, *p;
952         fstring dcname, user, domain;
953         int len;
954
955         mailslot_name(dc_ip, my_mailslot);
956
957         packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
958
959         if (packet == NULL) {
960                 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
961                 return False;
962         }
963
964         DEBUG(5, ("Received packet for %s\n", my_mailslot));
965
966         buf = packet->packet.dgram.data;
967         len = packet->packet.dgram.datasize;
968
969         if (len < 70) {
970                 /* 70 is a completely arbitrary value to make sure
971                    the SVAL below does not read uninitialized memory */
972                 DEBUG(3, ("GetDC got short response\n"));
973                 return False;
974         }
975
976         /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
977         p = buf+SVAL(buf, smb_vwv10);
978
979         if (CVAL(p,0) != SAMLOGON_R) {
980                 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
981                 return False;
982         }
983
984         p+=2;
985         pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
986                   STR_TERMINATE|STR_NOALIGN);
987         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
988         pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
989                   STR_TERMINATE|STR_NOALIGN);
990         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
991         pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
992                   STR_TERMINATE|STR_NOALIGN);
993         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
994
995         if (!strequal(domain, domain_name)) {
996                 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
997                           domain_name, domain));
998                 return False;
999         }
1000
1001         p = dcname;
1002         if (*p == '\\') p += 1;
1003         if (*p == '\\') p += 1;
1004
1005         fstrcpy(dc_name, p);
1006
1007         DEBUG(10, ("GetDC gave name %s for domain %s\n",
1008                    dc_name, domain));
1009
1010         return True;
1011 }
1012
1013 /*******************************************************************
1014  convert an ip to a name
1015 *******************************************************************/
1016
1017 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1018 {
1019         struct ip_service ip_list;
1020
1021         ip_list.ip = ip;
1022         ip_list.port = 0;
1023
1024 #ifdef WITH_ADS
1025         /* For active directory servers, try to get the ldap server name.
1026            None of these failures should be considered critical for now */
1027
1028         if (lp_security() == SEC_ADS) {
1029                 ADS_STRUCT *ads;
1030
1031                 ads = ads_init(domain->alt_name, domain->name, NULL);
1032                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1033
1034                 if (ads_try_connect( ads, inet_ntoa(ip) ) )  {
1035                         /* We got a cldap packet. */
1036                         fstrcpy(name, ads->config.ldap_server_name);
1037                         namecache_store(name, 0x20, 1, &ip_list);
1038
1039                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1040
1041                         if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1042                                 char *sitename = sitename_fetch(ads->config.realm);
1043
1044                                 /* We're going to use this KDC for this realm/domain.
1045                                    If we are using sites, then force the krb5 libs
1046                                    to use this KDC. */
1047
1048                                 create_local_private_krb5_conf_for_domain(domain->alt_name,
1049                                                                 domain->name,
1050                                                                 sitename,
1051                                                                 ip);
1052
1053                                 SAFE_FREE(sitename);
1054                                 /* Ensure we contact this DC also. */
1055                                 saf_store( domain->name, name);
1056                                 saf_store( domain->alt_name, name);
1057                         }
1058
1059                         ads_destroy( &ads );
1060                         return True;
1061                 }
1062
1063                 ads_destroy( &ads );
1064         }
1065 #endif
1066
1067         /* try GETDC requests next */
1068         
1069         if (send_getdc_request(ip, domain->name, &domain->sid)) {
1070                 int i;
1071                 smb_msleep(100);
1072                 for (i=0; i<5; i++) {
1073                         if (receive_getdc_response(ip, domain->name, name)) {
1074                                 namecache_store(name, 0x20, 1, &ip_list);
1075                                 return True;
1076                         }
1077                         smb_msleep(500);
1078                 }
1079         }
1080
1081         /* try node status request */
1082
1083         if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1084                 namecache_store(name, 0x20, 1, &ip_list);
1085                 return True;
1086         }
1087         return False;
1088 }
1089
1090 /*******************************************************************
1091  Retreive a list of IP address for domain controllers.  Fill in 
1092  the dcs[]  with results.
1093 *******************************************************************/
1094
1095 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1096                     struct dc_name_ip **dcs, int *num_dcs)
1097 {
1098         fstring dcname;
1099         struct  in_addr ip;
1100         struct  ip_service *ip_list = NULL;
1101         int     iplist_size = 0;
1102         int     i;
1103         BOOL    is_our_domain;
1104         enum security_types sec = (enum security_types)lp_security();
1105
1106         is_our_domain = strequal(domain->name, lp_workgroup());
1107
1108         if ( !is_our_domain 
1109                 && get_dc_name_via_netlogon(domain, dcname, &ip) 
1110                 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1111         {
1112                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1113                            dcname, inet_ntoa(ip)));
1114                 return True;
1115         }
1116
1117         if (sec == SEC_ADS) {
1118                 char *sitename = NULL;
1119
1120                 /* We need to make sure we know the local site before
1121                    doing any DNS queries, as this will restrict the
1122                    get_sorted_dc_list() call below to only fetching
1123                    DNS records for the correct site. */
1124
1125                 /* Find any DC to get the site record.
1126                    We deliberately don't care about the
1127                    return here. */
1128
1129                 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1130
1131                 sitename = sitename_fetch(domain->alt_name);
1132                 if (sitename) {
1133
1134                         /* Do the site-specific AD dns lookup first. */
1135                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1136
1137                         for ( i=0; i<iplist_size; i++ ) {
1138                                 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1139                                                         ip_list[i].ip, dcs, num_dcs);
1140                         }
1141
1142                         SAFE_FREE(ip_list);
1143                         SAFE_FREE(sitename);
1144                         iplist_size = 0;
1145                 }
1146
1147                 /* Now we add DCs from the main AD dns lookup. */
1148                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1149
1150                 for ( i=0; i<iplist_size; i++ ) {
1151                         add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1152                                                 ip_list[i].ip, dcs, num_dcs);
1153                 }
1154         }
1155
1156         /* try standard netbios queries if no ADS */
1157
1158         if (iplist_size==0) {
1159                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1160         }
1161
1162         /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1163
1164         /* now add to the dc array.  We'll wait until the last minute 
1165            to look up the name of the DC.  But we fill in the char* for 
1166            the ip now in to make the failed connection cache work */
1167
1168         for ( i=0; i<iplist_size; i++ ) {
1169                 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip), 
1170                         ip_list[i].ip, dcs, num_dcs);
1171         }
1172
1173         SAFE_FREE( ip_list );
1174
1175         return True;
1176 }
1177
1178 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1179                         const struct winbindd_domain *domain,
1180                         fstring dcname, struct sockaddr_in *addr, int *fd)
1181 {
1182         struct dc_name_ip *dcs = NULL;
1183         int num_dcs = 0;
1184
1185         const char **dcnames = NULL;
1186         int num_dcnames = 0;
1187
1188         struct sockaddr_in *addrs = NULL;
1189         int num_addrs = 0;
1190
1191         int i, fd_index;
1192
1193  again:
1194         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1195                 return False;
1196
1197         for (i=0; i<num_dcs; i++) {
1198
1199                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1200                                     &dcnames, &num_dcnames)) {
1201                         return False;
1202                 }
1203                 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1204                                       &addrs, &num_addrs)) {
1205                         return False;
1206                 }
1207
1208                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1209                                     &dcnames, &num_dcnames)) {
1210                         return False;
1211                 }
1212                 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1213                                       &addrs, &num_addrs)) {
1214                         return False;
1215                 }
1216         }
1217
1218         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1219                 return False;
1220
1221         if ((addrs == NULL) || (dcnames == NULL))
1222                 return False;
1223
1224         /* 5 second timeout. */
1225         if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) 
1226         {
1227                 for (i=0; i<num_dcs; i++) {
1228                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1229                                 "domain %s address %s. Error was %s\n",
1230                                 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1231                         winbind_add_failed_connection_entry(domain,
1232                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1233                 }
1234                 return False;
1235         }
1236
1237         *addr = addrs[fd_index];
1238
1239         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1240                 /* Ok, we've got a name for the DC */
1241                 fstrcpy(dcname, dcnames[fd_index]);
1242                 return True;
1243         }
1244
1245         /* Try to figure out the name */
1246         if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1247                 return True;
1248         }
1249
1250         /* We can not continue without the DC's name */
1251         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1252                                     NT_STATUS_UNSUCCESSFUL);
1253         goto again;
1254 }
1255
1256 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1257                                    struct winbindd_cm_conn *new_conn)
1258 {
1259         TALLOC_CTX *mem_ctx;
1260         NTSTATUS result;
1261         char *saf_servername = saf_fetch( domain->name );
1262         int retries;
1263
1264         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1265                 SAFE_FREE(saf_servername);
1266                 set_domain_offline(domain);
1267                 return NT_STATUS_NO_MEMORY;
1268         }
1269
1270         /* we have to check the server affinity cache here since 
1271            later we selecte a DC based on response time and not preference */
1272            
1273         /* Check the negative connection cache
1274            before talking to it. It going down may have
1275            triggered the reconnection. */
1276
1277         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1278
1279                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1280                         saf_servername, domain->name ));
1281
1282                 /* convert an ip address to a name */
1283                 if ( is_ipaddress( saf_servername ) ) {
1284                         fstring saf_name;
1285                         struct in_addr ip;
1286
1287                         ip = *interpret_addr2( saf_servername );
1288                         if (dcip_to_name( domain, ip, saf_name )) {
1289                                 fstrcpy( domain->dcname, saf_name );
1290                         } else {
1291                                 winbind_add_failed_connection_entry(
1292                                         domain, saf_servername,
1293                                         NT_STATUS_UNSUCCESSFUL);
1294                         }
1295                 } else {
1296                         fstrcpy( domain->dcname, saf_servername );
1297                 }
1298
1299                 SAFE_FREE( saf_servername );
1300         }
1301
1302         for (retries = 0; retries < 3; retries++) {
1303
1304                 int fd = -1;
1305                 BOOL retry = False;
1306
1307                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1308
1309                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1310                         domain->dcname, domain->name ));
1311
1312                 if (*domain->dcname 
1313                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1314                         && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1315                 {
1316                         struct sockaddr_in *addrs = NULL;
1317                         int num_addrs = 0;
1318                         int dummy = 0;
1319
1320                         if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1321                                 set_domain_offline(domain);
1322                                 talloc_destroy(mem_ctx);
1323                                 return NT_STATUS_NO_MEMORY;
1324                         }
1325                         if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1326                                 set_domain_offline(domain);
1327                                 talloc_destroy(mem_ctx);
1328                                 return NT_STATUS_NO_MEMORY;
1329                         }
1330
1331                         /* 5 second timeout. */
1332                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1333                                 fd = -1;
1334                         }
1335                 }
1336
1337                 if ((fd == -1) 
1338                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1339                 {
1340                         /* This is the one place where we will
1341                            set the global winbindd offline state
1342                            to true, if a "WINBINDD_OFFLINE" entry
1343                            is found in the winbindd cache. */
1344                         set_global_winbindd_state_offline();
1345                         break;
1346                 }
1347
1348                 new_conn->cli = NULL;
1349
1350                 result = cm_prepare_connection(domain, fd, domain->dcname,
1351                         &new_conn->cli, &retry);
1352
1353                 if (!retry)
1354                         break;
1355         }
1356
1357         if (NT_STATUS_IS_OK(result)) {
1358                 if (domain->online == False) {
1359                         /* We're changing state from offline to online. */
1360                         set_global_winbindd_state_online();
1361                 }
1362                 set_domain_online(domain);
1363         } else {
1364                 /* Ensure we setup the retry handler. */
1365                 set_domain_offline(domain);
1366         }
1367
1368         talloc_destroy(mem_ctx);
1369         return result;
1370 }
1371
1372 /* Close down all open pipes on a connection. */
1373
1374 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1375 {
1376         /* We're closing down a possibly dead
1377            connection. Don't have impossibly long (10s) timeouts. */
1378
1379         if (conn->cli) {
1380                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1381         }
1382
1383         if (conn->samr_pipe != NULL) {
1384                 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1385                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1386                         if (conn->cli) {
1387                                 cli_set_timeout(conn->cli, 500);
1388                         }
1389                 }
1390                 conn->samr_pipe = NULL;
1391         }
1392
1393         if (conn->lsa_pipe != NULL) {
1394                 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1395                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1396                         if (conn->cli) {
1397                                 cli_set_timeout(conn->cli, 500);
1398                         }
1399                 }
1400                 conn->lsa_pipe = NULL;
1401         }
1402
1403         if (conn->netlogon_pipe != NULL) {
1404                 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1405                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1406                         if (conn->cli) {
1407                                 cli_set_timeout(conn->cli, 500);
1408                         }
1409                 }
1410                 conn->netlogon_pipe = NULL;
1411         }
1412
1413         if (conn->cli) {
1414                 cli_shutdown(conn->cli);
1415         }
1416
1417         conn->cli = NULL;
1418 }
1419
1420 void close_conns_after_fork(void)
1421 {
1422         struct winbindd_domain *domain;
1423
1424         for (domain = domain_list(); domain; domain = domain->next) {
1425                 if (domain->conn.cli == NULL)
1426                         continue;
1427
1428                 if (domain->conn.cli->fd == -1)
1429                         continue;
1430
1431                 close(domain->conn.cli->fd);
1432                 domain->conn.cli->fd = -1;
1433         }
1434 }
1435
1436 static BOOL connection_ok(struct winbindd_domain *domain)
1437 {
1438         if (domain->conn.cli == NULL) {
1439                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1440                           "cli!\n", domain->dcname, domain->name));
1441                 return False;
1442         }
1443
1444         if (!domain->conn.cli->initialised) {
1445                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1446                           "initialised!\n", domain->dcname, domain->name));
1447                 return False;
1448         }
1449
1450         if (domain->conn.cli->fd == -1) {
1451                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1452                           "never started (fd == -1)\n", 
1453                           domain->dcname, domain->name));
1454                 return False;
1455         }
1456
1457         if (domain->online == False) {
1458                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1459                 return False;
1460         }
1461
1462         return True;
1463 }
1464
1465 /* Initialize a new connection up to the RPC BIND.
1466    Bypass online status check so always does network calls. */
1467
1468 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1469 {
1470         NTSTATUS result;
1471
1472         /* Internal connections never use the network. */
1473         if (domain->internal) {
1474                 domain->initialized = True;
1475                 return NT_STATUS_OK;
1476         }
1477
1478         if (connection_ok(domain)) {
1479                 if (!domain->initialized) {
1480                         set_dc_type_and_flags(domain);
1481                 }
1482                 return NT_STATUS_OK;
1483         }
1484
1485         invalidate_cm_connection(&domain->conn);
1486
1487         result = cm_open_connection(domain, &domain->conn);
1488
1489         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1490                 set_dc_type_and_flags(domain);
1491         }
1492
1493         return result;
1494 }
1495
1496 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1497 {
1498         if (domain->initialized && !domain->online) {
1499                 /* We check for online status elsewhere. */
1500                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1501         }
1502
1503         return init_dc_connection_network(domain);
1504 }
1505
1506 /******************************************************************************
1507  Set the trust flags (direction and forest location) for a domain
1508 ******************************************************************************/
1509
1510 static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1511 {
1512         struct winbindd_domain *our_domain;
1513         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1514         struct ds_domain_trust *domains = NULL;
1515         int count = 0;
1516         int i;
1517         uint32 flags = (DS_DOMAIN_IN_FOREST | 
1518                         DS_DOMAIN_DIRECT_OUTBOUND | 
1519                         DS_DOMAIN_DIRECT_INBOUND);
1520         struct rpc_pipe_client *cli;
1521         TALLOC_CTX *mem_ctx = NULL;
1522
1523         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1524         
1525         /* Our primary domain doesn't need to worry about trust flags.
1526            Force it to go through the network setup */
1527         if ( domain->primary ) {                
1528                 return False;           
1529         }
1530         
1531         our_domain = find_our_domain();
1532         
1533         if ( !connection_ok(our_domain) ) {
1534                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1535                 return False;
1536         }
1537
1538         /* This won't work unless our domain is AD */
1539          
1540         if ( !our_domain->active_directory ) {
1541                 return False;
1542         }
1543         
1544         /* Use DsEnumerateDomainTrusts to get us the trust direction
1545            and type */
1546
1547         result = cm_connect_netlogon(our_domain, &cli);
1548
1549         if (!NT_STATUS_IS_OK(result)) {
1550                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1551                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1552                           domain->name, nt_errstr(result)));
1553                 return False;
1554         }
1555
1556         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1557                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1558                 return False;
1559         }       
1560
1561         result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
1562                                               cli->cli->desthost, 
1563                                               flags, &domains,
1564                                               (unsigned int *)&count);
1565
1566         /* Now find the domain name and get the flags */
1567
1568         for ( i=0; i<count; i++ ) {
1569                 if ( strequal( domain->name, domains[i].netbios_domain ) ) {                    
1570                         domain->domain_flags          = domains[i].flags;
1571                         domain->domain_type           = domains[i].trust_type;
1572                         domain->domain_trust_attribs  = domains[i].trust_attributes;
1573                                                 
1574                         if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
1575                                 domain->active_directory = True;
1576
1577                         /* This flag is only set if the domain is *our* 
1578                            primary domain and the primary domain is in
1579                            native mode */
1580
1581                         domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
1582
1583                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1584                                   "native mode.\n", domain->name, 
1585                                   domain->native_mode ? "" : "NOT "));
1586
1587                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1588                                  "running active directory.\n", domain->name, 
1589                                  domain->active_directory ? "" : "NOT "));
1590
1591
1592                         domain->initialized = True;
1593
1594                         if ( !winbindd_can_contact_domain( domain) )
1595                                 domain->internal = True;
1596                         
1597                         break;
1598                 }               
1599         }
1600         
1601         talloc_destroy( mem_ctx );
1602         
1603         return domain->initialized;     
1604 }
1605
1606 /******************************************************************************
1607  We can 'sense' certain things about the DC by it's replies to certain
1608  questions.
1609
1610  This tells us if this particular remote server is Active Directory, and if it
1611  is native mode.
1612 ******************************************************************************/
1613
1614 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1615 {
1616         NTSTATUS                result;
1617         DS_DOMINFO_CTR          ctr;
1618         TALLOC_CTX              *mem_ctx = NULL;
1619         struct rpc_pipe_client  *cli;
1620         POLICY_HND pol;
1621
1622         char *domain_name = NULL;
1623         char *dns_name = NULL;
1624         char *forest_name = NULL;       
1625         DOM_SID *dom_sid = NULL;        
1626
1627         ZERO_STRUCT( ctr );
1628         
1629         if (!connection_ok(domain)) {
1630                 return;
1631         }
1632
1633         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1634
1635         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1636                                        &result);
1637
1638         if (cli == NULL) {
1639                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1640                           "PI_LSARPC_DS on domain %s: (%s)\n",
1641                           domain->name, nt_errstr(result)));
1642
1643                 /* if this is just a non-AD domain we need to continue
1644                  * identifying so that we can in the end return with
1645                  * domain->initialized = True - gd */
1646
1647                 goto no_lsarpc_ds;
1648         }
1649
1650         result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1651                                              DsRolePrimaryDomainInfoBasic,
1652                                              &ctr);
1653         cli_rpc_pipe_close(cli);
1654
1655         if (!NT_STATUS_IS_OK(result)) {
1656                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1657                           "on domain %s failed: (%s)\n",
1658                           domain->name, nt_errstr(result)));
1659                 return;
1660         }
1661         
1662         if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1663             !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1664                 domain->native_mode = True;
1665         } else {
1666                 domain->native_mode = False;
1667         }
1668
1669 no_lsarpc_ds:
1670         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1671
1672         if (cli == NULL) {
1673                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1674                           "PI_LSARPC on domain %s: (%s)\n",
1675                           domain->name, nt_errstr(result)));
1676                 cli_rpc_pipe_close(cli);
1677                 return;
1678         }
1679
1680         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1681                               domain->name);
1682         if (!mem_ctx) {
1683                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1684                 cli_rpc_pipe_close(cli);
1685                 return;
1686         }
1687
1688         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1689                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1690                 
1691         if (NT_STATUS_IS_OK(result)) {
1692                 /* This particular query is exactly what Win2k clients use 
1693                    to determine that the DC is active directory */
1694                 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1695                                                        12, &domain_name,
1696                                                        &dns_name, &forest_name,
1697                                                        NULL, &dom_sid);
1698         }
1699
1700         if (NT_STATUS_IS_OK(result)) {
1701                 domain->active_directory = True;
1702
1703                 if (domain_name)
1704                         fstrcpy(domain->name, domain_name);
1705
1706                 if (dns_name)
1707                         fstrcpy(domain->alt_name, dns_name);
1708
1709                 if ( forest_name )
1710                         fstrcpy(domain->forest_name, forest_name);              
1711
1712                 if (dom_sid) 
1713                         sid_copy(&domain->sid, dom_sid);
1714         } else {
1715                 domain->active_directory = False;
1716
1717                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1718                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1719                                                 &pol);
1720                         
1721                 if (!NT_STATUS_IS_OK(result))
1722                         goto done;
1723                         
1724                 result = rpccli_lsa_query_info_policy(cli, mem_ctx, 
1725                                                       &pol, 5, &domain_name, 
1726                                                       &dom_sid);
1727                         
1728                 if (NT_STATUS_IS_OK(result)) {
1729                         if (domain_name)
1730                                 fstrcpy(domain->name, domain_name);
1731
1732                         if (dom_sid) 
1733                                 sid_copy(&domain->sid, dom_sid);
1734                 }
1735         }
1736 done:
1737
1738         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1739                   domain->name, domain->native_mode ? "" : "NOT "));
1740
1741         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1742                   domain->name, domain->active_directory ? "" : "NOT "));
1743
1744         cli_rpc_pipe_close(cli);
1745         
1746         talloc_destroy(mem_ctx);
1747
1748         domain->initialized = True;
1749 }
1750
1751 /**********************************************************************
1752  Set the domain_flags (trust attributes, domain operating modes, etc... 
1753 ***********************************************************************/
1754
1755 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1756 {
1757         /* we always have to contact our primary domain */
1758
1759         if ( domain->primary ) {
1760                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1761                           "primary domain\n"));
1762                 set_dc_type_and_flags_connect( domain );
1763                 return;         
1764         }
1765
1766         /* Use our DC to get the information if possible */
1767
1768         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1769                 /* Otherwise, fallback to contacting the 
1770                    domain directly */
1771                 set_dc_type_and_flags_connect( domain );
1772         }
1773
1774         return;
1775 }
1776
1777
1778
1779 /**********************************************************************
1780 ***********************************************************************/
1781
1782 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1783                                    struct dcinfo **ppdc)
1784 {
1785         NTSTATUS result;
1786         struct rpc_pipe_client *netlogon_pipe;
1787
1788         if (lp_client_schannel() == False) {
1789                 return False;
1790         }
1791
1792         result = cm_connect_netlogon(domain, &netlogon_pipe);
1793         if (!NT_STATUS_IS_OK(result)) {
1794                 return False;
1795         }
1796
1797         /* Return a pointer to the struct dcinfo from the
1798            netlogon pipe. */
1799
1800         *ppdc = domain->conn.netlogon_pipe->dc;
1801         return True;
1802 }
1803
1804 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1805                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1806 {
1807         struct winbindd_cm_conn *conn;
1808         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1809         fstring conn_pwd;
1810         struct dcinfo *p_dcinfo;
1811
1812         result = init_dc_connection(domain);
1813         if (!NT_STATUS_IS_OK(result)) {
1814                 return result;
1815         }
1816
1817         conn = &domain->conn;
1818
1819         if (conn->samr_pipe != NULL) {
1820                 goto done;
1821         }
1822
1823         /*
1824          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1825          * sign and sealed pipe using the machine account password by
1826          * preference. If we can't - try schannel, if that fails, try
1827          * anonymous.
1828          */
1829
1830         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1831         if ((conn->cli->user_name[0] == '\0') ||
1832             (conn->cli->domain[0] == '\0') || 
1833             (conn_pwd[0] == '\0')) {
1834                 DEBUG(10, ("cm_connect_sam: No no user available for "
1835                            "domain %s, trying schannel\n", conn->cli->domain));
1836                 goto schannel;
1837         }
1838
1839         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1840            authenticated SAMR pipe with sign & seal. */
1841         conn->samr_pipe =
1842                 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1843                                                  PIPE_AUTH_LEVEL_PRIVACY,
1844                                                  conn->cli->domain,
1845                                                  conn->cli->user_name,
1846                                                  conn_pwd, &result);
1847
1848         if (conn->samr_pipe == NULL) {
1849                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1850                           "pipe for domain %s using NTLMSSP "
1851                           "authenticated pipe: user %s\\%s. Error was "
1852                           "%s\n", domain->name, conn->cli->domain,
1853                           conn->cli->user_name, nt_errstr(result)));
1854                 goto schannel;
1855         }
1856
1857         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1858                   "domain %s using NTLMSSP authenticated "
1859                   "pipe: user %s\\%s\n", domain->name,
1860                   conn->cli->domain, conn->cli->user_name ));
1861
1862         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1863                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1864                                      &conn->sam_connect_handle);
1865         if (NT_STATUS_IS_OK(result)) {
1866                 goto open_domain;
1867         }
1868         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1869                   "failed for domain %s, error was %s. Trying schannel\n",
1870                   domain->name, nt_errstr(result) ));
1871         cli_rpc_pipe_close(conn->samr_pipe);
1872
1873  schannel:
1874
1875         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1876
1877         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1878                 /* If this call fails - conn->cli can now be NULL ! */
1879                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1880                            "for domain %s, trying anon\n", domain->name));
1881                 goto anonymous;
1882         }
1883         conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1884                 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1885                  domain->name, p_dcinfo, &result);
1886
1887         if (conn->samr_pipe == NULL) {
1888                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1889                           "domain %s using schannel. Error was %s\n",
1890                           domain->name, nt_errstr(result) ));
1891                 goto anonymous;
1892         }
1893         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1894                   "schannel.\n", domain->name ));
1895
1896         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1897                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1898                                      &conn->sam_connect_handle);
1899         if (NT_STATUS_IS_OK(result)) {
1900                 goto open_domain;
1901         }
1902         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1903                   "for domain %s, error was %s. Trying anonymous\n",
1904                   domain->name, nt_errstr(result) ));
1905         cli_rpc_pipe_close(conn->samr_pipe);
1906
1907  anonymous:
1908
1909         /* Finally fall back to anonymous. */
1910         conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1911                                                    &result);
1912
1913         if (conn->samr_pipe == NULL) {
1914                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1915                 goto done;
1916         }
1917
1918         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1919                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1920                                      &conn->sam_connect_handle);
1921         if (!NT_STATUS_IS_OK(result)) {
1922                 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1923                           "for domain %s Error was %s\n",
1924                           domain->name, nt_errstr(result) ));
1925                 goto done;
1926         }
1927
1928  open_domain:
1929         result = rpccli_samr_open_domain(conn->samr_pipe,
1930                                          mem_ctx,
1931                                          &conn->sam_connect_handle,
1932                                          SEC_RIGHTS_MAXIMUM_ALLOWED,
1933                                          &domain->sid,
1934                                          &conn->sam_domain_handle);
1935
1936  done:
1937
1938         if (!NT_STATUS_IS_OK(result)) {
1939                 invalidate_cm_connection(conn);
1940                 return result;
1941         }
1942
1943         *cli = conn->samr_pipe;
1944         *sam_handle = conn->sam_domain_handle;
1945         return result;
1946 }
1947
1948 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1949                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1950 {
1951         struct winbindd_cm_conn *conn;
1952         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1953         fstring conn_pwd;
1954         struct dcinfo *p_dcinfo;
1955
1956         result = init_dc_connection(domain);
1957         if (!NT_STATUS_IS_OK(result))
1958                 return result;
1959
1960         conn = &domain->conn;
1961
1962         if (conn->lsa_pipe != NULL) {
1963                 goto done;
1964         }
1965
1966         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1967         if ((conn->cli->user_name[0] == '\0') ||
1968             (conn->cli->domain[0] == '\0') || 
1969             (conn_pwd[0] == '\0')) {
1970                 DEBUG(10, ("cm_connect_lsa: No no user available for "
1971                            "domain %s, trying schannel\n", conn->cli->domain));
1972                 goto schannel;
1973         }
1974
1975         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1976          * authenticated LSA pipe with sign & seal. */
1977         conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1978                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1979                  conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1980
1981         if (conn->lsa_pipe == NULL) {
1982                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1983                           "domain %s using NTLMSSP authenticated pipe: user "
1984                           "%s\\%s. Error was %s. Trying schannel.\n",
1985                           domain->name, conn->cli->domain,
1986                           conn->cli->user_name, nt_errstr(result)));
1987                 goto schannel;
1988         }
1989
1990         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1991                   "NTLMSSP authenticated pipe: user %s\\%s\n",
1992                   domain->name, conn->cli->domain, conn->cli->user_name ));
1993
1994         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1995                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1996                                         &conn->lsa_policy);
1997         if (NT_STATUS_IS_OK(result)) {
1998                 goto done;
1999         }
2000
2001         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2002                   "schannel\n"));
2003
2004         cli_rpc_pipe_close(conn->lsa_pipe);
2005
2006  schannel:
2007
2008         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2009
2010         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2011                 /* If this call fails - conn->cli can now be NULL ! */
2012                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2013                            "for domain %s, trying anon\n", domain->name));
2014                 goto anonymous;
2015         }
2016         conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2017                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2018                  domain->name, p_dcinfo, &result);
2019
2020         if (conn->lsa_pipe == NULL) {
2021                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2022                           "domain %s using schannel. Error was %s\n",
2023                           domain->name, nt_errstr(result) ));
2024                 goto anonymous;
2025         }
2026         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2027                   "schannel.\n", domain->name ));
2028
2029         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2030                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2031                                         &conn->lsa_policy);
2032         if (NT_STATUS_IS_OK(result)) {
2033                 goto done;
2034         }
2035
2036         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2037                   "anonymous\n"));
2038
2039         cli_rpc_pipe_close(conn->lsa_pipe);
2040
2041  anonymous:
2042
2043         conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2044                                                   &result);
2045         if (conn->lsa_pipe == NULL) {
2046                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2047                 goto done;
2048         }
2049
2050         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2051                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2052                                         &conn->lsa_policy);
2053  done:
2054         if (!NT_STATUS_IS_OK(result)) {
2055                 invalidate_cm_connection(conn);
2056                 return result;
2057         }
2058
2059         *cli = conn->lsa_pipe;
2060         *lsa_policy = conn->lsa_policy;
2061         return result;
2062 }
2063
2064 /****************************************************************************
2065  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2066  session key stored in conn->netlogon_pipe->dc->sess_key.
2067 ****************************************************************************/
2068
2069 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2070                              struct rpc_pipe_client **cli)
2071 {
2072         struct winbindd_cm_conn *conn;
2073         NTSTATUS result;
2074
2075         uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2076         uint8  mach_pwd[16];
2077         uint32  sec_chan_type;
2078         const char *account_name;
2079         struct rpc_pipe_client *netlogon_pipe = NULL;
2080
2081         *cli = NULL;
2082
2083         result = init_dc_connection(domain);
2084         if (!NT_STATUS_IS_OK(result)) {
2085                 return result;
2086         }
2087
2088         conn = &domain->conn;
2089
2090         if (conn->netlogon_pipe != NULL) {
2091                 *cli = conn->netlogon_pipe;
2092                 return NT_STATUS_OK;
2093         }
2094
2095         if (domain->primary && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
2096                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2097         }
2098
2099         netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2100                                                  &result);
2101         if (netlogon_pipe == NULL) {
2102                 return result;
2103         }
2104
2105         if ( !domain->primary ) {
2106                 /* Clear the schannel request bit and drop down */
2107                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2108                 goto no_schannel;
2109         }
2110         
2111         if (lp_client_schannel() != False) {
2112                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2113         }
2114
2115         /* if we are a DC and this is a trusted domain, then we need to use our
2116            domain name in the net_req_auth2() request */
2117
2118         if ( IS_DC
2119                 && !strequal(domain->name, lp_workgroup())
2120                 && lp_allow_trusted_domains() ) 
2121         {
2122                 account_name = lp_workgroup();
2123         } else {
2124                 account_name = domain->primary ?
2125                         global_myname() : domain->name;
2126         }
2127
2128         if (account_name == NULL) {
2129                 cli_rpc_pipe_close(netlogon_pipe);
2130                 return NT_STATUS_NO_MEMORY;
2131         }
2132
2133         result = rpccli_netlogon_setup_creds(
2134                  netlogon_pipe,
2135                  domain->dcname, /* server name. */
2136                  domain->name,   /* domain name */
2137                  global_myname(), /* client name */
2138                  account_name,   /* machine account */
2139                  mach_pwd,       /* machine password */
2140                  sec_chan_type,  /* from get_trust_pw */
2141                  &neg_flags);
2142
2143         if (!NT_STATUS_IS_OK(result)) {
2144                 cli_rpc_pipe_close(netlogon_pipe);
2145                 return result;
2146         }
2147
2148         if ((lp_client_schannel() == True) &&
2149                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2150                 DEBUG(3, ("Server did not offer schannel\n"));
2151                 cli_rpc_pipe_close(netlogon_pipe);
2152                 return NT_STATUS_ACCESS_DENIED;
2153         }
2154
2155  no_schannel:
2156         if ((lp_client_schannel() == False) ||
2157                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2158                 /* We're done - just keep the existing connection to NETLOGON
2159                  * open */
2160                 conn->netlogon_pipe = netlogon_pipe;
2161                 *cli = conn->netlogon_pipe;
2162                 return NT_STATUS_OK;
2163         }
2164
2165         /* Using the credentials from the first pipe, open a signed and sealed
2166            second netlogon pipe. The session key is stored in the schannel
2167            part of the new pipe auth struct.
2168         */
2169
2170         conn->netlogon_pipe =
2171                 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2172                                                     PI_NETLOGON,
2173                                                     PIPE_AUTH_LEVEL_PRIVACY,
2174                                                     domain->name,
2175                                                     netlogon_pipe->dc,
2176                                                     &result);
2177
2178         /* We can now close the initial netlogon pipe. */
2179         cli_rpc_pipe_close(netlogon_pipe);
2180
2181         if (conn->netlogon_pipe == NULL) {
2182                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2183                           "was %s\n", nt_errstr(result)));
2184                           
2185                 /* make sure we return something besides OK */
2186                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2187         }
2188
2189         *cli = conn->netlogon_pipe;
2190         return NT_STATUS_OK;
2191 }