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