r20296: If we're going to overwrite krb5.conf
[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 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 struct winbindd_domain *domain, struct in_addr ip, fstring name )
1006 {
1007         struct ip_service ip_list;
1008
1009         ip_list.ip = ip;
1010         ip_list.port = 0;
1011
1012 #ifdef WITH_ADS
1013         /* For active directory servers, try to get the ldap server name.
1014            None of these failures should be considered critical for now */
1015
1016         if (lp_security() == SEC_ADS) {
1017                 ADS_STRUCT *ads;
1018
1019                 ads = ads_init(domain->alt_name, domain->name, NULL);
1020                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1021
1022                 if (ads_try_connect( ads, inet_ntoa(ip) ) )  {
1023                         /* We got a cldap packet. */
1024                         fstrcpy(name, ads->config.ldap_server_name);
1025                         namecache_store(name, 0x20, 1, &ip_list);
1026
1027                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1028
1029                         if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1030                                 /* We're going to use this KDC for this realm/domain.
1031                                    If we are using sites, then force the krb5 libs
1032                                    to use this KDC. */
1033
1034                                 create_local_private_krb5_conf_for_domain(domain->alt_name,
1035                                                                 domain->name,
1036                                                                 ip);
1037
1038                                 /* Ensure we contact this DC also. */
1039                                 saf_store( domain->name, name);
1040                                 saf_store( domain->alt_name, name);
1041                         }
1042
1043                         ads_destroy( &ads );
1044                         return True;
1045                 }
1046
1047                 ads_destroy( &ads );
1048         }
1049 #endif
1050
1051         /* try GETDC requests next */
1052         
1053         if (send_getdc_request(ip, domain->name, &domain->sid)) {
1054                 int i;
1055                 smb_msleep(100);
1056                 for (i=0; i<5; i++) {
1057                         if (receive_getdc_response(ip, domain->name, name)) {
1058                                 namecache_store(name, 0x20, 1, &ip_list);
1059                                 return True;
1060                         }
1061                         smb_msleep(500);
1062                 }
1063         }
1064
1065         /* try node status request */
1066
1067         if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1068                 namecache_store(name, 0x20, 1, &ip_list);
1069                 return True;
1070         }
1071         return False;
1072 }
1073
1074 /*******************************************************************
1075  Retreive a list of IP address for domain controllers.  Fill in 
1076  the dcs[]  with results.
1077 *******************************************************************/
1078
1079 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1080                     struct dc_name_ip **dcs, int *num_dcs)
1081 {
1082         fstring dcname;
1083         struct  in_addr ip;
1084         struct  ip_service *ip_list = NULL;
1085         int     iplist_size = 0;
1086         int     i;
1087         BOOL    is_our_domain;
1088         enum security_types sec = (enum security_types)lp_security();
1089
1090         is_our_domain = strequal(domain->name, lp_workgroup());
1091
1092         if ( !is_our_domain 
1093                 && get_dc_name_via_netlogon(domain, dcname, &ip) 
1094                 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1095         {
1096                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1097                            dcname, inet_ntoa(ip)));
1098                 return True;
1099         }
1100
1101         if (sec == SEC_ADS) {
1102                 /* We need to make sure we know the local site before
1103                    doing any DNS queries, as this will restrict the
1104                    get_sorted_dc_list() call below to only fetching
1105                    DNS records for the correct site. */
1106
1107                 /* Find any DC to get the site record.
1108                    We deliberately don't care about the
1109                    return here. */
1110                 get_dc_name(domain->name, lp_realm(), dcname, &ip);
1111
1112                 /* Now do the site-specific AD dns lookup. */
1113                 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
1114         }
1115
1116         /* try standard netbios queries if no ADS */
1117
1118         if (iplist_size==0) 
1119                 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
1120
1121         /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1122
1123         /* now add to the dc array.  We'll wait until the last minute 
1124            to look up the name of the DC.  But we fill in the char* for 
1125            the ip now in to make the failed connection cache work */
1126
1127         for ( i=0; i<iplist_size; i++ ) {
1128                 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip), 
1129                         ip_list[i].ip, dcs, num_dcs);
1130         }
1131
1132         SAFE_FREE( ip_list );
1133
1134         return True;
1135 }
1136
1137 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1138                         const struct winbindd_domain *domain,
1139                         fstring dcname, struct sockaddr_in *addr, int *fd)
1140 {
1141         struct dc_name_ip *dcs = NULL;
1142         int num_dcs = 0;
1143
1144         const char **dcnames = NULL;
1145         int num_dcnames = 0;
1146
1147         struct sockaddr_in *addrs = NULL;
1148         int num_addrs = 0;
1149
1150         int i, fd_index;
1151
1152  again:
1153         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1154                 return False;
1155
1156         for (i=0; i<num_dcs; i++) {
1157
1158                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1159                                     &dcnames, &num_dcnames)) {
1160                         return False;
1161                 }
1162                 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1163                                       &addrs, &num_addrs)) {
1164                         return False;
1165                 }
1166
1167                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1168                                     &dcnames, &num_dcnames)) {
1169                         return False;
1170                 }
1171                 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1172                                       &addrs, &num_addrs)) {
1173                         return False;
1174                 }
1175         }
1176
1177         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1178                 return False;
1179
1180         if ((addrs == NULL) || (dcnames == NULL))
1181                 return False;
1182
1183         /* 5 second timeout. */
1184         if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) 
1185         {
1186                 for (i=0; i<num_dcs; i++) {
1187                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1188                                 "domain %s address %s. Error was %s\n",
1189                                 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1190                         winbind_add_failed_connection_entry(domain,
1191                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1192                 }
1193                 return False;
1194         }
1195
1196         *addr = addrs[fd_index];
1197
1198         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1199                 /* Ok, we've got a name for the DC */
1200                 fstrcpy(dcname, dcnames[fd_index]);
1201                 return True;
1202         }
1203
1204         /* Try to figure out the name */
1205         if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1206                 return True;
1207         }
1208
1209         /* We can not continue without the DC's name */
1210         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1211                                     NT_STATUS_UNSUCCESSFUL);
1212         goto again;
1213 }
1214
1215 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1216                                    struct winbindd_cm_conn *new_conn)
1217 {
1218         TALLOC_CTX *mem_ctx;
1219         NTSTATUS result;
1220         char *saf_servername = saf_fetch( domain->name );
1221         int retries;
1222
1223         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1224                 SAFE_FREE(saf_servername);
1225                 set_domain_offline(domain);
1226                 return NT_STATUS_NO_MEMORY;
1227         }
1228
1229         /* we have to check the server affinity cache here since 
1230            later we selecte a DC based on response time and not preference */
1231            
1232         /* Check the negative connection cache
1233            before talking to it. It going down may have
1234            triggered the reconnection. */
1235
1236         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1237
1238                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1239                         saf_servername, domain->name ));
1240
1241                 /* convert an ip address to a name */
1242                 if ( is_ipaddress( saf_servername ) ) {
1243                         fstring saf_name;
1244                         struct in_addr ip;
1245
1246                         ip = *interpret_addr2( saf_servername );
1247                         if (dcip_to_name( domain, ip, saf_name )) {
1248                                 fstrcpy( domain->dcname, saf_name );
1249                         } else {
1250                                 winbind_add_failed_connection_entry(
1251                                         domain, saf_servername,
1252                                         NT_STATUS_UNSUCCESSFUL);
1253                         }
1254                 } else {
1255                         fstrcpy( domain->dcname, saf_servername );
1256                 }
1257
1258                 SAFE_FREE( saf_servername );
1259         }
1260
1261         for (retries = 0; retries < 3; retries++) {
1262
1263                 int fd = -1;
1264                 BOOL retry = False;
1265
1266                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1267
1268                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1269                         domain->dcname, domain->name ));
1270
1271                 if (*domain->dcname 
1272                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1273                         && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1274                 {
1275                         struct sockaddr_in *addrs = NULL;
1276                         int num_addrs = 0;
1277                         int dummy = 0;
1278
1279                         if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1280                                 set_domain_offline(domain);
1281                                 talloc_destroy(mem_ctx);
1282                                 return NT_STATUS_NO_MEMORY;
1283                         }
1284                         if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1285                                 set_domain_offline(domain);
1286                                 talloc_destroy(mem_ctx);
1287                                 return NT_STATUS_NO_MEMORY;
1288                         }
1289
1290                         /* 5 second timeout. */
1291                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1292                                 fd = -1;
1293                         }
1294                 }
1295
1296                 if ((fd == -1) 
1297                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1298                 {
1299                         /* This is the one place where we will
1300                            set the global winbindd offline state
1301                            to true, if a "WINBINDD_OFFLINE" entry
1302                            is found in the winbindd cache. */
1303                         set_global_winbindd_state_offline();
1304                         break;
1305                 }
1306
1307                 new_conn->cli = NULL;
1308
1309                 result = cm_prepare_connection(domain, fd, domain->dcname,
1310                         &new_conn->cli, &retry);
1311
1312                 if (!retry)
1313                         break;
1314         }
1315
1316         if (NT_STATUS_IS_OK(result)) {
1317                 if (domain->online == False) {
1318                         /* We're changing state from offline to online. */
1319                         set_global_winbindd_state_online();
1320                 }
1321                 set_domain_online(domain);
1322         } else {
1323                 /* Ensure we setup the retry handler. */
1324                 set_domain_offline(domain);
1325         }
1326
1327         talloc_destroy(mem_ctx);
1328         return result;
1329 }
1330
1331 /* Close down all open pipes on a connection. */
1332
1333 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1334 {
1335         /* We're closing down a possibly dead
1336            connection. Don't have impossibly long (10s) timeouts. */
1337
1338         if (conn->cli) {
1339                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1340         }
1341
1342         if (conn->samr_pipe != NULL) {
1343                 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1344                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1345                         if (conn->cli) {
1346                                 cli_set_timeout(conn->cli, 500);
1347                         }
1348                 }
1349                 conn->samr_pipe = NULL;
1350         }
1351
1352         if (conn->lsa_pipe != NULL) {
1353                 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1354                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1355                         if (conn->cli) {
1356                                 cli_set_timeout(conn->cli, 500);
1357                         }
1358                 }
1359                 conn->lsa_pipe = NULL;
1360         }
1361
1362         if (conn->netlogon_pipe != NULL) {
1363                 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1364                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1365                         if (conn->cli) {
1366                                 cli_set_timeout(conn->cli, 500);
1367                         }
1368                 }
1369                 conn->netlogon_pipe = NULL;
1370         }
1371
1372         if (conn->cli) {
1373                 cli_shutdown(conn->cli);
1374         }
1375
1376         conn->cli = NULL;
1377 }
1378
1379 void close_conns_after_fork(void)
1380 {
1381         struct winbindd_domain *domain;
1382
1383         for (domain = domain_list(); domain; domain = domain->next) {
1384                 if (domain->conn.cli == NULL)
1385                         continue;
1386
1387                 if (domain->conn.cli->fd == -1)
1388                         continue;
1389
1390                 close(domain->conn.cli->fd);
1391                 domain->conn.cli->fd = -1;
1392         }
1393 }
1394
1395 static BOOL connection_ok(struct winbindd_domain *domain)
1396 {
1397         if (domain->conn.cli == NULL) {
1398                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1399                           "cli!\n", domain->dcname, domain->name));
1400                 return False;
1401         }
1402
1403         if (!domain->conn.cli->initialised) {
1404                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1405                           "initialised!\n", domain->dcname, domain->name));
1406                 return False;
1407         }
1408
1409         if (domain->conn.cli->fd == -1) {
1410                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1411                           "never started (fd == -1)\n", 
1412                           domain->dcname, domain->name));
1413                 return False;
1414         }
1415
1416         if (domain->online == False) {
1417                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1418                 return False;
1419         }
1420
1421         return True;
1422 }
1423
1424 /* Initialize a new connection up to the RPC BIND.
1425    Bypass online status check so always does network calls. */
1426
1427 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1428 {
1429         NTSTATUS result;
1430
1431         /* Internal connections never use the network. */
1432         if (domain->internal) {
1433                 domain->initialized = True;
1434                 return NT_STATUS_OK;
1435         }
1436
1437         if (connection_ok(domain)) {
1438                 if (!domain->initialized) {
1439                         set_dc_type_and_flags(domain);
1440                 }
1441                 return NT_STATUS_OK;
1442         }
1443
1444         invalidate_cm_connection(&domain->conn);
1445
1446         result = cm_open_connection(domain, &domain->conn);
1447
1448         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1449                 set_dc_type_and_flags(domain);
1450         }
1451
1452         return result;
1453 }
1454
1455 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1456 {
1457         if (domain->initialized && !domain->online) {
1458                 /* We check for online status elsewhere. */
1459                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1460         }
1461
1462         return init_dc_connection_network(domain);
1463 }
1464
1465 /******************************************************************************
1466  We can 'sense' certain things about the DC by it's replies to certain
1467  questions.
1468
1469  This tells us if this particular remote server is Active Directory, and if it
1470  is native mode.
1471 ******************************************************************************/
1472
1473 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1474 {
1475         NTSTATUS                result;
1476         DS_DOMINFO_CTR          ctr;
1477         TALLOC_CTX              *mem_ctx = NULL;
1478         struct rpc_pipe_client  *cli;
1479         POLICY_HND pol;
1480
1481         char *domain_name = NULL;
1482         char *dns_name = NULL;
1483         DOM_SID *dom_sid = NULL;
1484
1485         ZERO_STRUCT( ctr );
1486         
1487         if (!connection_ok(domain)) {
1488                 return;
1489         }
1490
1491         DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1492
1493         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1494                                        &result);
1495
1496         if (cli == NULL) {
1497                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1498                           "PI_LSARPC_DS on domain %s: (%s)\n",
1499                           domain->name, nt_errstr(result)));
1500                 return;
1501         }
1502
1503         result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1504                                              DsRolePrimaryDomainInfoBasic,
1505                                              &ctr);
1506         cli_rpc_pipe_close(cli);
1507
1508         if (!NT_STATUS_IS_OK(result)) {
1509                 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1510                           "on domain %s failed: (%s)\n",
1511                           domain->name, nt_errstr(result)));
1512                 return;
1513         }
1514         
1515         if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1516             !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1517                 domain->native_mode = True;
1518         } else {
1519                 domain->native_mode = False;
1520         }
1521
1522         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1523
1524         if (cli == NULL) {
1525                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1526                           "PI_LSARPC on domain %s: (%s)\n",
1527                           domain->name, nt_errstr(result)));
1528                 cli_rpc_pipe_close(cli);
1529                 return;
1530         }
1531
1532         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1533                               domain->name);
1534         if (!mem_ctx) {
1535                 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1536                 cli_rpc_pipe_close(cli);
1537                 return;
1538         }
1539
1540         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1541                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1542                 
1543         if (NT_STATUS_IS_OK(result)) {
1544                 /* This particular query is exactly what Win2k clients use 
1545                    to determine that the DC is active directory */
1546                 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1547                                                        12, &domain_name,
1548                                                        &dns_name, NULL,
1549                                                        NULL, &dom_sid);
1550         }
1551
1552         if (NT_STATUS_IS_OK(result)) {
1553                 domain->active_directory = True;
1554
1555                 if (domain_name)
1556                         fstrcpy(domain->name, domain_name);
1557
1558                 if (dns_name)
1559                         fstrcpy(domain->alt_name, dns_name);
1560
1561                 if (dom_sid) 
1562                         sid_copy(&domain->sid, dom_sid);
1563         } else {
1564                 domain->active_directory = False;
1565
1566                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1567                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1568                                                 &pol);
1569                         
1570                 if (!NT_STATUS_IS_OK(result))
1571                         goto done;
1572                         
1573                 result = rpccli_lsa_query_info_policy(cli, mem_ctx, 
1574                                                       &pol, 5, &domain_name, 
1575                                                       &dom_sid);
1576                         
1577                 if (NT_STATUS_IS_OK(result)) {
1578                         if (domain_name)
1579                                 fstrcpy(domain->name, domain_name);
1580
1581                         if (dom_sid) 
1582                                 sid_copy(&domain->sid, dom_sid);
1583                 }
1584         }
1585 done:
1586
1587         DEBUG(5, ("set_dc_type_and_flags: domain %s is %snative mode.\n",
1588                   domain->name, domain->native_mode ? "" : "NOT "));
1589
1590         DEBUG(5,("set_dc_type_and_flags: domain %s is %sactive directory.\n",
1591                   domain->name, domain->active_directory ? "" : "NOT "));
1592
1593         cli_rpc_pipe_close(cli);
1594         
1595         talloc_destroy(mem_ctx);
1596
1597         domain->initialized = True;
1598 }
1599
1600 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1601                                    struct dcinfo **ppdc)
1602 {
1603         NTSTATUS result;
1604         struct rpc_pipe_client *netlogon_pipe;
1605
1606         if (lp_client_schannel() == False) {
1607                 return False;
1608         }
1609
1610         result = cm_connect_netlogon(domain, &netlogon_pipe);
1611         if (!NT_STATUS_IS_OK(result)) {
1612                 return False;
1613         }
1614
1615         /* Return a pointer to the struct dcinfo from the
1616            netlogon pipe. */
1617
1618         *ppdc = domain->conn.netlogon_pipe->dc;
1619         return True;
1620 }
1621
1622 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1623                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1624 {
1625         struct winbindd_cm_conn *conn;
1626         NTSTATUS result;
1627         fstring conn_pwd;
1628         struct dcinfo *p_dcinfo;
1629
1630         result = init_dc_connection(domain);
1631         if (!NT_STATUS_IS_OK(result)) {
1632                 return result;
1633         }
1634
1635         conn = &domain->conn;
1636
1637         if (conn->samr_pipe != NULL) {
1638                 goto done;
1639         }
1640
1641         /*
1642          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1643          * sign and sealed pipe using the machine account password by
1644          * preference. If we can't - try schannel, if that fails, try
1645          * anonymous.
1646          */
1647
1648         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1649         if ((conn->cli->user_name[0] == '\0') ||
1650             (conn->cli->domain[0] == '\0') || 
1651             (conn_pwd[0] == '\0')) {
1652                 DEBUG(10, ("cm_connect_sam: No no user available for "
1653                            "domain %s, trying schannel\n", conn->cli->domain));
1654                 goto schannel;
1655         }
1656
1657         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1658            authenticated SAMR pipe with sign & seal. */
1659         conn->samr_pipe =
1660                 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1661                                                  PIPE_AUTH_LEVEL_PRIVACY,
1662                                                  conn->cli->domain,
1663                                                  conn->cli->user_name,
1664                                                  conn_pwd, &result);
1665
1666         if (conn->samr_pipe == NULL) {
1667                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1668                           "pipe for domain %s using NTLMSSP "
1669                           "authenticated pipe: user %s\\%s. Error was "
1670                           "%s\n", domain->name, conn->cli->domain,
1671                           conn->cli->user_name, nt_errstr(result)));
1672                 goto schannel;
1673         }
1674
1675         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1676                   "domain %s using NTLMSSP authenticated "
1677                   "pipe: user %s\\%s\n", domain->name,
1678                   conn->cli->domain, conn->cli->user_name ));
1679
1680         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1681                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1682                                      &conn->sam_connect_handle);
1683         if (NT_STATUS_IS_OK(result)) {
1684                 goto open_domain;
1685         }
1686         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1687                   "failed for domain %s, error was %s. Trying schannel\n",
1688                   domain->name, nt_errstr(result) ));
1689         cli_rpc_pipe_close(conn->samr_pipe);
1690
1691  schannel:
1692
1693         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1694
1695         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1696                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1697                            "for domain %s, trying anon\n", conn->cli->domain));
1698                 goto anonymous;
1699         }
1700         conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1701                 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1702                  domain->name, p_dcinfo, &result);
1703
1704         if (conn->samr_pipe == NULL) {
1705                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1706                           "domain %s using schannel. Error was %s\n",
1707                           domain->name, nt_errstr(result) ));
1708                 goto anonymous;
1709         }
1710         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1711                   "schannel.\n", domain->name ));
1712
1713         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1714                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1715                                      &conn->sam_connect_handle);
1716         if (NT_STATUS_IS_OK(result)) {
1717                 goto open_domain;
1718         }
1719         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1720                   "for domain %s, error was %s. Trying anonymous\n",
1721                   domain->name, nt_errstr(result) ));
1722         cli_rpc_pipe_close(conn->samr_pipe);
1723
1724  anonymous:
1725
1726         /* Finally fall back to anonymous. */
1727         conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1728                                                    &result);
1729
1730         if (conn->samr_pipe == NULL) {
1731                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1732                 goto done;
1733         }
1734
1735         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1736                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1737                                      &conn->sam_connect_handle);
1738         if (!NT_STATUS_IS_OK(result)) {
1739                 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1740                           "for domain %s Error was %s\n",
1741                           domain->name, nt_errstr(result) ));
1742                 goto done;
1743         }
1744
1745  open_domain:
1746         result = rpccli_samr_open_domain(conn->samr_pipe,
1747                                          mem_ctx,
1748                                          &conn->sam_connect_handle,
1749                                          SEC_RIGHTS_MAXIMUM_ALLOWED,
1750                                          &domain->sid,
1751                                          &conn->sam_domain_handle);
1752
1753  done:
1754
1755         if (!NT_STATUS_IS_OK(result)) {
1756                 invalidate_cm_connection(conn);
1757                 return result;
1758         }
1759
1760         *cli = conn->samr_pipe;
1761         *sam_handle = conn->sam_domain_handle;
1762         return result;
1763 }
1764
1765 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1766                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1767 {
1768         struct winbindd_cm_conn *conn;
1769         NTSTATUS result;
1770         fstring conn_pwd;
1771         struct dcinfo *p_dcinfo;
1772
1773         result = init_dc_connection(domain);
1774         if (!NT_STATUS_IS_OK(result))
1775                 return result;
1776
1777         conn = &domain->conn;
1778
1779         if (conn->lsa_pipe != NULL) {
1780                 goto done;
1781         }
1782
1783         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1784         if ((conn->cli->user_name[0] == '\0') ||
1785             (conn->cli->domain[0] == '\0') || 
1786             (conn_pwd[0] == '\0')) {
1787                 DEBUG(10, ("cm_connect_lsa: No no user available for "
1788                            "domain %s, trying schannel\n", conn->cli->domain));
1789                 goto schannel;
1790         }
1791
1792         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1793          * authenticated LSA pipe with sign & seal. */
1794         conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1795                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1796                  conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1797
1798         if (conn->lsa_pipe == NULL) {
1799                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1800                           "domain %s using NTLMSSP authenticated pipe: user "
1801                           "%s\\%s. Error was %s. Trying schannel.\n",
1802                           domain->name, conn->cli->domain,
1803                           conn->cli->user_name, nt_errstr(result)));
1804                 goto schannel;
1805         }
1806
1807         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1808                   "NTLMSSP authenticated pipe: user %s\\%s\n",
1809                   domain->name, conn->cli->domain, conn->cli->user_name ));
1810
1811         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1812                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1813                                         &conn->lsa_policy);
1814         if (NT_STATUS_IS_OK(result)) {
1815                 goto done;
1816         }
1817
1818         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1819                   "schannel\n"));
1820
1821         cli_rpc_pipe_close(conn->lsa_pipe);
1822
1823  schannel:
1824
1825         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1826
1827         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1828                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1829                            "for domain %s, trying anon\n", conn->cli->domain));
1830                 goto anonymous;
1831         }
1832         conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1833                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1834                  domain->name, p_dcinfo, &result);
1835
1836         if (conn->lsa_pipe == NULL) {
1837                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1838                           "domain %s using schannel. Error was %s\n",
1839                           domain->name, nt_errstr(result) ));
1840                 goto anonymous;
1841         }
1842         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1843                   "schannel.\n", domain->name ));
1844
1845         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1846                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1847                                         &conn->lsa_policy);
1848         if (NT_STATUS_IS_OK(result)) {
1849                 goto done;
1850         }
1851
1852         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1853                   "anonymous\n"));
1854
1855         cli_rpc_pipe_close(conn->lsa_pipe);
1856
1857  anonymous:
1858
1859         conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1860                                                   &result);
1861         if (conn->lsa_pipe == NULL) {
1862                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1863                 goto done;
1864         }
1865
1866         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1867                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1868                                         &conn->lsa_policy);
1869  done:
1870         if (!NT_STATUS_IS_OK(result)) {
1871                 invalidate_cm_connection(conn);
1872                 return NT_STATUS_UNSUCCESSFUL;
1873         }
1874
1875         *cli = conn->lsa_pipe;
1876         *lsa_policy = conn->lsa_policy;
1877         return result;
1878 }
1879
1880 /****************************************************************************
1881  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1882  session key stored in conn->netlogon_pipe->dc->sess_key.
1883 ****************************************************************************/
1884
1885 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1886                              struct rpc_pipe_client **cli)
1887 {
1888         struct winbindd_cm_conn *conn;
1889         NTSTATUS result;
1890
1891         uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1892         uint8  mach_pwd[16];
1893         uint32  sec_chan_type;
1894         const char *account_name;
1895         struct rpc_pipe_client *netlogon_pipe = NULL;
1896
1897         *cli = NULL;
1898
1899         result = init_dc_connection(domain);
1900         if (!NT_STATUS_IS_OK(result)) {
1901                 return result;
1902         }
1903
1904         conn = &domain->conn;
1905
1906         if (conn->netlogon_pipe != NULL) {
1907                 *cli = conn->netlogon_pipe;
1908                 return NT_STATUS_OK;
1909         }
1910
1911         if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1912                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1913         }
1914
1915         netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1916                                                  &result);
1917         if (netlogon_pipe == NULL) {
1918                 return result;
1919         }
1920
1921         if (lp_client_schannel() != False) {
1922                 neg_flags |= NETLOGON_NEG_SCHANNEL;
1923         }
1924
1925         /* if we are a DC and this is a trusted domain, then we need to use our
1926            domain name in the net_req_auth2() request */
1927
1928         if ( IS_DC
1929                 && !strequal(domain->name, lp_workgroup())
1930                 && lp_allow_trusted_domains() ) 
1931         {
1932                 account_name = lp_workgroup();
1933         } else {
1934                 account_name = domain->primary ?
1935                         global_myname() : domain->name;
1936         }
1937
1938         if (account_name == NULL) {
1939                 cli_rpc_pipe_close(netlogon_pipe);
1940                 return NT_STATUS_NO_MEMORY;
1941         }
1942
1943         result = rpccli_netlogon_setup_creds(
1944                  netlogon_pipe,
1945                  domain->dcname, /* server name. */
1946                  domain->name,   /* domain name */
1947                  global_myname(), /* client name */
1948                  account_name,   /* machine account */
1949                  mach_pwd,       /* machine password */
1950                  sec_chan_type,  /* from get_trust_pw */
1951                  &neg_flags);
1952
1953         if (!NT_STATUS_IS_OK(result)) {
1954                 cli_rpc_pipe_close(netlogon_pipe);
1955                 return result;
1956         }
1957
1958         if ((lp_client_schannel() == True) &&
1959                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1960                 DEBUG(3, ("Server did not offer schannel\n"));
1961                 cli_rpc_pipe_close(netlogon_pipe);
1962                 return NT_STATUS_ACCESS_DENIED;
1963         }
1964
1965         if ((lp_client_schannel() == False) ||
1966                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1967                 /* We're done - just keep the existing connection to NETLOGON
1968                  * open */
1969                 conn->netlogon_pipe = netlogon_pipe;
1970                 *cli = conn->netlogon_pipe;
1971                 return NT_STATUS_OK;
1972         }
1973
1974         /* Using the credentials from the first pipe, open a signed and sealed
1975            second netlogon pipe. The session key is stored in the schannel
1976            part of the new pipe auth struct.
1977         */
1978
1979         conn->netlogon_pipe =
1980                 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1981                                                     PI_NETLOGON,
1982                                                     PIPE_AUTH_LEVEL_PRIVACY,
1983                                                     domain->name,
1984                                                     netlogon_pipe->dc,
1985                                                     &result);
1986
1987         /* We can now close the initial netlogon pipe. */
1988         cli_rpc_pipe_close(netlogon_pipe);
1989
1990         if (conn->netlogon_pipe == NULL) {
1991                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1992                           "was %s\n", nt_errstr(result)));
1993                           
1994                 /* make sure we return something besides OK */
1995                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
1996         }
1997
1998         *cli = conn->netlogon_pipe;
1999         return NT_STATUS_OK;
2000 }