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