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