c6dab6f2e6e6ff4fc398bb0a5cd623447e5ab686
[kai/samba.git] / source3 / winbindd / 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 3 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, see <http://www.gnu.org/licenses/>.
24 */
25
26 /*
27    We need to manage connections to domain controllers without having to
28    mess up the main winbindd code with other issues.  The aim of the
29    connection manager is to:
30   
31        - make connections to domain controllers and cache them
32        - re-establish connections when networks or servers go down
33        - centralise the policy on connection timeouts, domain controller
34          selection etc
35        - manage re-entrancy for when winbindd becomes able to handle
36          multiple outstanding rpc requests
37   
38    Why not have connection management as part of the rpc layer like tng?
39    Good question.  This code may morph into libsmb/rpc_cache.c or something
40    like that but at the moment it's simply staying as part of winbind.  I
41    think the TNG architecture of forcing every user of the rpc layer to use
42    the connection caching system is a bad idea.  It should be an optional
43    method of using the routines.
44
45    The TNG design is quite good but I disagree with some aspects of the
46    implementation. -tpot
47
48  */
49
50 /*
51    TODO:
52
53      - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
54        moved down into another function.
55
56      - Take care when destroying cli_structs as they can be shared between
57        various sam handles.
58
59  */
60
61 #include "includes.h"
62 #include "winbindd.h"
63
64 #undef DBGC_CLASS
65 #define DBGC_CLASS DBGC_WINBIND
66
67 struct dc_name_ip {
68         fstring name;
69         struct sockaddr_storage ss;
70 };
71
72 extern struct winbindd_methods reconnect_methods;
73 extern bool override_logfile;
74
75 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
76 static void set_dc_type_and_flags( struct winbindd_domain *domain );
77 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
78                     struct dc_name_ip **dcs, int *num_dcs);
79
80 /****************************************************************
81  Child failed to find DC's. Reschedule check.
82 ****************************************************************/
83
84 static void msg_failed_to_go_online(struct messaging_context *msg,
85                                     void *private_data,
86                                     uint32_t msg_type,
87                                     struct server_id server_id,
88                                     DATA_BLOB *data)
89 {
90         struct winbindd_domain *domain;
91         const char *domainname = (const char *)data->data;
92
93         if (data->data == NULL || data->length == 0) {
94                 return;
95         }
96
97         DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
98
99         for (domain = domain_list(); domain; domain = domain->next) {
100                 if (domain->internal) {
101                         continue;
102                 }
103
104                 if (strequal(domain->name, domainname)) {
105                         if (domain->online) {
106                                 /* We're already online, ignore. */
107                                 DEBUG(5,("msg_fail_to_go_online: domain %s "
108                                         "already online.\n", domainname));
109                                 continue;
110                         }
111
112                         /* Reschedule the online check. */
113                         set_domain_offline(domain);
114                         break;
115                 }
116         }
117 }
118
119 /****************************************************************
120  Actually cause a reconnect from a message.
121 ****************************************************************/
122
123 static void msg_try_to_go_online(struct messaging_context *msg,
124                                  void *private_data,
125                                  uint32_t msg_type,
126                                  struct server_id server_id,
127                                  DATA_BLOB *data)
128 {
129         struct winbindd_domain *domain;
130         const char *domainname = (const char *)data->data;
131
132         if (data->data == NULL || data->length == 0) {
133                 return;
134         }
135
136         DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
137
138         for (domain = domain_list(); domain; domain = domain->next) {
139                 if (domain->internal) {
140                         continue;
141                 }
142
143                 if (strequal(domain->name, domainname)) {
144
145                         if (domain->online) {
146                                 /* We're already online, ignore. */
147                                 DEBUG(5,("msg_try_to_go_online: domain %s "
148                                         "already online.\n", domainname));
149                                 continue;
150                         }
151
152                         /* This call takes care of setting the online
153                            flag to true if we connected, or re-adding
154                            the offline handler if false. Bypasses online
155                            check so always does network calls. */
156
157                         init_dc_connection_network(domain);
158                         break;
159                 }
160         }
161 }
162
163 /****************************************************************
164  Fork a child to try and contact a DC. Do this as contacting a
165  DC requires blocking lookups and we don't want to block our
166  parent.
167 ****************************************************************/
168
169 static bool fork_child_dc_connect(struct winbindd_domain *domain)
170 {
171         struct dc_name_ip *dcs = NULL;
172         int num_dcs = 0;
173         TALLOC_CTX *mem_ctx = NULL;
174         pid_t child_pid;
175         pid_t parent_pid = sys_getpid();
176
177         /* Stop zombies */
178         CatchChild();
179
180         child_pid = sys_fork();
181
182         if (child_pid == -1) {
183                 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
184                 return False;
185         }
186
187         if (child_pid != 0) {
188                 /* Parent */
189                 messaging_register(winbind_messaging_context(), NULL,
190                                    MSG_WINBIND_TRY_TO_GO_ONLINE,
191                                    msg_try_to_go_online);
192                 messaging_register(winbind_messaging_context(), NULL,
193                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
194                                    msg_failed_to_go_online);
195                 return True;
196         }
197
198         /* Child. */
199
200         /* Leave messages blocked - we will never process one. */
201
202         if (!reinit_after_fork(winbind_messaging_context(), true)) {
203                 DEBUG(0,("reinit_after_fork() failed\n"));
204                 _exit(0);
205         }
206
207         close_conns_after_fork();
208
209         if (!override_logfile) {
210                 char *logfile;
211                 if (asprintf(&logfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) > 0) {
212                         lp_set_logfile(logfile);
213                         SAFE_FREE(logfile);
214                         reopen_logs();
215                 }
216         }
217
218         mem_ctx = talloc_init("fork_child_dc_connect");
219         if (!mem_ctx) {
220                 DEBUG(0,("talloc_init failed.\n"));
221                 _exit(0);
222         }
223
224         if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
225                 /* Still offline ? Can't find DC's. */
226                 messaging_send_buf(winbind_messaging_context(),
227                                    pid_to_procid(parent_pid),
228                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
229                                    (uint8 *)domain->name,
230                                    strlen(domain->name)+1);
231                 _exit(0);
232         }
233
234         /* We got a DC. Send a message to our parent to get it to
235            try and do the same. */
236
237         messaging_send_buf(winbind_messaging_context(),
238                            pid_to_procid(parent_pid),
239                            MSG_WINBIND_TRY_TO_GO_ONLINE,
240                            (uint8 *)domain->name,
241                            strlen(domain->name)+1);
242         _exit(0);
243 }
244
245 /****************************************************************
246  Handler triggered if we're offline to try and detect a DC.
247 ****************************************************************/
248
249 static void check_domain_online_handler(struct event_context *ctx,
250                                         struct timed_event *te,
251                                         const struct timeval *now,
252                                         void *private_data)
253 {
254         struct winbindd_domain *domain =
255                 (struct winbindd_domain *)private_data;
256
257         DEBUG(10,("check_domain_online_handler: called for domain "
258                   "%s (online = %s)\n", domain->name, 
259                   domain->online ? "True" : "False" ));
260
261         TALLOC_FREE(domain->check_online_event);
262
263         /* Are we still in "startup" mode ? */
264
265         if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
266                 /* No longer in "startup" mode. */
267                 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
268                         domain->name ));
269                 domain->startup = False;
270         }
271
272         /* We've been told to stay offline, so stay
273            that way. */
274
275         if (get_global_winbindd_state_offline()) {
276                 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
277                         domain->name ));
278                 return;
279         }
280
281         /* Fork a child to test if it can contact a DC. 
282            If it can then send ourselves a message to
283            cause a reconnect. */
284
285         fork_child_dc_connect(domain);
286 }
287
288 /****************************************************************
289  If we're still offline setup the timeout check.
290 ****************************************************************/
291
292 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
293 {
294         int wbc = lp_winbind_cache_time();
295         int domain_online_check;
296
297         /*
298          * If "winbind:online check timeout" is set explicitly,
299          * override the default of "winbind cache timeout"
300          *
301          * Add this as a parametric option and don't document it. The
302          * whole offline abuse for non-reachable DCs needs
303          * fixing. Till then, use this hackish parameter.
304          */
305
306         domain_online_check = lp_parm_int(-1, "winbind",
307                                           "online check timeout", 0);
308         if (domain_online_check != 0) {
309                 wbc = domain_online_check;
310         }
311
312         if (domain->startup) {
313                 domain->check_online_timeout = 10;
314         } else if (domain->check_online_timeout < wbc) {
315                 domain->check_online_timeout = wbc;
316         }
317 }
318
319 /****************************************************************
320  Set domain offline and also add handler to put us back online
321  if we detect a DC.
322 ****************************************************************/
323
324 void set_domain_offline(struct winbindd_domain *domain)
325 {
326         DEBUG(10,("set_domain_offline: called for domain %s\n",
327                 domain->name ));
328
329         TALLOC_FREE(domain->check_online_event);
330
331         if (domain->internal) {
332                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
333                         domain->name ));
334                 return;
335         }
336
337         domain->online = False;
338
339         /* Offline domains are always initialized. They're
340            re-initialized when they go back online. */
341
342         domain->initialized = True;
343
344         /* We only add the timeout handler that checks and
345            allows us to go back online when we've not
346            been told to remain offline. */
347
348         if (get_global_winbindd_state_offline()) {
349                 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
350                         domain->name ));
351                 return;
352         }
353
354         /* If we're in statup mode, check again in 10 seconds, not in
355            lp_winbind_cache_time() seconds (which is 5 mins by default). */
356
357         calc_new_online_timeout_check(domain);
358
359         domain->check_online_event = event_add_timed(winbind_event_context(),
360                                                 NULL,
361                                                 timeval_current_ofs(domain->check_online_timeout,0),
362                                                 "check_domain_online_handler",
363                                                 check_domain_online_handler,
364                                                 domain);
365
366         /* The above *has* to succeed for winbindd to work. */
367         if (!domain->check_online_event) {
368                 smb_panic("set_domain_offline: failed to add online handler");
369         }
370
371         DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
372                 domain->name ));
373
374         /* Send an offline message to the idmap child when our
375            primary domain goes offline */
376
377         if ( domain->primary ) {
378                 struct winbindd_child *idmap = idmap_child();
379                 
380                 if ( idmap->pid != 0 ) {
381                         messaging_send_buf(winbind_messaging_context(),
382                                            pid_to_procid(idmap->pid), 
383                                            MSG_WINBIND_OFFLINE, 
384                                            (uint8 *)domain->name, 
385                                            strlen(domain->name)+1);
386                 }                       
387         }
388
389         return; 
390 }
391
392 /****************************************************************
393  Set domain online - if allowed.
394 ****************************************************************/
395
396 static void set_domain_online(struct winbindd_domain *domain)
397 {
398         struct timeval now;
399
400         DEBUG(10,("set_domain_online: called for domain %s\n",
401                 domain->name ));
402
403         if (domain->internal) {
404                 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
405                         domain->name ));
406                 return;
407         }
408
409         if (get_global_winbindd_state_offline()) {
410                 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
411                         domain->name ));
412                 return;
413         }
414
415         winbindd_set_locator_kdc_envs(domain);
416
417         /* If we are waiting to get a krb5 ticket, trigger immediately. */
418         GetTimeOfDay(&now);
419         set_event_dispatch_time(winbind_event_context(),
420                                 "krb5_ticket_gain_handler", now);
421
422         /* Ok, we're out of any startup mode now... */
423         domain->startup = False;
424
425         if (domain->online == False) {
426                 /* We were offline - now we're online. We default to
427                    using the MS-RPC backend if we started offline,
428                    and if we're going online for the first time we
429                    should really re-initialize the backends and the
430                    checks to see if we're talking to an AD or NT domain.
431                 */
432
433                 domain->initialized = False;
434
435                 /* 'reconnect_methods' is the MS-RPC backend. */
436                 if (domain->backend == &reconnect_methods) {
437                         domain->backend = NULL;
438                 }
439         }
440
441         /* Ensure we have no online timeout checks. */
442         domain->check_online_timeout = 0;
443         TALLOC_FREE(domain->check_online_event);
444
445         /* Ensure we ignore any pending child messages. */
446         messaging_deregister(winbind_messaging_context(),
447                              MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
448         messaging_deregister(winbind_messaging_context(),
449                              MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
450
451         domain->online = True;
452
453         /* Send an online message to the idmap child when our
454            primary domain comes online */
455
456         if ( domain->primary ) {
457                 struct winbindd_child *idmap = idmap_child();
458                 
459                 if ( idmap->pid != 0 ) {
460                         messaging_send_buf(winbind_messaging_context(),
461                                            pid_to_procid(idmap->pid), 
462                                            MSG_WINBIND_ONLINE, 
463                                            (uint8 *)domain->name, 
464                                            strlen(domain->name)+1);
465                 }                       
466         }
467
468         return; 
469 }
470
471 /****************************************************************
472  Requested to set a domain online.
473 ****************************************************************/
474
475 void set_domain_online_request(struct winbindd_domain *domain)
476 {
477         struct timeval tev;
478
479         DEBUG(10,("set_domain_online_request: called for domain %s\n",
480                 domain->name ));
481
482         if (get_global_winbindd_state_offline()) {
483                 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
484                         domain->name ));
485                 return;
486         }
487
488         /* We've been told it's safe to go online and
489            try and connect to a DC. But I don't believe it
490            because network manager seems to lie.
491            Wait at least 5 seconds. Heuristics suck... */
492
493         if (!domain->check_online_event) {
494                 /* If we've come from being globally offline we
495                    don't have a check online event handler set.
496                    We need to add one now we're trying to go
497                    back online. */
498
499                 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
500                         domain->name ));
501
502                 domain->check_online_event = event_add_timed(winbind_event_context(),
503                                                                 NULL,
504                                                                 timeval_current_ofs(5, 0),
505                                                                 "check_domain_online_handler",
506                                                                 check_domain_online_handler,
507                                                                 domain);
508
509                 /* The above *has* to succeed for winbindd to work. */
510                 if (!domain->check_online_event) {
511                         smb_panic("set_domain_online_request: failed to add online handler");
512                 }
513         }
514
515         GetTimeOfDay(&tev);
516
517         /* Go into "startup" mode again. */
518         domain->startup_time = tev.tv_sec;
519         domain->startup = True;
520
521         tev.tv_sec += 5;
522
523         set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
524 }
525
526 /****************************************************************
527  Add -ve connection cache entries for domain and realm.
528 ****************************************************************/
529
530 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
531                                         const char *server,
532                                         NTSTATUS result)
533 {
534         add_failed_connection_entry(domain->name, server, result);
535         /* If this was the saf name for the last thing we talked to,
536            remove it. */
537         saf_delete(domain->name);
538         if (*domain->alt_name) {
539                 add_failed_connection_entry(domain->alt_name, server, result);
540                 saf_delete(domain->alt_name);
541         }
542         winbindd_unset_locator_kdc_env(domain);
543 }
544
545 /* Choose between anonymous or authenticated connections.  We need to use
546    an authenticated connection if DCs have the RestrictAnonymous registry
547    entry set > 0, or the "Additional restrictions for anonymous
548    connections" set in the win2k Local Security Policy. 
549    
550    Caller to free() result in domain, username, password
551 */
552
553 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
554 {
555         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
556         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
557         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
558         
559         if (*username && **username) {
560
561                 if (!*domain || !**domain)
562                         *domain = smb_xstrdup(lp_workgroup());
563                 
564                 if (!*password || !**password)
565                         *password = smb_xstrdup("");
566
567                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
568                           *domain, *username));
569
570         } else {
571                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
572                 *username = smb_xstrdup("");
573                 *domain = smb_xstrdup("");
574                 *password = smb_xstrdup("");
575         }
576 }
577
578 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
579                                      fstring dcname,
580                                      struct sockaddr_storage *dc_ss)
581 {
582         struct winbindd_domain *our_domain = NULL;
583         struct rpc_pipe_client *netlogon_pipe = NULL;
584         NTSTATUS result;
585         WERROR werr;
586         TALLOC_CTX *mem_ctx;
587         unsigned int orig_timeout;
588         const char *tmp = NULL;
589         const char *p;
590
591         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
592          * moment.... */
593
594         if (IS_DC) {
595                 return False;
596         }
597
598         if (domain->primary) {
599                 return False;
600         }
601
602         our_domain = find_our_domain();
603
604         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
605                 return False;
606         }
607
608         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
609         if (!NT_STATUS_IS_OK(result)) {
610                 talloc_destroy(mem_ctx);
611                 return False;
612         }
613
614         /* This call can take a long time - allow the server to time out.
615            35 seconds should do it. */
616
617         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
618
619         if (our_domain->active_directory) {
620                 struct netr_DsRGetDCNameInfo *domain_info = NULL;
621
622                 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
623                                                   mem_ctx,
624                                                   our_domain->dcname,
625                                                   domain->name,
626                                                   NULL,
627                                                   NULL,
628                                                   DS_RETURN_DNS_NAME,
629                                                   &domain_info,
630                                                   &werr);
631                 if (W_ERROR_IS_OK(werr)) {
632                         tmp = talloc_strdup(
633                                 mem_ctx, domain_info->dc_unc);
634                         if (tmp == NULL) {
635                                 DEBUG(0, ("talloc_strdup failed\n"));
636                                 talloc_destroy(mem_ctx);
637                                 return false;
638                         }
639                         if (strlen(domain->alt_name) == 0) {
640                                 fstrcpy(domain->alt_name,
641                                         domain_info->domain_name);
642                         }
643                         if (strlen(domain->forest_name) == 0) {
644                                 fstrcpy(domain->forest_name,
645                                         domain_info->forest_name);
646                         }
647                 }
648         } else {
649                 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
650                                                   our_domain->dcname,
651                                                   domain->name,
652                                                   &tmp,
653                                                   &werr);
654         }
655
656         /* And restore our original timeout. */
657         rpccli_set_timeout(netlogon_pipe, orig_timeout);
658
659         if (!NT_STATUS_IS_OK(result)) {
660                 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
661                         nt_errstr(result)));
662                 talloc_destroy(mem_ctx);
663                 return false;
664         }
665
666         if (!W_ERROR_IS_OK(werr)) {
667                 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
668                            dos_errstr(werr)));
669                 talloc_destroy(mem_ctx);
670                 return false;
671         }
672
673         /* rpccli_netr_GetAnyDCName gives us a name with \\ */
674         p = strip_hostname(tmp);
675
676         fstrcpy(dcname, p);
677
678         talloc_destroy(mem_ctx);
679
680         DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
681
682         if (!resolve_name(dcname, dc_ss, 0x20)) {
683                 return False;
684         }
685
686         return True;
687 }
688
689 /**
690  * Helper function to assemble trust password and account name
691  */
692 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
693                                 char **machine_password,
694                                 char **machine_account,
695                                 char **machine_krb5_principal)
696 {
697         const char *account_name;
698         const char *name = NULL;
699         
700         /* If we are a DC and this is not our own domain */
701
702         if (IS_DC) {
703                 name = domain->name;
704         } else {
705                 struct winbindd_domain *our_domain = find_our_domain();
706
707                 if (!our_domain)
708                         return NT_STATUS_INVALID_SERVER_STATE;          
709                 
710                 name = our_domain->name;                
711         }       
712         
713         if (!get_trust_pw_clear(name, machine_password,
714                                 &account_name, NULL))
715         {
716                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
717         }
718
719         if ((machine_account != NULL) &&
720             (asprintf(machine_account, "%s$", account_name) == -1))
721         {
722                 return NT_STATUS_NO_MEMORY;
723         }
724
725         /* For now assume our machine account only exists in our domain */
726
727         if (machine_krb5_principal != NULL)
728         {
729                 struct winbindd_domain *our_domain = find_our_domain();
730
731                 if (!our_domain) {
732                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;                       
733                 }
734                 
735                 if (asprintf(machine_krb5_principal, "%s$@%s",
736                              account_name, our_domain->alt_name) == -1)
737                 {
738                         return NT_STATUS_NO_MEMORY;
739                 }
740
741                 strupper_m(*machine_krb5_principal);
742         }
743
744         return NT_STATUS_OK;
745 }
746
747 /************************************************************************
748  Given a fd with a just-connected TCP connection to a DC, open a connection
749  to the pipe.
750 ************************************************************************/
751
752 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
753                                       const int sockfd,
754                                       const char *controller,
755                                       struct cli_state **cli,
756                                       bool *retry)
757 {
758         char *machine_password = NULL;
759         char *machine_krb5_principal = NULL;
760         char *machine_account = NULL;
761         char *ipc_username = NULL;
762         char *ipc_domain = NULL;
763         char *ipc_password = NULL;
764
765         struct named_mutex *mutex;
766
767         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
768
769         struct sockaddr peeraddr;
770         socklen_t peeraddr_len;
771
772         struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
773
774         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
775                 controller, domain->name ));
776
777         *retry = True;
778
779         mutex = grab_named_mutex(talloc_tos(), controller,
780                                  WINBIND_SERVER_MUTEX_WAIT_TIME);
781         if (mutex == NULL) {
782                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
783                          controller));
784                 result = NT_STATUS_POSSIBLE_DEADLOCK;
785                 goto done;
786         }
787
788         if ((*cli = cli_initialise()) == NULL) {
789                 DEBUG(1, ("Could not cli_initialize\n"));
790                 result = NT_STATUS_NO_MEMORY;
791                 goto done;
792         }
793
794         (*cli)->timeout = 10000;        /* 10 seconds */
795         (*cli)->fd = sockfd;
796         fstrcpy((*cli)->desthost, controller);
797         (*cli)->use_kerberos = True;
798
799         peeraddr_len = sizeof(peeraddr);
800
801         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
802             (peeraddr_len != sizeof(struct sockaddr_in)) ||
803             (peeraddr_in->sin_family != PF_INET))
804         {
805                 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
806                 result = NT_STATUS_UNSUCCESSFUL;
807                 goto done;
808         }
809
810         if (ntohs(peeraddr_in->sin_port) == 139) {
811                 struct nmb_name calling;
812                 struct nmb_name called;
813
814                 make_nmb_name(&calling, global_myname(), 0x0);
815                 make_nmb_name(&called, "*SMBSERVER", 0x20);
816
817                 if (!cli_session_request(*cli, &calling, &called)) {
818                         DEBUG(8, ("cli_session_request failed for %s\n",
819                                   controller));
820                         result = NT_STATUS_UNSUCCESSFUL;
821                         goto done;
822                 }
823         }
824
825         cli_setup_signing_state(*cli, Undefined);
826
827         if (!cli_negprot(*cli)) {
828                 DEBUG(1, ("cli_negprot failed\n"));
829                 result = NT_STATUS_UNSUCCESSFUL;
830                 goto done;
831         }
832
833         if (!is_dc_trusted_domain_situation(domain->name) &&
834             (*cli)->protocol >= PROTOCOL_NT1 &&
835             (*cli)->capabilities & CAP_EXTENDED_SECURITY)
836         {
837                 ADS_STATUS ads_status;
838
839                 result = get_trust_creds(domain, &machine_password,
840                                          &machine_account,
841                                          &machine_krb5_principal);
842                 if (!NT_STATUS_IS_OK(result)) {
843                         goto anon_fallback;
844                 }
845
846                 if (lp_security() == SEC_ADS) {
847
848                         /* Try a krb5 session */
849
850                         (*cli)->use_kerberos = True;
851                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
852                                   "[%s] and realm [%s]\n", controller, global_myname(),
853                                   machine_krb5_principal, domain->alt_name));
854
855                         winbindd_set_locator_kdc_envs(domain);
856
857                         ads_status = cli_session_setup_spnego(*cli,
858                                                               machine_krb5_principal, 
859                                                               machine_password,
860                                                               lp_workgroup(),
861                                                               domain->name);
862
863                         if (!ADS_ERR_OK(ads_status)) {
864                                 DEBUG(4,("failed kerberos session setup with %s\n",
865                                          ads_errstr(ads_status)));
866                         }
867
868                         result = ads_ntstatus(ads_status);
869                         if (NT_STATUS_IS_OK(result)) {
870                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
871                                 cli_init_creds(*cli, machine_account, domain->name, machine_password);
872                                 goto session_setup_done;
873                         }
874                 }
875
876                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
877                 (*cli)->use_kerberos = False;
878
879                 DEBUG(5, ("connecting to %s from %s with username "
880                           "[%s]\\[%s]\n",  controller, global_myname(),
881                           lp_workgroup(), machine_account));
882
883                 ads_status = cli_session_setup_spnego(*cli,
884                                                       machine_account, 
885                                                       machine_password, 
886                                                       lp_workgroup(),
887                                                       NULL);
888                 if (!ADS_ERR_OK(ads_status)) {
889                         DEBUG(4, ("authenticated session setup failed with %s\n",
890                                 ads_errstr(ads_status)));
891                 }
892
893                 result = ads_ntstatus(ads_status);
894                 if (NT_STATUS_IS_OK(result)) {
895                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
896                         cli_init_creds(*cli, machine_account, domain->name, machine_password);
897                         goto session_setup_done;
898                 }
899         }
900
901         /* Fall back to non-kerberos session setup with auth_user */
902
903         (*cli)->use_kerberos = False;
904
905         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
906
907         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
908             (strlen(ipc_username) > 0)) {
909
910                 /* Only try authenticated if we have a username */
911
912                 DEBUG(5, ("connecting to %s from %s with username "
913                           "[%s]\\[%s]\n",  controller, global_myname(),
914                           ipc_domain, ipc_username));
915
916                 if (NT_STATUS_IS_OK(cli_session_setup(
917                                             *cli, ipc_username,
918                                             ipc_password, strlen(ipc_password)+1,
919                                             ipc_password, strlen(ipc_password)+1,
920                                             ipc_domain))) {
921                         /* Successful logon with given username. */
922                         cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
923                         goto session_setup_done;
924                 } else {
925                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
926                                 ipc_domain, ipc_username ));
927                 }
928         }
929
930  anon_fallback:
931
932         /* Fall back to anonymous connection, this might fail later */
933
934         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
935                                               NULL, 0, ""))) {
936                 DEBUG(5, ("Connected anonymously\n"));
937                 cli_init_creds(*cli, "", "", "");
938                 goto session_setup_done;
939         }
940
941         result = cli_nt_error(*cli);
942
943         if (NT_STATUS_IS_OK(result))
944                 result = NT_STATUS_UNSUCCESSFUL;
945
946         /* We can't session setup */
947
948         goto done;
949
950  session_setup_done:
951
952         /* cache the server name for later connections */
953
954         saf_store( domain->name, (*cli)->desthost );
955         if (domain->alt_name && (*cli)->use_kerberos) {
956                 saf_store( domain->alt_name, (*cli)->desthost );
957         }
958
959         winbindd_set_locator_kdc_envs(domain);
960
961         if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
962
963                 result = cli_nt_error(*cli);
964
965                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
966
967                 if (NT_STATUS_IS_OK(result))
968                         result = NT_STATUS_UNSUCCESSFUL;
969
970                 goto done;
971         }
972
973         TALLOC_FREE(mutex);
974         *retry = False;
975
976         /* set the domain if empty; needed for schannel connections */
977         if ( !*(*cli)->domain ) {
978                 fstrcpy( (*cli)->domain, domain->name );
979         }
980
981         result = NT_STATUS_OK;
982
983  done:
984         TALLOC_FREE(mutex);
985         SAFE_FREE(machine_account);
986         SAFE_FREE(machine_password);
987         SAFE_FREE(machine_krb5_principal);
988         SAFE_FREE(ipc_username);
989         SAFE_FREE(ipc_domain);
990         SAFE_FREE(ipc_password);
991
992         if (!NT_STATUS_IS_OK(result)) {
993                 winbind_add_failed_connection_entry(domain, controller, result);
994                 if ((*cli) != NULL) {
995                         cli_shutdown(*cli);
996                         *cli = NULL;
997                 }
998         }
999
1000         return result;
1001 }
1002
1003 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1004                               const char *dcname, struct sockaddr_storage *pss,
1005                               struct dc_name_ip **dcs, int *num)
1006 {
1007         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1008                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1009                 return False;
1010         }
1011
1012         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1013
1014         if (*dcs == NULL)
1015                 return False;
1016
1017         fstrcpy((*dcs)[*num].name, dcname);
1018         (*dcs)[*num].ss = *pss;
1019         *num += 1;
1020         return True;
1021 }
1022
1023 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1024                                   struct sockaddr_storage *pss, uint16 port,
1025                                   struct sockaddr_storage **addrs, int *num)
1026 {
1027         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1028
1029         if (*addrs == NULL) {
1030                 *num = 0;
1031                 return False;
1032         }
1033
1034         (*addrs)[*num] = *pss;
1035         set_sockaddr_port(&(*addrs)[*num], port);
1036
1037         *num += 1;
1038         return True;
1039 }
1040
1041 /*******************************************************************
1042  convert an ip to a name
1043 *******************************************************************/
1044
1045 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1046                 const struct winbindd_domain *domain,
1047                 struct sockaddr_storage *pss,
1048                 fstring name )
1049 {
1050         struct ip_service ip_list;
1051         uint32_t nt_version = NETLOGON_VERSION_1;
1052
1053         ip_list.ss = *pss;
1054         ip_list.port = 0;
1055
1056 #ifdef WITH_ADS
1057         /* For active directory servers, try to get the ldap server name.
1058            None of these failures should be considered critical for now */
1059
1060         if (lp_security() == SEC_ADS) {
1061                 ADS_STRUCT *ads;
1062                 ADS_STATUS ads_status;
1063                 char addr[INET6_ADDRSTRLEN];
1064
1065                 print_sockaddr(addr, sizeof(addr), pss);
1066
1067                 ads = ads_init(domain->alt_name, domain->name, addr);
1068                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1069
1070                 ads_status = ads_connect(ads);
1071                 if (ADS_ERR_OK(ads_status)) {
1072                         /* We got a cldap packet. */
1073                         fstrcpy(name, ads->config.ldap_server_name);
1074                         namecache_store(name, 0x20, 1, &ip_list);
1075
1076                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1077
1078                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1079                                 if (ads_closest_dc(ads)) {
1080                                         char *sitename = sitename_fetch(ads->config.realm);
1081
1082                                         /* We're going to use this KDC for this realm/domain.
1083                                            If we are using sites, then force the krb5 libs
1084                                            to use this KDC. */
1085
1086                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1087                                                                         domain->name,
1088                                                                         sitename,
1089                                                                         pss);
1090
1091                                         SAFE_FREE(sitename);
1092                                 } else {
1093                                         /* use an off site KDC */
1094                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1095                                                                         domain->name,
1096                                                                         NULL,
1097                                                                         pss);
1098                                 }
1099                                 winbindd_set_locator_kdc_envs(domain);
1100
1101                                 /* Ensure we contact this DC also. */
1102                                 saf_store( domain->name, name);
1103                                 saf_store( domain->alt_name, name);
1104                         }
1105
1106                         ads_destroy( &ads );
1107                         return True;
1108                 }
1109
1110                 ads_destroy( &ads );
1111         }
1112 #endif
1113
1114         /* try GETDC requests next */
1115
1116         if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1117                                pss, domain->name, &domain->sid,
1118                                nt_version)) {
1119                 const char *dc_name = NULL;
1120                 int i;
1121                 smb_msleep(100);
1122                 for (i=0; i<5; i++) {
1123                         if (receive_getdc_response(mem_ctx, pss, domain->name,
1124                                                    &nt_version,
1125                                                    &dc_name, NULL)) {
1126                                 fstrcpy(name, dc_name);
1127                                 namecache_store(name, 0x20, 1, &ip_list);
1128                                 return True;
1129                         }
1130                         smb_msleep(500);
1131                 }
1132         }
1133
1134         /* try node status request */
1135
1136         if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1137                 namecache_store(name, 0x20, 1, &ip_list);
1138                 return True;
1139         }
1140         return False;
1141 }
1142
1143 /*******************************************************************
1144  Retreive a list of IP address for domain controllers.  Fill in 
1145  the dcs[]  with results.
1146 *******************************************************************/
1147
1148 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1149                     struct dc_name_ip **dcs, int *num_dcs)
1150 {
1151         fstring dcname;
1152         struct  sockaddr_storage ss;
1153         struct  ip_service *ip_list = NULL;
1154         int     iplist_size = 0;
1155         int     i;
1156         bool    is_our_domain;
1157         enum security_types sec = (enum security_types)lp_security();
1158
1159         is_our_domain = strequal(domain->name, lp_workgroup());
1160
1161         if ( !is_our_domain
1162                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1163                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs, num_dcs) )
1164         {
1165                 char addr[INET6_ADDRSTRLEN];
1166                 print_sockaddr(addr, sizeof(addr), &ss);
1167                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1168                            dcname, addr));
1169                 return True;
1170         }
1171
1172         if (sec == SEC_ADS) {
1173                 char *sitename = NULL;
1174
1175                 /* We need to make sure we know the local site before
1176                    doing any DNS queries, as this will restrict the
1177                    get_sorted_dc_list() call below to only fetching
1178                    DNS records for the correct site. */
1179
1180                 /* Find any DC to get the site record.
1181                    We deliberately don't care about the
1182                    return here. */
1183
1184                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1185
1186                 sitename = sitename_fetch(domain->alt_name);
1187                 if (sitename) {
1188
1189                         /* Do the site-specific AD dns lookup first. */
1190                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1191
1192                         for ( i=0; i<iplist_size; i++ ) {
1193                                 char addr[INET6_ADDRSTRLEN];
1194                                 print_sockaddr(addr, sizeof(addr),
1195                                                 &ip_list[i].ss);
1196                                 add_one_dc_unique(mem_ctx,
1197                                                 domain->name,
1198                                                 addr,
1199                                                 &ip_list[i].ss,
1200                                                 dcs,
1201                                                 num_dcs);
1202                         }
1203
1204                         SAFE_FREE(ip_list);
1205                         SAFE_FREE(sitename);
1206                         iplist_size = 0;
1207                 }
1208
1209                 /* Now we add DCs from the main AD dns lookup. */
1210                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1211
1212                 for ( i=0; i<iplist_size; i++ ) {
1213                         char addr[INET6_ADDRSTRLEN];
1214                         print_sockaddr(addr, sizeof(addr),
1215                                         &ip_list[i].ss);
1216                         add_one_dc_unique(mem_ctx,
1217                                         domain->name,
1218                                         addr,
1219                                         &ip_list[i].ss,
1220                                         dcs,
1221                                         num_dcs);
1222                 }
1223         }
1224
1225         /* try standard netbios queries if no ADS */
1226
1227         if (iplist_size==0) {
1228                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1229         }
1230
1231         /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1232
1233         /* now add to the dc array.  We'll wait until the last minute 
1234            to look up the name of the DC.  But we fill in the char* for 
1235            the ip now in to make the failed connection cache work */
1236
1237         for ( i=0; i<iplist_size; i++ ) {
1238                 char addr[INET6_ADDRSTRLEN];
1239                 print_sockaddr(addr, sizeof(addr),
1240                                 &ip_list[i].ss);
1241                 add_one_dc_unique(mem_ctx, domain->name, addr,
1242                         &ip_list[i].ss, dcs, num_dcs);
1243         }
1244
1245         SAFE_FREE( ip_list );
1246
1247         return True;
1248 }
1249
1250 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1251                         struct winbindd_domain *domain,
1252                         fstring dcname, struct sockaddr_storage *pss, int *fd)
1253 {
1254         struct dc_name_ip *dcs = NULL;
1255         int num_dcs = 0;
1256
1257         const char **dcnames = NULL;
1258         int num_dcnames = 0;
1259
1260         struct sockaddr_storage *addrs = NULL;
1261         int num_addrs = 0;
1262
1263         int i, fd_index;
1264
1265         *fd = -1;
1266
1267  again:
1268         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1269                 return False;
1270
1271         for (i=0; i<num_dcs; i++) {
1272
1273                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1274                                     &dcnames, &num_dcnames)) {
1275                         return False;
1276                 }
1277                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1278                                       &addrs, &num_addrs)) {
1279                         return False;
1280                 }
1281
1282                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1283                                     &dcnames, &num_dcnames)) {
1284                         return False;
1285                 }
1286                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1287                                       &addrs, &num_addrs)) {
1288                         return False;
1289                 }
1290         }
1291
1292         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1293                 return False;
1294
1295         if ((addrs == NULL) || (dcnames == NULL))
1296                 return False;
1297
1298         /* 5 second timeout. */
1299         if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1300                 for (i=0; i<num_dcs; i++) {
1301                         char ab[INET6_ADDRSTRLEN];
1302                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1303                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1304                                 "domain %s address %s. Error was %s\n",
1305                                 domain->name, ab, strerror(errno) ));
1306                         winbind_add_failed_connection_entry(domain,
1307                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1308                 }
1309                 return False;
1310         }
1311
1312         *pss = addrs[fd_index];
1313
1314         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1315                 /* Ok, we've got a name for the DC */
1316                 fstrcpy(dcname, dcnames[fd_index]);
1317                 return True;
1318         }
1319
1320         /* Try to figure out the name */
1321         if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1322                 return True;
1323         }
1324
1325         /* We can not continue without the DC's name */
1326         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1327                                     NT_STATUS_UNSUCCESSFUL);
1328
1329         /* Throw away all arrays as we're doing this again. */
1330         TALLOC_FREE(dcs);
1331         num_dcs = 0;
1332
1333         TALLOC_FREE(dcnames);
1334         num_dcnames = 0;
1335         
1336         TALLOC_FREE(addrs);
1337         num_addrs = 0;
1338
1339         close(*fd);
1340         *fd = -1;
1341
1342         goto again;
1343 }
1344
1345 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1346                                    struct winbindd_cm_conn *new_conn)
1347 {
1348         TALLOC_CTX *mem_ctx;
1349         NTSTATUS result;
1350         char *saf_servername = saf_fetch( domain->name );
1351         int retries;
1352
1353         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1354                 SAFE_FREE(saf_servername);
1355                 set_domain_offline(domain);
1356                 return NT_STATUS_NO_MEMORY;
1357         }
1358
1359         /* we have to check the server affinity cache here since 
1360            later we selecte a DC based on response time and not preference */
1361            
1362         /* Check the negative connection cache
1363            before talking to it. It going down may have
1364            triggered the reconnection. */
1365
1366         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1367
1368                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1369                         saf_servername, domain->name ));
1370
1371                 /* convert an ip address to a name */
1372                 if (is_ipaddress( saf_servername ) ) {
1373                         fstring saf_name;
1374                         struct sockaddr_storage ss;
1375
1376                         if (!interpret_string_addr(&ss, saf_servername,
1377                                                 AI_NUMERICHOST)) {
1378                                 return NT_STATUS_UNSUCCESSFUL;
1379                         }
1380                         if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1381                                 fstrcpy( domain->dcname, saf_name );
1382                         } else {
1383                                 winbind_add_failed_connection_entry(
1384                                         domain, saf_servername,
1385                                         NT_STATUS_UNSUCCESSFUL);
1386                         }
1387                 } else {
1388                         fstrcpy( domain->dcname, saf_servername );
1389                 }
1390
1391                 SAFE_FREE( saf_servername );
1392         }
1393
1394         for (retries = 0; retries < 3; retries++) {
1395                 int fd = -1;
1396                 bool retry = False;
1397
1398                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1399
1400                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1401                         domain->dcname, domain->name ));
1402
1403                 if (*domain->dcname 
1404                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1405                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1406                 {
1407                         struct sockaddr_storage *addrs = NULL;
1408                         int num_addrs = 0;
1409                         int dummy = 0;
1410
1411                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1412                                 set_domain_offline(domain);
1413                                 talloc_destroy(mem_ctx);
1414                                 return NT_STATUS_NO_MEMORY;
1415                         }
1416                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1417                                 set_domain_offline(domain);
1418                                 talloc_destroy(mem_ctx);
1419                                 return NT_STATUS_NO_MEMORY;
1420                         }
1421
1422                         /* 5 second timeout. */
1423                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1424                                 fd = -1;
1425                         }
1426                 }
1427
1428                 if ((fd == -1) 
1429                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1430                 {
1431                         /* This is the one place where we will
1432                            set the global winbindd offline state
1433                            to true, if a "WINBINDD_OFFLINE" entry
1434                            is found in the winbindd cache. */
1435                         set_global_winbindd_state_offline();
1436                         break;
1437                 }
1438
1439                 new_conn->cli = NULL;
1440
1441                 result = cm_prepare_connection(domain, fd, domain->dcname,
1442                         &new_conn->cli, &retry);
1443
1444                 if (!retry)
1445                         break;
1446         }
1447
1448         if (NT_STATUS_IS_OK(result)) {
1449
1450                 winbindd_set_locator_kdc_envs(domain);
1451
1452                 if (domain->online == False) {
1453                         /* We're changing state from offline to online. */
1454                         set_global_winbindd_state_online();
1455                 }
1456                 set_domain_online(domain);
1457         } else {
1458                 /* Ensure we setup the retry handler. */
1459                 set_domain_offline(domain);
1460         }
1461
1462         talloc_destroy(mem_ctx);
1463         return result;
1464 }
1465
1466 /* Close down all open pipes on a connection. */
1467
1468 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1469 {
1470         /* We're closing down a possibly dead
1471            connection. Don't have impossibly long (10s) timeouts. */
1472
1473         if (conn->cli) {
1474                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1475         }
1476
1477         if (conn->samr_pipe != NULL) {
1478                 TALLOC_FREE(conn->samr_pipe);
1479                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1480                 if (conn->cli) {
1481                         cli_set_timeout(conn->cli, 500);
1482                 }
1483         }
1484
1485         if (conn->lsa_pipe != NULL) {
1486                 TALLOC_FREE(conn->lsa_pipe);
1487                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1488                 if (conn->cli) {
1489                         cli_set_timeout(conn->cli, 500);
1490                 }
1491         }
1492
1493         if (conn->netlogon_pipe != NULL) {
1494                 TALLOC_FREE(conn->netlogon_pipe);
1495                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1496                 if (conn->cli) {
1497                         cli_set_timeout(conn->cli, 500);
1498                 }
1499         }
1500
1501         if (conn->cli) {
1502                 cli_shutdown(conn->cli);
1503         }
1504
1505         conn->cli = NULL;
1506 }
1507
1508 void close_conns_after_fork(void)
1509 {
1510         struct winbindd_domain *domain;
1511
1512         for (domain = domain_list(); domain; domain = domain->next) {
1513                 if (domain->conn.cli == NULL)
1514                         continue;
1515
1516                 if (domain->conn.cli->fd == -1)
1517                         continue;
1518
1519                 close(domain->conn.cli->fd);
1520                 domain->conn.cli->fd = -1;
1521         }
1522 }
1523
1524 static bool connection_ok(struct winbindd_domain *domain)
1525 {
1526         if (domain->conn.cli == NULL) {
1527                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1528                           "cli!\n", domain->dcname, domain->name));
1529                 return False;
1530         }
1531
1532         if (!domain->conn.cli->initialised) {
1533                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1534                           "initialised!\n", domain->dcname, domain->name));
1535                 return False;
1536         }
1537
1538         if (domain->conn.cli->fd == -1) {
1539                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1540                           "never started (fd == -1)\n", 
1541                           domain->dcname, domain->name));
1542                 return False;
1543         }
1544
1545         if (domain->online == False) {
1546                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1547                 return False;
1548         }
1549
1550         return True;
1551 }
1552
1553 /* Initialize a new connection up to the RPC BIND.
1554    Bypass online status check so always does network calls. */
1555
1556 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1557 {
1558         NTSTATUS result;
1559
1560         /* Internal connections never use the network. */
1561         if (domain->internal) {
1562                 domain->initialized = True;
1563                 return NT_STATUS_OK;
1564         }
1565
1566         if (connection_ok(domain)) {
1567                 if (!domain->initialized) {
1568                         set_dc_type_and_flags(domain);
1569                 }
1570                 return NT_STATUS_OK;
1571         }
1572
1573         invalidate_cm_connection(&domain->conn);
1574
1575         result = cm_open_connection(domain, &domain->conn);
1576
1577         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1578                 set_dc_type_and_flags(domain);
1579         }
1580
1581         return result;
1582 }
1583
1584 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1585 {
1586         if (domain->initialized && !domain->online) {
1587                 /* We check for online status elsewhere. */
1588                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1589         }
1590
1591         return init_dc_connection_network(domain);
1592 }
1593
1594 /******************************************************************************
1595  Set the trust flags (direction and forest location) for a domain
1596 ******************************************************************************/
1597
1598 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1599 {
1600         struct winbindd_domain *our_domain;
1601         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1602         struct netr_DomainTrustList trusts;
1603         int i;
1604         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1605                         NETR_TRUST_FLAG_OUTBOUND |
1606                         NETR_TRUST_FLAG_INBOUND);
1607         struct rpc_pipe_client *cli;
1608         TALLOC_CTX *mem_ctx = NULL;
1609
1610         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1611         
1612         /* Our primary domain doesn't need to worry about trust flags.
1613            Force it to go through the network setup */
1614         if ( domain->primary ) {                
1615                 return False;           
1616         }
1617         
1618         our_domain = find_our_domain();
1619         
1620         if ( !connection_ok(our_domain) ) {
1621                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1622                 return False;
1623         }
1624
1625         /* This won't work unless our domain is AD */
1626          
1627         if ( !our_domain->active_directory ) {
1628                 return False;
1629         }
1630         
1631         /* Use DsEnumerateDomainTrusts to get us the trust direction
1632            and type */
1633
1634         result = cm_connect_netlogon(our_domain, &cli);
1635
1636         if (!NT_STATUS_IS_OK(result)) {
1637                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1638                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1639                           domain->name, nt_errstr(result)));
1640                 return False;
1641         }
1642
1643         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1644                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1645                 return False;
1646         }       
1647
1648         result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1649                                                       cli->desthost,
1650                                                       flags,
1651                                                       &trusts,
1652                                                       NULL);
1653         if (!NT_STATUS_IS_OK(result)) {
1654                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1655                         "failed to query trusted domain list: %s\n",
1656                         nt_errstr(result)));
1657                 talloc_destroy(mem_ctx);
1658                 return false;
1659         }
1660
1661         /* Now find the domain name and get the flags */
1662
1663         for ( i=0; i<trusts.count; i++ ) {
1664                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1665                         domain->domain_flags          = trusts.array[i].trust_flags;
1666                         domain->domain_type           = trusts.array[i].trust_type;
1667                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1668
1669                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1670                                 domain->active_directory = True;
1671
1672                         /* This flag is only set if the domain is *our* 
1673                            primary domain and the primary domain is in
1674                            native mode */
1675
1676                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1677
1678                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1679                                   "native mode.\n", domain->name, 
1680                                   domain->native_mode ? "" : "NOT "));
1681
1682                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1683                                  "running active directory.\n", domain->name, 
1684                                  domain->active_directory ? "" : "NOT "));
1685
1686
1687                         domain->initialized = True;
1688
1689                         if ( !winbindd_can_contact_domain( domain) )
1690                                 domain->internal = True;
1691                         
1692                         break;
1693                 }               
1694         }
1695         
1696         talloc_destroy( mem_ctx );
1697         
1698         return domain->initialized;     
1699 }
1700
1701 /******************************************************************************
1702  We can 'sense' certain things about the DC by it's replies to certain
1703  questions.
1704
1705  This tells us if this particular remote server is Active Directory, and if it
1706  is native mode.
1707 ******************************************************************************/
1708
1709 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1710 {
1711         NTSTATUS                result;
1712         WERROR werr;
1713         TALLOC_CTX              *mem_ctx = NULL;
1714         struct rpc_pipe_client  *cli;
1715         POLICY_HND pol;
1716         union dssetup_DsRoleInfo info;
1717         union lsa_PolicyInformation *lsa_info = NULL;
1718
1719         if (!connection_ok(domain)) {
1720                 return;
1721         }
1722
1723         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1724                               domain->name);
1725         if (!mem_ctx) {
1726                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1727                 return;
1728         }
1729
1730         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1731
1732         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1733                                           &ndr_table_dssetup.syntax_id,
1734                                           &cli);
1735
1736         if (!NT_STATUS_IS_OK(result)) {
1737                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1738                           "PI_DSSETUP on domain %s: (%s)\n",
1739                           domain->name, nt_errstr(result)));
1740
1741                 /* if this is just a non-AD domain we need to continue
1742                  * identifying so that we can in the end return with
1743                  * domain->initialized = True - gd */
1744
1745                 goto no_dssetup;
1746         }
1747
1748         result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1749                                                                   DS_ROLE_BASIC_INFORMATION,
1750                                                                   &info,
1751                                                                   &werr);
1752         TALLOC_FREE(cli);
1753
1754         if (!NT_STATUS_IS_OK(result)) {
1755                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1756                           "on domain %s failed: (%s)\n",
1757                           domain->name, nt_errstr(result)));
1758
1759                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1760                  * every opcode on the DSSETUP pipe, continue with
1761                  * no_dssetup mode here as well to get domain->initialized
1762                  * set - gd */
1763
1764                 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1765                         goto no_dssetup;
1766                 }
1767
1768                 TALLOC_FREE(mem_ctx);
1769                 return;
1770         }
1771
1772         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1773             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1774                 domain->native_mode = True;
1775         } else {
1776                 domain->native_mode = False;
1777         }
1778
1779 no_dssetup:
1780         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1781                                           &ndr_table_lsarpc.syntax_id, &cli);
1782
1783         if (!NT_STATUS_IS_OK(result)) {
1784                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1785                           "PI_LSARPC on domain %s: (%s)\n",
1786                           domain->name, nt_errstr(result)));
1787                 TALLOC_FREE(cli);
1788                 TALLOC_FREE(mem_ctx);
1789                 return;
1790         }
1791
1792         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1793                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1794                 
1795         if (NT_STATUS_IS_OK(result)) {
1796                 /* This particular query is exactly what Win2k clients use 
1797                    to determine that the DC is active directory */
1798                 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1799                                                      &pol,
1800                                                      LSA_POLICY_INFO_DNS,
1801                                                      &lsa_info);
1802         }
1803
1804         if (NT_STATUS_IS_OK(result)) {
1805                 domain->active_directory = True;
1806
1807                 if (lsa_info->dns.name.string) {
1808                         fstrcpy(domain->name, lsa_info->dns.name.string);
1809                 }
1810
1811                 if (lsa_info->dns.dns_domain.string) {
1812                         fstrcpy(domain->alt_name,
1813                                 lsa_info->dns.dns_domain.string);
1814                 }
1815
1816                 /* See if we can set some domain trust flags about
1817                    ourself */
1818
1819                 if (lsa_info->dns.dns_forest.string) {
1820                         fstrcpy(domain->forest_name,
1821                                 lsa_info->dns.dns_forest.string);
1822
1823                         if (strequal(domain->forest_name, domain->alt_name)) {
1824                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1825                         }
1826                 }
1827
1828                 if (lsa_info->dns.sid) {
1829                         sid_copy(&domain->sid, lsa_info->dns.sid);
1830                 }
1831         } else {
1832                 domain->active_directory = False;
1833
1834                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1835                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1836                                                 &pol);
1837
1838                 if (!NT_STATUS_IS_OK(result)) {
1839                         goto done;
1840                 }
1841
1842                 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1843                                                     &pol,
1844                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1845                                                     &lsa_info);
1846
1847                 if (NT_STATUS_IS_OK(result)) {
1848
1849                         if (lsa_info->account_domain.name.string) {
1850                                 fstrcpy(domain->name,
1851                                         lsa_info->account_domain.name.string);
1852                         }
1853
1854                         if (lsa_info->account_domain.sid) {
1855                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1856                         }
1857                 }
1858         }
1859 done:
1860
1861         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1862                   domain->name, domain->native_mode ? "" : "NOT "));
1863
1864         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1865                   domain->name, domain->active_directory ? "" : "NOT "));
1866
1867         TALLOC_FREE(cli);
1868
1869         TALLOC_FREE(mem_ctx);
1870
1871         domain->initialized = True;
1872 }
1873
1874 /**********************************************************************
1875  Set the domain_flags (trust attributes, domain operating modes, etc... 
1876 ***********************************************************************/
1877
1878 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1879 {
1880         /* we always have to contact our primary domain */
1881
1882         if ( domain->primary ) {
1883                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1884                           "primary domain\n"));
1885                 set_dc_type_and_flags_connect( domain );
1886                 return;         
1887         }
1888
1889         /* Use our DC to get the information if possible */
1890
1891         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1892                 /* Otherwise, fallback to contacting the 
1893                    domain directly */
1894                 set_dc_type_and_flags_connect( domain );
1895         }
1896
1897         return;
1898 }
1899
1900
1901
1902 /**********************************************************************
1903 ***********************************************************************/
1904
1905 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1906                                    struct dcinfo **ppdc)
1907 {
1908         NTSTATUS result;
1909         struct rpc_pipe_client *netlogon_pipe;
1910
1911         if (lp_client_schannel() == False) {
1912                 return False;
1913         }
1914
1915         result = cm_connect_netlogon(domain, &netlogon_pipe);
1916         if (!NT_STATUS_IS_OK(result)) {
1917                 return False;
1918         }
1919
1920         /* Return a pointer to the struct dcinfo from the
1921            netlogon pipe. */
1922
1923         *ppdc = domain->conn.netlogon_pipe->dc;
1924         return True;
1925 }
1926
1927 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1928                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1929 {
1930         struct winbindd_cm_conn *conn;
1931         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1932         fstring conn_pwd;
1933         struct dcinfo *p_dcinfo;
1934         char *machine_password = NULL;
1935         char *machine_account = NULL;
1936         char *domain_name = NULL;
1937
1938         result = init_dc_connection(domain);
1939         if (!NT_STATUS_IS_OK(result)) {
1940                 return result;
1941         }
1942
1943         conn = &domain->conn;
1944
1945         if (conn->samr_pipe != NULL) {
1946                 goto done;
1947         }
1948
1949         /*
1950          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1951          * sign and sealed pipe using the machine account password by
1952          * preference. If we can't - try schannel, if that fails, try
1953          * anonymous.
1954          */
1955
1956         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1957         if ((conn->cli->user_name[0] == '\0') ||
1958             (conn->cli->domain[0] == '\0') || 
1959             (conn_pwd[0] == '\0'))
1960         {
1961                 result = get_trust_creds(domain, &machine_password,
1962                                          &machine_account, NULL);
1963                 if (!NT_STATUS_IS_OK(result)) {
1964                         DEBUG(10, ("cm_connect_sam: No no user available for "
1965                                    "domain %s, trying schannel\n", conn->cli->domain));
1966                         goto schannel;
1967                 }
1968                 domain_name = domain->name;
1969         } else {
1970                 machine_password = SMB_STRDUP(conn_pwd);                
1971                 machine_account = SMB_STRDUP(conn->cli->user_name);
1972                 domain_name = conn->cli->domain;
1973         }
1974
1975         if (!machine_password || !machine_account) {
1976                 result = NT_STATUS_NO_MEMORY;
1977                 goto done;
1978         }
1979
1980         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1981            authenticated SAMR pipe with sign & seal. */
1982         result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
1983                                                   &ndr_table_samr.syntax_id,
1984                                                   PIPE_AUTH_LEVEL_PRIVACY,
1985                                                   domain_name,
1986                                                   machine_account,
1987                                                   machine_password,
1988                                                   &conn->samr_pipe);
1989
1990         if (!NT_STATUS_IS_OK(result)) {
1991                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1992                           "pipe for domain %s using NTLMSSP "
1993                           "authenticated pipe: user %s\\%s. Error was "
1994                           "%s\n", domain->name, domain_name,
1995                           machine_account, nt_errstr(result)));
1996                 goto schannel;
1997         }
1998
1999         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2000                   "domain %s using NTLMSSP authenticated "
2001                   "pipe: user %s\\%s\n", domain->name,
2002                   domain_name, machine_account));
2003
2004         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2005                                       conn->samr_pipe->desthost,
2006                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2007                                       &conn->sam_connect_handle);
2008         if (NT_STATUS_IS_OK(result)) {
2009                 goto open_domain;
2010         }
2011         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2012                   "failed for domain %s, error was %s. Trying schannel\n",
2013                   domain->name, nt_errstr(result) ));
2014         TALLOC_FREE(conn->samr_pipe);
2015
2016  schannel:
2017
2018         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2019
2020         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2021                 /* If this call fails - conn->cli can now be NULL ! */
2022                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2023                            "for domain %s, trying anon\n", domain->name));
2024                 goto anonymous;
2025         }
2026         result = cli_rpc_pipe_open_schannel_with_key
2027                 (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
2028                  domain->name, p_dcinfo, &conn->samr_pipe);
2029
2030         if (!NT_STATUS_IS_OK(result)) {
2031                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2032                           "domain %s using schannel. Error was %s\n",
2033                           domain->name, nt_errstr(result) ));
2034                 goto anonymous;
2035         }
2036         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2037                   "schannel.\n", domain->name ));
2038
2039         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2040                                       conn->samr_pipe->desthost,
2041                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2042                                       &conn->sam_connect_handle);
2043         if (NT_STATUS_IS_OK(result)) {
2044                 goto open_domain;
2045         }
2046         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2047                   "for domain %s, error was %s. Trying anonymous\n",
2048                   domain->name, nt_errstr(result) ));
2049         TALLOC_FREE(conn->samr_pipe);
2050
2051  anonymous:
2052
2053         /* Finally fall back to anonymous. */
2054         result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2055                                           &conn->samr_pipe);
2056
2057         if (!NT_STATUS_IS_OK(result)) {
2058                 goto done;
2059         }
2060
2061         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2062                                       conn->samr_pipe->desthost,
2063                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2064                                       &conn->sam_connect_handle);
2065         if (!NT_STATUS_IS_OK(result)) {
2066                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2067                           "for domain %s Error was %s\n",
2068                           domain->name, nt_errstr(result) ));
2069                 goto done;
2070         }
2071
2072  open_domain:
2073         result = rpccli_samr_OpenDomain(conn->samr_pipe,
2074                                         mem_ctx,
2075                                         &conn->sam_connect_handle,
2076                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2077                                         &domain->sid,
2078                                         &conn->sam_domain_handle);
2079
2080  done:
2081
2082         if (!NT_STATUS_IS_OK(result)) {
2083                 invalidate_cm_connection(conn);
2084                 return result;
2085         }
2086
2087         *cli = conn->samr_pipe;
2088         *sam_handle = conn->sam_domain_handle;
2089         SAFE_FREE(machine_password);
2090         SAFE_FREE(machine_account);
2091         return result;
2092 }
2093
2094 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2095                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2096 {
2097         struct winbindd_cm_conn *conn;
2098         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2099         fstring conn_pwd;
2100         struct dcinfo *p_dcinfo;
2101
2102         result = init_dc_connection(domain);
2103         if (!NT_STATUS_IS_OK(result))
2104                 return result;
2105
2106         conn = &domain->conn;
2107
2108         if (conn->lsa_pipe != NULL) {
2109                 goto done;
2110         }
2111
2112         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2113         if ((conn->cli->user_name[0] == '\0') ||
2114             (conn->cli->domain[0] == '\0') || 
2115             (conn_pwd[0] == '\0')) {
2116                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2117                            "domain %s, trying schannel\n", conn->cli->domain));
2118                 goto schannel;
2119         }
2120
2121         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2122          * authenticated LSA pipe with sign & seal. */
2123         result = cli_rpc_pipe_open_spnego_ntlmssp
2124                 (conn->cli, &ndr_table_lsarpc.syntax_id,
2125                  PIPE_AUTH_LEVEL_PRIVACY,
2126                  conn->cli->domain, conn->cli->user_name, conn_pwd,
2127                  &conn->lsa_pipe);
2128
2129         if (!NT_STATUS_IS_OK(result)) {
2130                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2131                           "domain %s using NTLMSSP authenticated pipe: user "
2132                           "%s\\%s. Error was %s. Trying schannel.\n",
2133                           domain->name, conn->cli->domain,
2134                           conn->cli->user_name, nt_errstr(result)));
2135                 goto schannel;
2136         }
2137
2138         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2139                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2140                   domain->name, conn->cli->domain, conn->cli->user_name ));
2141
2142         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2143                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2144                                         &conn->lsa_policy);
2145         if (NT_STATUS_IS_OK(result)) {
2146                 goto done;
2147         }
2148
2149         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2150                   "schannel\n"));
2151
2152         TALLOC_FREE(conn->lsa_pipe);
2153
2154  schannel:
2155
2156         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2157
2158         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2159                 /* If this call fails - conn->cli can now be NULL ! */
2160                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2161                            "for domain %s, trying anon\n", domain->name));
2162                 goto anonymous;
2163         }
2164         result = cli_rpc_pipe_open_schannel_with_key
2165                 (conn->cli, &ndr_table_lsarpc.syntax_id,
2166                  PIPE_AUTH_LEVEL_PRIVACY,
2167                  domain->name, p_dcinfo, &conn->lsa_pipe);
2168
2169         if (!NT_STATUS_IS_OK(result)) {
2170                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2171                           "domain %s using schannel. Error was %s\n",
2172                           domain->name, nt_errstr(result) ));
2173                 goto anonymous;
2174         }
2175         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2176                   "schannel.\n", domain->name ));
2177
2178         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2179                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2180                                         &conn->lsa_policy);
2181         if (NT_STATUS_IS_OK(result)) {
2182                 goto done;
2183         }
2184
2185         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2186                   "anonymous\n"));
2187
2188         TALLOC_FREE(conn->lsa_pipe);
2189
2190  anonymous:
2191
2192         result = cli_rpc_pipe_open_noauth(conn->cli,
2193                                           &ndr_table_lsarpc.syntax_id,
2194                                           &conn->lsa_pipe);
2195         if (!NT_STATUS_IS_OK(result)) {
2196                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2197                 goto done;
2198         }
2199
2200         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2201                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2202                                         &conn->lsa_policy);
2203  done:
2204         if (!NT_STATUS_IS_OK(result)) {
2205                 invalidate_cm_connection(conn);
2206                 return result;
2207         }
2208
2209         *cli = conn->lsa_pipe;
2210         *lsa_policy = conn->lsa_policy;
2211         return result;
2212 }
2213
2214 /****************************************************************************
2215  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2216  session key stored in conn->netlogon_pipe->dc->sess_key.
2217 ****************************************************************************/
2218
2219 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2220                              struct rpc_pipe_client **cli)
2221 {
2222         struct winbindd_cm_conn *conn;
2223         NTSTATUS result;
2224
2225         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2226         uint8  mach_pwd[16];
2227         uint32  sec_chan_type;
2228         const char *account_name;
2229         struct rpc_pipe_client *netlogon_pipe = NULL;
2230
2231         *cli = NULL;
2232
2233         result = init_dc_connection(domain);
2234         if (!NT_STATUS_IS_OK(result)) {
2235                 return result;
2236         }
2237
2238         conn = &domain->conn;
2239
2240         if (conn->netlogon_pipe != NULL) {
2241                 *cli = conn->netlogon_pipe;
2242                 return NT_STATUS_OK;
2243         }
2244
2245         result = cli_rpc_pipe_open_noauth(conn->cli,
2246                                           &ndr_table_netlogon.syntax_id,
2247                                           &netlogon_pipe);
2248         if (!NT_STATUS_IS_OK(result)) {
2249                 return result;
2250         }
2251
2252         if ((!IS_DC) && (!domain->primary)) {
2253                 /* Clear the schannel request bit and drop down */
2254                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2255                 goto no_schannel;
2256         }
2257
2258         if (lp_client_schannel() != False) {
2259                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2260         }
2261
2262         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2263                                &sec_chan_type))
2264         {
2265                 TALLOC_FREE(netlogon_pipe);
2266                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2267         }
2268
2269         result = rpccli_netlogon_setup_creds(
2270                  netlogon_pipe,
2271                  domain->dcname, /* server name. */
2272                  domain->name,   /* domain name */
2273                  global_myname(), /* client name */
2274                  account_name,   /* machine account */
2275                  mach_pwd,       /* machine password */
2276                  sec_chan_type,  /* from get_trust_pw */
2277                  &neg_flags);
2278
2279         if (!NT_STATUS_IS_OK(result)) {
2280                 TALLOC_FREE(netlogon_pipe);
2281                 return result;
2282         }
2283
2284         if ((lp_client_schannel() == True) &&
2285                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2286                 DEBUG(3, ("Server did not offer schannel\n"));
2287                 TALLOC_FREE(netlogon_pipe);
2288                 return NT_STATUS_ACCESS_DENIED;
2289         }
2290
2291  no_schannel:
2292         if ((lp_client_schannel() == False) ||
2293                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2294                 /*
2295                  * NetSamLogonEx only works for schannel
2296                  */
2297                 domain->can_do_samlogon_ex = False;
2298
2299                 /* We're done - just keep the existing connection to NETLOGON
2300                  * open */
2301                 conn->netlogon_pipe = netlogon_pipe;
2302                 *cli = conn->netlogon_pipe;
2303                 return NT_STATUS_OK;
2304         }
2305
2306         /* Using the credentials from the first pipe, open a signed and sealed
2307            second netlogon pipe. The session key is stored in the schannel
2308            part of the new pipe auth struct.
2309         */
2310
2311         result = cli_rpc_pipe_open_schannel_with_key(
2312                 conn->cli, &ndr_table_netlogon.syntax_id,
2313                 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2314                 &conn->netlogon_pipe);
2315
2316         /* We can now close the initial netlogon pipe. */
2317         TALLOC_FREE(netlogon_pipe);
2318
2319         if (!NT_STATUS_IS_OK(result)) {
2320                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2321                           "was %s\n", nt_errstr(result)));
2322                           
2323                 /* make sure we return something besides OK */
2324                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2325         }
2326
2327         /*
2328          * Try NetSamLogonEx for AD domains
2329          */
2330         domain->can_do_samlogon_ex = domain->active_directory;
2331
2332         *cli = conn->netlogon_pipe;
2333         return NT_STATUS_OK;
2334 }