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