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