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