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