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