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