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