d4241a0c7822ba36b4af34cd886f14e0b9dea12c
[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 done;
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         /* Fall back to anonymous connection, this might fail later */
914
915         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
916                                               NULL, 0, ""))) {
917                 DEBUG(5, ("Connected anonymously\n"));
918                 cli_init_creds(*cli, "", "", "");
919                 goto session_setup_done;
920         }
921
922         result = cli_nt_error(*cli);
923
924         if (NT_STATUS_IS_OK(result))
925                 result = NT_STATUS_UNSUCCESSFUL;
926
927         /* We can't session setup */
928
929         goto done;
930
931  session_setup_done:
932
933         /* cache the server name for later connections */
934
935         saf_store( domain->name, (*cli)->desthost );
936         if (domain->alt_name && (*cli)->use_kerberos) {
937                 saf_store( domain->alt_name, (*cli)->desthost );
938         }
939
940         winbindd_set_locator_kdc_envs(domain);
941
942         if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
943
944                 result = cli_nt_error(*cli);
945
946                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
947
948                 if (NT_STATUS_IS_OK(result))
949                         result = NT_STATUS_UNSUCCESSFUL;
950
951                 goto done;
952         }
953
954         TALLOC_FREE(mutex);
955         *retry = False;
956
957         /* set the domain if empty; needed for schannel connections */
958         if ( !*(*cli)->domain ) {
959                 fstrcpy( (*cli)->domain, domain->name );
960         }
961
962         result = NT_STATUS_OK;
963
964  done:
965         TALLOC_FREE(mutex);
966         SAFE_FREE(machine_account);
967         SAFE_FREE(machine_password);
968         SAFE_FREE(machine_krb5_principal);
969         SAFE_FREE(ipc_username);
970         SAFE_FREE(ipc_domain);
971         SAFE_FREE(ipc_password);
972
973         if (!NT_STATUS_IS_OK(result)) {
974                 winbind_add_failed_connection_entry(domain, controller, result);
975                 if ((*cli) != NULL) {
976                         cli_shutdown(*cli);
977                         *cli = NULL;
978                 }
979         }
980
981         return result;
982 }
983
984 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
985                               const char *dcname, struct sockaddr_storage *pss,
986                               struct dc_name_ip **dcs, int *num)
987 {
988         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
989                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
990                 return False;
991         }
992
993         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
994
995         if (*dcs == NULL)
996                 return False;
997
998         fstrcpy((*dcs)[*num].name, dcname);
999         (*dcs)[*num].ss = *pss;
1000         *num += 1;
1001         return True;
1002 }
1003
1004 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1005                                   struct sockaddr_storage *pss, uint16 port,
1006                                   struct sockaddr_storage **addrs, int *num)
1007 {
1008         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1009
1010         if (*addrs == NULL) {
1011                 *num = 0;
1012                 return False;
1013         }
1014
1015         (*addrs)[*num] = *pss;
1016         set_sockaddr_port(&(*addrs)[*num], port);
1017
1018         *num += 1;
1019         return True;
1020 }
1021
1022 static void mailslot_name(struct in_addr dc_ip, fstring name)
1023 {
1024         fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
1025 }
1026
1027 static bool send_getdc_request(struct sockaddr_storage *dc_ss,
1028                                const char *domain_name,
1029                                const DOM_SID *sid)
1030 {
1031         char outbuf[1024];
1032         struct in_addr dc_ip;
1033         char *p;
1034         fstring my_acct_name;
1035         fstring my_mailslot;
1036         size_t sid_size;
1037
1038         if (dc_ss->ss_family != AF_INET) {
1039                 return false;
1040         }
1041
1042         dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
1043         mailslot_name(dc_ip, my_mailslot);
1044
1045         memset(outbuf, '\0', sizeof(outbuf));
1046
1047         p = outbuf;
1048
1049         SCVAL(p, 0, SAMLOGON);
1050         p++;
1051
1052         SCVAL(p, 0, 0); /* Count pointer ... */
1053         p++;
1054
1055         SIVAL(p, 0, 0); /* The sender's token ... */
1056         p += 2;
1057
1058         p += dos_PutUniCode(p, global_myname(),
1059                         sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
1060         fstr_sprintf(my_acct_name, "%s$", global_myname());
1061         p += dos_PutUniCode(p, my_acct_name,
1062                         sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
1063
1064         if (strlen(my_mailslot)+1 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
1065                 return false;
1066         }
1067
1068         memcpy(p, my_mailslot, strlen(my_mailslot)+1);
1069         p += strlen(my_mailslot)+1;
1070
1071         if (sizeof(outbuf) - PTR_DIFF(p, outbuf) < 8) {
1072                 return false;
1073         }
1074
1075         SIVAL(p, 0, 0x80);
1076         p+=4;
1077
1078         sid_size = ndr_size_dom_sid(sid, 0);
1079
1080         SIVAL(p, 0, sid_size);
1081         p+=4;
1082
1083         p = ALIGN4(p, outbuf);
1084         if (PTR_DIFF(p, outbuf) > sizeof(outbuf)) {
1085                 return false;
1086         }
1087
1088         if (sid_size + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
1089                 return false;
1090         }
1091         sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid);
1092
1093         p += sid_size;
1094
1095         SIVAL(p, 0, 1);
1096         SSVAL(p, 4, 0xffff);
1097         SSVAL(p, 6, 0xffff);
1098         p+=8;
1099
1100         return cli_send_mailslot(winbind_messaging_context(),
1101                                  False, "\\MAILSLOT\\NET\\NTLOGON", 0,
1102                                  outbuf, PTR_DIFF(p, outbuf),
1103                                  global_myname(), 0, domain_name, 0x1c,
1104                                  dc_ss);
1105 }
1106
1107 static bool receive_getdc_response(struct sockaddr_storage *dc_ss,
1108                                    const char *domain_name,
1109                                    fstring dc_name)
1110 {
1111         struct packet_struct *packet;
1112         fstring my_mailslot;
1113         char *buf, *p;
1114         fstring dcname, user, domain;
1115         int len;
1116         struct in_addr dc_ip;
1117
1118         if (dc_ss->ss_family != AF_INET) {
1119                 return false;
1120         }
1121         dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
1122         mailslot_name(dc_ip, my_mailslot);
1123
1124         packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
1125
1126         if (packet == NULL) {
1127                 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
1128                 return False;
1129         }
1130
1131         DEBUG(5, ("Received packet for %s\n", my_mailslot));
1132
1133         buf = packet->packet.dgram.data;
1134         len = packet->packet.dgram.datasize;
1135
1136         if (len < 70) {
1137                 /* 70 is a completely arbitrary value to make sure
1138                    the SVAL below does not read uninitialized memory */
1139                 DEBUG(3, ("GetDC got short response\n"));
1140                 return False;
1141         }
1142
1143         /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1144         p = buf+SVAL(buf, smb_vwv10);
1145
1146         if (CVAL(p,0) != SAMLOGON_R) {
1147                 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
1148                 return False;
1149         }
1150
1151         p+=2;
1152         pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1153                   STR_TERMINATE|STR_NOALIGN);
1154         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1155         pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1156                   STR_TERMINATE|STR_NOALIGN);
1157         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1158         pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1159                   STR_TERMINATE|STR_NOALIGN);
1160         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1161
1162         if (!strequal(domain, domain_name)) {
1163                 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1164                           domain_name, domain));
1165                 return False;
1166         }
1167
1168         p = dcname;
1169         if (*p == '\\') p += 1;
1170         if (*p == '\\') p += 1;
1171
1172         fstrcpy(dc_name, p);
1173
1174         DEBUG(10, ("GetDC gave name %s for domain %s\n",
1175                    dc_name, domain));
1176
1177         return True;
1178 }
1179
1180 /*******************************************************************
1181  convert an ip to a name
1182 *******************************************************************/
1183
1184 static bool dcip_to_name(const struct winbindd_domain *domain,
1185                 struct sockaddr_storage *pss,
1186                 fstring name )
1187 {
1188         struct ip_service ip_list;
1189
1190         ip_list.ss = *pss;
1191         ip_list.port = 0;
1192
1193 #ifdef WITH_ADS
1194         /* For active directory servers, try to get the ldap server name.
1195            None of these failures should be considered critical for now */
1196
1197         if (lp_security() == SEC_ADS) {
1198                 ADS_STRUCT *ads;
1199                 char addr[INET6_ADDRSTRLEN];
1200
1201                 print_sockaddr(addr, sizeof(addr), pss);
1202
1203                 ads = ads_init(domain->alt_name, domain->name, NULL);
1204                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1205
1206                 if (ads_try_connect(ads, addr)) {
1207                         /* We got a cldap packet. */
1208                         fstrcpy(name, ads->config.ldap_server_name);
1209                         namecache_store(name, 0x20, 1, &ip_list);
1210
1211                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1212
1213                         if (domain->primary && (ads->config.flags & ADS_KDC)) {
1214                                 if (ads_closest_dc(ads)) {
1215                                         char *sitename = sitename_fetch(ads->config.realm);
1216
1217                                         /* We're going to use this KDC for this realm/domain.
1218                                            If we are using sites, then force the krb5 libs
1219                                            to use this KDC. */
1220
1221                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1222                                                                         domain->name,
1223                                                                         sitename,
1224                                                                         pss);
1225
1226                                         SAFE_FREE(sitename);
1227                                 } else {
1228                                         /* use an off site KDC */
1229                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1230                                                                         domain->name,
1231                                                                         NULL,
1232                                                                         pss);
1233                                 }
1234                                 winbindd_set_locator_kdc_envs(domain);
1235
1236                                 /* Ensure we contact this DC also. */
1237                                 saf_store( domain->name, name);
1238                                 saf_store( domain->alt_name, name);
1239                         }
1240
1241                         ads_destroy( &ads );
1242                         return True;
1243                 }
1244
1245                 ads_destroy( &ads );
1246         }
1247 #endif
1248
1249         /* try GETDC requests next */
1250
1251         if (send_getdc_request(pss, domain->name, &domain->sid)) {
1252                 int i;
1253                 smb_msleep(100);
1254                 for (i=0; i<5; i++) {
1255                         if (receive_getdc_response(pss, domain->name, name)) {
1256                                 namecache_store(name, 0x20, 1, &ip_list);
1257                                 return True;
1258                         }
1259                         smb_msleep(500);
1260                 }
1261         }
1262
1263         /* try node status request */
1264
1265         if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1266                 namecache_store(name, 0x20, 1, &ip_list);
1267                 return True;
1268         }
1269         return False;
1270 }
1271
1272 /*******************************************************************
1273  Retreive a list of IP address for domain controllers.  Fill in 
1274  the dcs[]  with results.
1275 *******************************************************************/
1276
1277 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1278                     struct dc_name_ip **dcs, int *num_dcs)
1279 {
1280         fstring dcname;
1281         struct  sockaddr_storage ss;
1282         struct  ip_service *ip_list = NULL;
1283         int     iplist_size = 0;
1284         int     i;
1285         bool    is_our_domain;
1286         enum security_types sec = (enum security_types)lp_security();
1287
1288         is_our_domain = strequal(domain->name, lp_workgroup());
1289
1290         if ( !is_our_domain
1291                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1292                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs, num_dcs) )
1293         {
1294                 char addr[INET6_ADDRSTRLEN];
1295                 print_sockaddr(addr, sizeof(addr), &ss);
1296                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1297                            dcname, addr));
1298                 return True;
1299         }
1300
1301         if (sec == SEC_ADS) {
1302                 char *sitename = NULL;
1303
1304                 /* We need to make sure we know the local site before
1305                    doing any DNS queries, as this will restrict the
1306                    get_sorted_dc_list() call below to only fetching
1307                    DNS records for the correct site. */
1308
1309                 /* Find any DC to get the site record.
1310                    We deliberately don't care about the
1311                    return here. */
1312
1313                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1314
1315                 sitename = sitename_fetch(domain->alt_name);
1316                 if (sitename) {
1317
1318                         /* Do the site-specific AD dns lookup first. */
1319                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1320
1321                         for ( i=0; i<iplist_size; i++ ) {
1322                                 char addr[INET6_ADDRSTRLEN];
1323                                 print_sockaddr(addr, sizeof(addr),
1324                                                 &ip_list[i].ss);
1325                                 add_one_dc_unique(mem_ctx,
1326                                                 domain->name,
1327                                                 addr,
1328                                                 &ip_list[i].ss,
1329                                                 dcs,
1330                                                 num_dcs);
1331                         }
1332
1333                         SAFE_FREE(ip_list);
1334                         SAFE_FREE(sitename);
1335                         iplist_size = 0;
1336                 }
1337
1338                 /* Now we add DCs from the main AD dns lookup. */
1339                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1340
1341                 for ( i=0; i<iplist_size; i++ ) {
1342                         char addr[INET6_ADDRSTRLEN];
1343                         print_sockaddr(addr, sizeof(addr),
1344                                         &ip_list[i].ss);
1345                         add_one_dc_unique(mem_ctx,
1346                                         domain->name,
1347                                         addr,
1348                                         &ip_list[i].ss,
1349                                         dcs,
1350                                         num_dcs);
1351                 }
1352         }
1353
1354         /* try standard netbios queries if no ADS */
1355
1356         if (iplist_size==0) {
1357                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1358         }
1359
1360         /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1361
1362         /* now add to the dc array.  We'll wait until the last minute 
1363            to look up the name of the DC.  But we fill in the char* for 
1364            the ip now in to make the failed connection cache work */
1365
1366         for ( i=0; i<iplist_size; i++ ) {
1367                 char addr[INET6_ADDRSTRLEN];
1368                 print_sockaddr(addr, sizeof(addr),
1369                                 &ip_list[i].ss);
1370                 add_one_dc_unique(mem_ctx, domain->name, addr,
1371                         &ip_list[i].ss, dcs, num_dcs);
1372         }
1373
1374         SAFE_FREE( ip_list );
1375
1376         return True;
1377 }
1378
1379 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1380                         struct winbindd_domain *domain,
1381                         fstring dcname, struct sockaddr_storage *pss, int *fd)
1382 {
1383         struct dc_name_ip *dcs = NULL;
1384         int num_dcs = 0;
1385
1386         const char **dcnames = NULL;
1387         int num_dcnames = 0;
1388
1389         struct sockaddr_storage *addrs = NULL;
1390         int num_addrs = 0;
1391
1392         int i, fd_index;
1393
1394  again:
1395         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1396                 return False;
1397
1398         for (i=0; i<num_dcs; i++) {
1399
1400                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1401                                     &dcnames, &num_dcnames)) {
1402                         return False;
1403                 }
1404                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1405                                       &addrs, &num_addrs)) {
1406                         return False;
1407                 }
1408
1409                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1410                                     &dcnames, &num_dcnames)) {
1411                         return False;
1412                 }
1413                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1414                                       &addrs, &num_addrs)) {
1415                         return False;
1416                 }
1417         }
1418
1419         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1420                 return False;
1421
1422         if ((addrs == NULL) || (dcnames == NULL))
1423                 return False;
1424
1425         /* 5 second timeout. */
1426         if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1427                 for (i=0; i<num_dcs; i++) {
1428                         char ab[INET6_ADDRSTRLEN];
1429                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1430                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1431                                 "domain %s address %s. Error was %s\n",
1432                                 domain->name, ab, strerror(errno) ));
1433                         winbind_add_failed_connection_entry(domain,
1434                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1435                 }
1436                 return False;
1437         }
1438
1439         *pss = addrs[fd_index];
1440
1441         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1442                 /* Ok, we've got a name for the DC */
1443                 fstrcpy(dcname, dcnames[fd_index]);
1444                 return True;
1445         }
1446
1447         /* Try to figure out the name */
1448         if (dcip_to_name(domain, pss, dcname)) {
1449                 return True;
1450         }
1451
1452         /* We can not continue without the DC's name */
1453         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1454                                     NT_STATUS_UNSUCCESSFUL);
1455         goto again;
1456 }
1457
1458 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1459                                    struct winbindd_cm_conn *new_conn)
1460 {
1461         TALLOC_CTX *mem_ctx;
1462         NTSTATUS result;
1463         char *saf_servername = saf_fetch( domain->name );
1464         int retries;
1465
1466         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1467                 SAFE_FREE(saf_servername);
1468                 set_domain_offline(domain);
1469                 return NT_STATUS_NO_MEMORY;
1470         }
1471
1472         /* we have to check the server affinity cache here since 
1473            later we selecte a DC based on response time and not preference */
1474            
1475         /* Check the negative connection cache
1476            before talking to it. It going down may have
1477            triggered the reconnection. */
1478
1479         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1480
1481                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1482                         saf_servername, domain->name ));
1483
1484                 /* convert an ip address to a name */
1485                 if (is_ipaddress( saf_servername ) ) {
1486                         fstring saf_name;
1487                         struct sockaddr_storage ss;
1488
1489                         if (!interpret_string_addr(&ss, saf_servername,
1490                                                 AI_NUMERICHOST)) {
1491                                 return NT_STATUS_UNSUCCESSFUL;
1492                         }
1493                         if (dcip_to_name( domain, &ss, saf_name )) {
1494                                 fstrcpy( domain->dcname, saf_name );
1495                         } else {
1496                                 winbind_add_failed_connection_entry(
1497                                         domain, saf_servername,
1498                                         NT_STATUS_UNSUCCESSFUL);
1499                         }
1500                 } else {
1501                         fstrcpy( domain->dcname, saf_servername );
1502                 }
1503
1504                 SAFE_FREE( saf_servername );
1505         }
1506
1507         for (retries = 0; retries < 3; retries++) {
1508                 int fd = -1;
1509                 bool retry = False;
1510
1511                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1512
1513                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1514                         domain->dcname, domain->name ));
1515
1516                 if (*domain->dcname 
1517                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1518                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1519                 {
1520                         struct sockaddr_storage *addrs = NULL;
1521                         int num_addrs = 0;
1522                         int dummy = 0;
1523
1524                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1525                                 set_domain_offline(domain);
1526                                 talloc_destroy(mem_ctx);
1527                                 return NT_STATUS_NO_MEMORY;
1528                         }
1529                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1530                                 set_domain_offline(domain);
1531                                 talloc_destroy(mem_ctx);
1532                                 return NT_STATUS_NO_MEMORY;
1533                         }
1534
1535                         /* 5 second timeout. */
1536                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1537                                 fd = -1;
1538                         }
1539                 }
1540
1541                 if ((fd == -1) 
1542                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1543                 {
1544                         /* This is the one place where we will
1545                            set the global winbindd offline state
1546                            to true, if a "WINBINDD_OFFLINE" entry
1547                            is found in the winbindd cache. */
1548                         set_global_winbindd_state_offline();
1549                         break;
1550                 }
1551
1552                 new_conn->cli = NULL;
1553
1554                 result = cm_prepare_connection(domain, fd, domain->dcname,
1555                         &new_conn->cli, &retry);
1556
1557                 if (!retry)
1558                         break;
1559         }
1560
1561         if (NT_STATUS_IS_OK(result)) {
1562
1563                 winbindd_set_locator_kdc_envs(domain);
1564
1565                 if (domain->online == False) {
1566                         /* We're changing state from offline to online. */
1567                         set_global_winbindd_state_online();
1568                 }
1569                 set_domain_online(domain);
1570         } else {
1571                 /* Ensure we setup the retry handler. */
1572                 set_domain_offline(domain);
1573         }
1574
1575         talloc_destroy(mem_ctx);
1576         return result;
1577 }
1578
1579 /* Close down all open pipes on a connection. */
1580
1581 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1582 {
1583         /* We're closing down a possibly dead
1584            connection. Don't have impossibly long (10s) timeouts. */
1585
1586         if (conn->cli) {
1587                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1588         }
1589
1590         if (conn->samr_pipe != NULL) {
1591                 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1592                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1593                         if (conn->cli) {
1594                                 cli_set_timeout(conn->cli, 500);
1595                         }
1596                 }
1597                 conn->samr_pipe = NULL;
1598         }
1599
1600         if (conn->lsa_pipe != NULL) {
1601                 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1602                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1603                         if (conn->cli) {
1604                                 cli_set_timeout(conn->cli, 500);
1605                         }
1606                 }
1607                 conn->lsa_pipe = NULL;
1608         }
1609
1610         if (conn->netlogon_pipe != NULL) {
1611                 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1612                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1613                         if (conn->cli) {
1614                                 cli_set_timeout(conn->cli, 500);
1615                         }
1616                 }
1617                 conn->netlogon_pipe = NULL;
1618         }
1619
1620         if (conn->cli) {
1621                 cli_shutdown(conn->cli);
1622         }
1623
1624         conn->cli = NULL;
1625 }
1626
1627 void close_conns_after_fork(void)
1628 {
1629         struct winbindd_domain *domain;
1630
1631         for (domain = domain_list(); domain; domain = domain->next) {
1632                 if (domain->conn.cli == NULL)
1633                         continue;
1634
1635                 if (domain->conn.cli->fd == -1)
1636                         continue;
1637
1638                 close(domain->conn.cli->fd);
1639                 domain->conn.cli->fd = -1;
1640         }
1641 }
1642
1643 static bool connection_ok(struct winbindd_domain *domain)
1644 {
1645         if (domain->conn.cli == NULL) {
1646                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1647                           "cli!\n", domain->dcname, domain->name));
1648                 return False;
1649         }
1650
1651         if (!domain->conn.cli->initialised) {
1652                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1653                           "initialised!\n", domain->dcname, domain->name));
1654                 return False;
1655         }
1656
1657         if (domain->conn.cli->fd == -1) {
1658                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1659                           "never started (fd == -1)\n", 
1660                           domain->dcname, domain->name));
1661                 return False;
1662         }
1663
1664         if (domain->online == False) {
1665                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1666                 return False;
1667         }
1668
1669         return True;
1670 }
1671
1672 /* Initialize a new connection up to the RPC BIND.
1673    Bypass online status check so always does network calls. */
1674
1675 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1676 {
1677         NTSTATUS result;
1678
1679         /* Internal connections never use the network. */
1680         if (domain->internal) {
1681                 domain->initialized = True;
1682                 return NT_STATUS_OK;
1683         }
1684
1685         if (connection_ok(domain)) {
1686                 if (!domain->initialized) {
1687                         set_dc_type_and_flags(domain);
1688                 }
1689                 return NT_STATUS_OK;
1690         }
1691
1692         invalidate_cm_connection(&domain->conn);
1693
1694         result = cm_open_connection(domain, &domain->conn);
1695
1696         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1697                 set_dc_type_and_flags(domain);
1698         }
1699
1700         return result;
1701 }
1702
1703 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1704 {
1705         if (domain->initialized && !domain->online) {
1706                 /* We check for online status elsewhere. */
1707                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1708         }
1709
1710         return init_dc_connection_network(domain);
1711 }
1712
1713 /******************************************************************************
1714  Set the trust flags (direction and forest location) for a domain
1715 ******************************************************************************/
1716
1717 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1718 {
1719         struct winbindd_domain *our_domain;
1720         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1721         struct netr_DomainTrustList trusts;
1722         int i;
1723         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1724                         NETR_TRUST_FLAG_OUTBOUND |
1725                         NETR_TRUST_FLAG_INBOUND);
1726         struct rpc_pipe_client *cli;
1727         TALLOC_CTX *mem_ctx = NULL;
1728
1729         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1730         
1731         /* Our primary domain doesn't need to worry about trust flags.
1732            Force it to go through the network setup */
1733         if ( domain->primary ) {                
1734                 return False;           
1735         }
1736         
1737         our_domain = find_our_domain();
1738         
1739         if ( !connection_ok(our_domain) ) {
1740                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1741                 return False;
1742         }
1743
1744         /* This won't work unless our domain is AD */
1745          
1746         if ( !our_domain->active_directory ) {
1747                 return False;
1748         }
1749         
1750         /* Use DsEnumerateDomainTrusts to get us the trust direction
1751            and type */
1752
1753         result = cm_connect_netlogon(our_domain, &cli);
1754
1755         if (!NT_STATUS_IS_OK(result)) {
1756                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1757                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1758                           domain->name, nt_errstr(result)));
1759                 return False;
1760         }
1761
1762         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1763                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1764                 return False;
1765         }       
1766
1767         result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1768                                                       cli->cli->desthost,
1769                                                       flags,
1770                                                       &trusts,
1771                                                       NULL);
1772         if (!NT_STATUS_IS_OK(result)) {
1773                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1774                         "failed to query trusted domain list: %s\n",
1775                         nt_errstr(result)));
1776                 talloc_destroy(mem_ctx);
1777                 return false;
1778         }
1779
1780         /* Now find the domain name and get the flags */
1781
1782         for ( i=0; i<trusts.count; i++ ) {
1783                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1784                         domain->domain_flags          = trusts.array[i].trust_flags;
1785                         domain->domain_type           = trusts.array[i].trust_type;
1786                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1787
1788                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1789                                 domain->active_directory = True;
1790
1791                         /* This flag is only set if the domain is *our* 
1792                            primary domain and the primary domain is in
1793                            native mode */
1794
1795                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1796
1797                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1798                                   "native mode.\n", domain->name, 
1799                                   domain->native_mode ? "" : "NOT "));
1800
1801                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1802                                  "running active directory.\n", domain->name, 
1803                                  domain->active_directory ? "" : "NOT "));
1804
1805
1806                         domain->initialized = True;
1807
1808                         if ( !winbindd_can_contact_domain( domain) )
1809                                 domain->internal = True;
1810                         
1811                         break;
1812                 }               
1813         }
1814         
1815         talloc_destroy( mem_ctx );
1816         
1817         return domain->initialized;     
1818 }
1819
1820 /******************************************************************************
1821  We can 'sense' certain things about the DC by it's replies to certain
1822  questions.
1823
1824  This tells us if this particular remote server is Active Directory, and if it
1825  is native mode.
1826 ******************************************************************************/
1827
1828 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1829 {
1830         NTSTATUS                result;
1831         WERROR werr;
1832         TALLOC_CTX              *mem_ctx = NULL;
1833         struct rpc_pipe_client  *cli;
1834         POLICY_HND pol;
1835         union dssetup_DsRoleInfo info;
1836         union lsa_PolicyInformation *lsa_info = NULL;
1837
1838         if (!connection_ok(domain)) {
1839                 return;
1840         }
1841
1842         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1843                               domain->name);
1844         if (!mem_ctx) {
1845                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1846                 return;
1847         }
1848
1849         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1850
1851         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_DSSETUP,
1852                                        &result);
1853
1854         if (cli == NULL) {
1855                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1856                           "PI_DSSETUP on domain %s: (%s)\n",
1857                           domain->name, nt_errstr(result)));
1858
1859                 /* if this is just a non-AD domain we need to continue
1860                  * identifying so that we can in the end return with
1861                  * domain->initialized = True - gd */
1862
1863                 goto no_dssetup;
1864         }
1865
1866         result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1867                                                                   DS_ROLE_BASIC_INFORMATION,
1868                                                                   &info,
1869                                                                   &werr);
1870         cli_rpc_pipe_close(cli);
1871
1872         if (!NT_STATUS_IS_OK(result)) {
1873                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1874                           "on domain %s failed: (%s)\n",
1875                           domain->name, nt_errstr(result)));
1876
1877                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1878                  * every opcode on the DSSETUP pipe, continue with
1879                  * no_dssetup mode here as well to get domain->initialized
1880                  * set - gd */
1881
1882                 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1883                         goto no_dssetup;
1884                 }
1885
1886                 TALLOC_FREE(mem_ctx);
1887                 return;
1888         }
1889
1890         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1891             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1892                 domain->native_mode = True;
1893         } else {
1894                 domain->native_mode = False;
1895         }
1896
1897 no_dssetup:
1898         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1899
1900         if (cli == NULL) {
1901                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1902                           "PI_LSARPC on domain %s: (%s)\n",
1903                           domain->name, nt_errstr(result)));
1904                 cli_rpc_pipe_close(cli);
1905                 TALLOC_FREE(mem_ctx);
1906                 return;
1907         }
1908
1909         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1910                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1911                 
1912         if (NT_STATUS_IS_OK(result)) {
1913                 /* This particular query is exactly what Win2k clients use 
1914                    to determine that the DC is active directory */
1915                 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1916                                                      &pol,
1917                                                      LSA_POLICY_INFO_DNS,
1918                                                      &lsa_info);
1919         }
1920
1921         if (NT_STATUS_IS_OK(result)) {
1922                 domain->active_directory = True;
1923
1924                 if (lsa_info->dns.name.string) {
1925                         fstrcpy(domain->name, lsa_info->dns.name.string);
1926                 }
1927
1928                 if (lsa_info->dns.dns_domain.string) {
1929                         fstrcpy(domain->alt_name,
1930                                 lsa_info->dns.dns_domain.string);
1931                 }
1932
1933                 /* See if we can set some domain trust flags about
1934                    ourself */
1935
1936                 if (lsa_info->dns.dns_forest.string) {
1937                         fstrcpy(domain->forest_name,
1938                                 lsa_info->dns.dns_forest.string);
1939
1940                         if (strequal(domain->forest_name, domain->alt_name)) {
1941                                 domain->domain_flags = NETR_TRUST_FLAG_TREEROOT;
1942                         }
1943                 }
1944
1945                 if (lsa_info->dns.sid) {
1946                         sid_copy(&domain->sid, lsa_info->dns.sid);
1947                 }
1948         } else {
1949                 domain->active_directory = False;
1950
1951                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1952                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1953                                                 &pol);
1954
1955                 if (!NT_STATUS_IS_OK(result)) {
1956                         goto done;
1957                 }
1958
1959                 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1960                                                     &pol,
1961                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1962                                                     &lsa_info);
1963
1964                 if (NT_STATUS_IS_OK(result)) {
1965
1966                         if (lsa_info->account_domain.name.string) {
1967                                 fstrcpy(domain->name,
1968                                         lsa_info->account_domain.name.string);
1969                         }
1970
1971                         if (lsa_info->account_domain.sid) {
1972                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1973                         }
1974                 }
1975         }
1976 done:
1977
1978         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1979                   domain->name, domain->native_mode ? "" : "NOT "));
1980
1981         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1982                   domain->name, domain->active_directory ? "" : "NOT "));
1983
1984         cli_rpc_pipe_close(cli);
1985
1986         TALLOC_FREE(mem_ctx);
1987
1988         domain->initialized = True;
1989 }
1990
1991 /**********************************************************************
1992  Set the domain_flags (trust attributes, domain operating modes, etc... 
1993 ***********************************************************************/
1994
1995 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1996 {
1997         /* we always have to contact our primary domain */
1998
1999         if ( domain->primary ) {
2000                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2001                           "primary domain\n"));
2002                 set_dc_type_and_flags_connect( domain );
2003                 return;         
2004         }
2005
2006         /* Use our DC to get the information if possible */
2007
2008         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2009                 /* Otherwise, fallback to contacting the 
2010                    domain directly */
2011                 set_dc_type_and_flags_connect( domain );
2012         }
2013
2014         return;
2015 }
2016
2017
2018
2019 /**********************************************************************
2020 ***********************************************************************/
2021
2022 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
2023                                    struct dcinfo **ppdc)
2024 {
2025         NTSTATUS result;
2026         struct rpc_pipe_client *netlogon_pipe;
2027
2028         if (lp_client_schannel() == False) {
2029                 return False;
2030         }
2031
2032         result = cm_connect_netlogon(domain, &netlogon_pipe);
2033         if (!NT_STATUS_IS_OK(result)) {
2034                 return False;
2035         }
2036
2037         /* Return a pointer to the struct dcinfo from the
2038            netlogon pipe. */
2039
2040         *ppdc = domain->conn.netlogon_pipe->dc;
2041         return True;
2042 }
2043
2044 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2045                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
2046 {
2047         struct winbindd_cm_conn *conn;
2048         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2049         fstring conn_pwd;
2050         struct dcinfo *p_dcinfo;
2051         char *machine_password = NULL;
2052         char *machine_account = NULL;
2053         char *domain_name = NULL;
2054
2055         result = init_dc_connection(domain);
2056         if (!NT_STATUS_IS_OK(result)) {
2057                 return result;
2058         }
2059
2060         conn = &domain->conn;
2061
2062         if (conn->samr_pipe != NULL) {
2063                 goto done;
2064         }
2065
2066         /*
2067          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2068          * sign and sealed pipe using the machine account password by
2069          * preference. If we can't - try schannel, if that fails, try
2070          * anonymous.
2071          */
2072
2073         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2074         if ((conn->cli->user_name[0] == '\0') ||
2075             (conn->cli->domain[0] == '\0') || 
2076             (conn_pwd[0] == '\0'))
2077         {
2078                 result = get_trust_creds(domain, &machine_password,
2079                                          &machine_account, NULL);
2080                 if (!NT_STATUS_IS_OK(result)) {
2081                         DEBUG(10, ("cm_connect_sam: No no user available for "
2082                                    "domain %s, trying schannel\n", conn->cli->domain));
2083                         goto schannel;
2084                 }
2085                 domain_name = domain->name;
2086         } else {
2087                 machine_password = SMB_STRDUP(conn_pwd);                
2088                 machine_account = SMB_STRDUP(conn->cli->user_name);
2089                 domain_name = conn->cli->domain;
2090         }
2091
2092         if (!machine_password || !machine_account) {
2093                 result = NT_STATUS_NO_MEMORY;
2094                 goto done;
2095         }
2096
2097         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2098            authenticated SAMR pipe with sign & seal. */
2099         conn->samr_pipe =
2100                 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
2101                                                  PIPE_AUTH_LEVEL_PRIVACY,
2102                                                  domain_name,
2103                                                  machine_account,
2104                                                  machine_password, &result);
2105
2106         if (conn->samr_pipe == NULL) {
2107                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2108                           "pipe for domain %s using NTLMSSP "
2109                           "authenticated pipe: user %s\\%s. Error was "
2110                           "%s\n", domain->name, domain_name,
2111                           machine_account, nt_errstr(result)));
2112                 goto schannel;
2113         }
2114
2115         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2116                   "domain %s using NTLMSSP authenticated "
2117                   "pipe: user %s\\%s\n", domain->name,
2118                   domain_name, machine_account));
2119
2120         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2121                                       conn->samr_pipe->cli->desthost,
2122                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2123                                       &conn->sam_connect_handle);
2124         if (NT_STATUS_IS_OK(result)) {
2125                 goto open_domain;
2126         }
2127         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2128                   "failed for domain %s, error was %s. Trying schannel\n",
2129                   domain->name, nt_errstr(result) ));
2130         cli_rpc_pipe_close(conn->samr_pipe);
2131
2132  schannel:
2133
2134         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2135
2136         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2137                 /* If this call fails - conn->cli can now be NULL ! */
2138                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2139                            "for domain %s, trying anon\n", domain->name));
2140                 goto anonymous;
2141         }
2142         conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
2143                 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
2144                  domain->name, p_dcinfo, &result);
2145
2146         if (conn->samr_pipe == NULL) {
2147                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2148                           "domain %s using schannel. Error was %s\n",
2149                           domain->name, nt_errstr(result) ));
2150                 goto anonymous;
2151         }
2152         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2153                   "schannel.\n", domain->name ));
2154
2155         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2156                                       conn->samr_pipe->cli->desthost,
2157                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2158                                       &conn->sam_connect_handle);
2159         if (NT_STATUS_IS_OK(result)) {
2160                 goto open_domain;
2161         }
2162         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2163                   "for domain %s, error was %s. Trying anonymous\n",
2164                   domain->name, nt_errstr(result) ));
2165         cli_rpc_pipe_close(conn->samr_pipe);
2166
2167  anonymous:
2168
2169         /* Finally fall back to anonymous. */
2170         conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
2171                                                    &result);
2172
2173         if (conn->samr_pipe == NULL) {
2174                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2175                 goto done;
2176         }
2177
2178         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2179                                       conn->samr_pipe->cli->desthost,
2180                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2181                                       &conn->sam_connect_handle);
2182         if (!NT_STATUS_IS_OK(result)) {
2183                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2184                           "for domain %s Error was %s\n",
2185                           domain->name, nt_errstr(result) ));
2186                 goto done;
2187         }
2188
2189  open_domain:
2190         result = rpccli_samr_OpenDomain(conn->samr_pipe,
2191                                         mem_ctx,
2192                                         &conn->sam_connect_handle,
2193                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2194                                         &domain->sid,
2195                                         &conn->sam_domain_handle);
2196
2197  done:
2198
2199         if (!NT_STATUS_IS_OK(result)) {
2200                 invalidate_cm_connection(conn);
2201                 return result;
2202         }
2203
2204         *cli = conn->samr_pipe;
2205         *sam_handle = conn->sam_domain_handle;
2206         SAFE_FREE(machine_password);
2207         SAFE_FREE(machine_account);
2208         return result;
2209 }
2210
2211 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2212                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2213 {
2214         struct winbindd_cm_conn *conn;
2215         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2216         fstring conn_pwd;
2217         struct dcinfo *p_dcinfo;
2218
2219         result = init_dc_connection(domain);
2220         if (!NT_STATUS_IS_OK(result))
2221                 return result;
2222
2223         conn = &domain->conn;
2224
2225         if (conn->lsa_pipe != NULL) {
2226                 goto done;
2227         }
2228
2229         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2230         if ((conn->cli->user_name[0] == '\0') ||
2231             (conn->cli->domain[0] == '\0') || 
2232             (conn_pwd[0] == '\0')) {
2233                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2234                            "domain %s, trying schannel\n", conn->cli->domain));
2235                 goto schannel;
2236         }
2237
2238         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2239          * authenticated LSA pipe with sign & seal. */
2240         conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
2241                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2242                  conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
2243
2244         if (conn->lsa_pipe == NULL) {
2245                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2246                           "domain %s using NTLMSSP authenticated pipe: user "
2247                           "%s\\%s. Error was %s. Trying schannel.\n",
2248                           domain->name, conn->cli->domain,
2249                           conn->cli->user_name, nt_errstr(result)));
2250                 goto schannel;
2251         }
2252
2253         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2254                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2255                   domain->name, conn->cli->domain, conn->cli->user_name ));
2256
2257         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2258                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2259                                         &conn->lsa_policy);
2260         if (NT_STATUS_IS_OK(result)) {
2261                 goto done;
2262         }
2263
2264         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2265                   "schannel\n"));
2266
2267         cli_rpc_pipe_close(conn->lsa_pipe);
2268
2269  schannel:
2270
2271         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2272
2273         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2274                 /* If this call fails - conn->cli can now be NULL ! */
2275                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2276                            "for domain %s, trying anon\n", domain->name));
2277                 goto anonymous;
2278         }
2279         conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2280                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2281                  domain->name, p_dcinfo, &result);
2282
2283         if (conn->lsa_pipe == NULL) {
2284                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2285                           "domain %s using schannel. Error was %s\n",
2286                           domain->name, nt_errstr(result) ));
2287                 goto anonymous;
2288         }
2289         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2290                   "schannel.\n", domain->name ));
2291
2292         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2293                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2294                                         &conn->lsa_policy);
2295         if (NT_STATUS_IS_OK(result)) {
2296                 goto done;
2297         }
2298
2299         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2300                   "anonymous\n"));
2301
2302         cli_rpc_pipe_close(conn->lsa_pipe);
2303
2304  anonymous:
2305
2306         conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2307                                                   &result);
2308         if (conn->lsa_pipe == NULL) {
2309                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2310                 goto done;
2311         }
2312
2313         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2314                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2315                                         &conn->lsa_policy);
2316  done:
2317         if (!NT_STATUS_IS_OK(result)) {
2318                 invalidate_cm_connection(conn);
2319                 return result;
2320         }
2321
2322         *cli = conn->lsa_pipe;
2323         *lsa_policy = conn->lsa_policy;
2324         return result;
2325 }
2326
2327 /****************************************************************************
2328  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2329  session key stored in conn->netlogon_pipe->dc->sess_key.
2330 ****************************************************************************/
2331
2332 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2333                              struct rpc_pipe_client **cli)
2334 {
2335         struct winbindd_cm_conn *conn;
2336         NTSTATUS result;
2337
2338         uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2339         uint8  mach_pwd[16];
2340         uint32  sec_chan_type;
2341         const char *account_name;
2342         struct rpc_pipe_client *netlogon_pipe = NULL;
2343
2344         *cli = NULL;
2345
2346         result = init_dc_connection(domain);
2347         if (!NT_STATUS_IS_OK(result)) {
2348                 return result;
2349         }
2350
2351         if (domain->active_directory) {
2352                 neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2353         }
2354
2355         conn = &domain->conn;
2356
2357         if (conn->netlogon_pipe != NULL) {
2358                 *cli = conn->netlogon_pipe;
2359                 return NT_STATUS_OK;
2360         }
2361
2362         netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2363                                                  &result);
2364         if (netlogon_pipe == NULL) {
2365                 return result;
2366         }
2367
2368         if ((!IS_DC) && (!domain->primary)) {
2369                 /* Clear the schannel request bit and drop down */
2370                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2371                 goto no_schannel;
2372         }
2373
2374         if (lp_client_schannel() != False) {
2375                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2376         }
2377
2378         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2379                                &sec_chan_type))
2380         {
2381                 cli_rpc_pipe_close(netlogon_pipe);
2382                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2383         }
2384
2385         result = rpccli_netlogon_setup_creds(
2386                  netlogon_pipe,
2387                  domain->dcname, /* server name. */
2388                  domain->name,   /* domain name */
2389                  global_myname(), /* client name */
2390                  account_name,   /* machine account */
2391                  mach_pwd,       /* machine password */
2392                  sec_chan_type,  /* from get_trust_pw */
2393                  &neg_flags);
2394
2395         if (!NT_STATUS_IS_OK(result)) {
2396                 cli_rpc_pipe_close(netlogon_pipe);
2397                 return result;
2398         }
2399
2400         if ((lp_client_schannel() == True) &&
2401                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2402                 DEBUG(3, ("Server did not offer schannel\n"));
2403                 cli_rpc_pipe_close(netlogon_pipe);
2404                 return NT_STATUS_ACCESS_DENIED;
2405         }
2406
2407  no_schannel:
2408         if ((lp_client_schannel() == False) ||
2409                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2410                 /*
2411                  * NetSamLogonEx only works for schannel
2412                  */
2413                 domain->can_do_samlogon_ex = False;
2414
2415                 /* We're done - just keep the existing connection to NETLOGON
2416                  * open */
2417                 conn->netlogon_pipe = netlogon_pipe;
2418                 *cli = conn->netlogon_pipe;
2419                 return NT_STATUS_OK;
2420         }
2421
2422         /* Using the credentials from the first pipe, open a signed and sealed
2423            second netlogon pipe. The session key is stored in the schannel
2424            part of the new pipe auth struct.
2425         */
2426
2427         conn->netlogon_pipe =
2428                 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2429                                                     PI_NETLOGON,
2430                                                     PIPE_AUTH_LEVEL_PRIVACY,
2431                                                     domain->name,
2432                                                     netlogon_pipe->dc,
2433                                                     &result);
2434
2435         /* We can now close the initial netlogon pipe. */
2436         cli_rpc_pipe_close(netlogon_pipe);
2437
2438         if (conn->netlogon_pipe == NULL) {
2439                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2440                           "was %s\n", nt_errstr(result)));
2441                           
2442                 /* make sure we return something besides OK */
2443                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2444         }
2445
2446         /*
2447          * Try NetSamLogonEx for AD domains
2448          */
2449         domain->can_do_samlogon_ex = domain->active_directory;
2450
2451         *cli = conn->netlogon_pipe;
2452         return NT_STATUS_OK;
2453 }