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