0a5c147fd57fed3df2b6c717ebb6fac9eff00466
[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 parent_pid = sys_getpid();
175         char *lfile = NULL;
176
177         if (domain->dc_probe_pid != (pid_t)-1) {
178                 /*
179                  * We might already have a DC probe
180                  * child working, check.
181                  */
182                 if (process_exists_by_pid(domain->dc_probe_pid)) {
183                         DEBUG(10,("fork_child_dc_connect: pid %u already "
184                                 "checking for DC's.\n",
185                                 (unsigned int)domain->dc_probe_pid));
186                         return true;
187                 }
188                 domain->dc_probe_pid = (pid_t)-1;
189         }
190
191         domain->dc_probe_pid = sys_fork();
192
193         if (domain->dc_probe_pid == (pid_t)-1) {
194                 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
195                 return False;
196         }
197
198         if (domain->dc_probe_pid != (pid_t)0) {
199                 /* Parent */
200                 messaging_register(winbind_messaging_context(), NULL,
201                                    MSG_WINBIND_TRY_TO_GO_ONLINE,
202                                    msg_try_to_go_online);
203                 messaging_register(winbind_messaging_context(), NULL,
204                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
205                                    msg_failed_to_go_online);
206                 return True;
207         }
208
209         /* Child. */
210
211         /* Leave messages blocked - we will never process one. */
212
213         if (!override_logfile) {
214                 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
215                         DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
216                         _exit(1);
217                 }
218         }
219
220         if (!winbindd_reinit_after_fork(lfile)) {
221                 messaging_send_buf(winbind_messaging_context(),
222                                    pid_to_procid(parent_pid),
223                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
224                                    (uint8 *)domain->name,
225                                    strlen(domain->name)+1);
226                 _exit(1);
227         }
228         SAFE_FREE(lfile);
229
230         mem_ctx = talloc_init("fork_child_dc_connect");
231         if (!mem_ctx) {
232                 DEBUG(0,("talloc_init failed.\n"));
233                 messaging_send_buf(winbind_messaging_context(),
234                                    pid_to_procid(parent_pid),
235                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
236                                    (uint8 *)domain->name,
237                                    strlen(domain->name)+1);
238                 _exit(1);
239         }
240
241         if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
242                 /* Still offline ? Can't find DC's. */
243                 messaging_send_buf(winbind_messaging_context(),
244                                    pid_to_procid(parent_pid),
245                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
246                                    (uint8 *)domain->name,
247                                    strlen(domain->name)+1);
248                 _exit(0);
249         }
250
251         /* We got a DC. Send a message to our parent to get it to
252            try and do the same. */
253
254         messaging_send_buf(winbind_messaging_context(),
255                            pid_to_procid(parent_pid),
256                            MSG_WINBIND_TRY_TO_GO_ONLINE,
257                            (uint8 *)domain->name,
258                            strlen(domain->name)+1);
259         _exit(0);
260 }
261
262 /****************************************************************
263  Handler triggered if we're offline to try and detect a DC.
264 ****************************************************************/
265
266 static void check_domain_online_handler(struct event_context *ctx,
267                                         struct timed_event *te,
268                                         struct timeval now,
269                                         void *private_data)
270 {
271         struct winbindd_domain *domain =
272                 (struct winbindd_domain *)private_data;
273
274         DEBUG(10,("check_domain_online_handler: called for domain "
275                   "%s (online = %s)\n", domain->name, 
276                   domain->online ? "True" : "False" ));
277
278         TALLOC_FREE(domain->check_online_event);
279
280         /* Are we still in "startup" mode ? */
281
282         if (domain->startup && (now.tv_sec > domain->startup_time + 30)) {
283                 /* No longer in "startup" mode. */
284                 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
285                         domain->name ));
286                 domain->startup = False;
287         }
288
289         /* We've been told to stay offline, so stay
290            that way. */
291
292         if (get_global_winbindd_state_offline()) {
293                 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
294                         domain->name ));
295                 return;
296         }
297
298         /* Fork a child to test if it can contact a DC. 
299            If it can then send ourselves a message to
300            cause a reconnect. */
301
302         fork_child_dc_connect(domain);
303 }
304
305 /****************************************************************
306  If we're still offline setup the timeout check.
307 ****************************************************************/
308
309 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
310 {
311         int wbr = lp_winbind_reconnect_delay();
312
313         if (domain->startup) {
314                 domain->check_online_timeout = 10;
315         } else if (domain->check_online_timeout < wbr) {
316                 domain->check_online_timeout = wbr;
317         }
318 }
319
320 /****************************************************************
321  Set domain offline and also add handler to put us back online
322  if we detect a DC.
323 ****************************************************************/
324
325 void set_domain_offline(struct winbindd_domain *domain)
326 {
327         DEBUG(10,("set_domain_offline: called for domain %s\n",
328                 domain->name ));
329
330         TALLOC_FREE(domain->check_online_event);
331
332         if (domain->internal) {
333                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
334                         domain->name ));
335                 return;
336         }
337
338         domain->online = False;
339
340         /* Offline domains are always initialized. They're
341            re-initialized when they go back online. */
342
343         domain->initialized = True;
344
345         /* We only add the timeout handler that checks and
346            allows us to go back online when we've not
347            been told to remain offline. */
348
349         if (get_global_winbindd_state_offline()) {
350                 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
351                         domain->name ));
352                 return;
353         }
354
355         /* If we're in statup mode, check again in 10 seconds, not in
356            lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
357
358         calc_new_online_timeout_check(domain);
359
360         domain->check_online_event = event_add_timed(winbind_event_context(),
361                                                 NULL,
362                                                 timeval_current_ofs(domain->check_online_timeout,0),
363                                                 check_domain_online_handler,
364                                                 domain);
365
366         /* The above *has* to succeed for winbindd to work. */
367         if (!domain->check_online_event) {
368                 smb_panic("set_domain_offline: failed to add online handler");
369         }
370
371         DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
372                 domain->name ));
373
374         /* Send an offline message to the idmap child when our
375            primary domain goes offline */
376
377         if ( domain->primary ) {
378                 struct winbindd_child *idmap = idmap_child();
379
380                 if ( idmap->pid != 0 ) {
381                         messaging_send_buf(winbind_messaging_context(),
382                                            pid_to_procid(idmap->pid), 
383                                            MSG_WINBIND_OFFLINE, 
384                                            (uint8 *)domain->name, 
385                                            strlen(domain->name)+1);
386                 }                       
387         }
388
389         return; 
390 }
391
392 /****************************************************************
393  Set domain online - if allowed.
394 ****************************************************************/
395
396 static void set_domain_online(struct winbindd_domain *domain)
397 {
398         DEBUG(10,("set_domain_online: called for domain %s\n",
399                 domain->name ));
400
401         if (domain->internal) {
402                 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
403                         domain->name ));
404                 return;
405         }
406
407         if (get_global_winbindd_state_offline()) {
408                 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
409                         domain->name ));
410                 return;
411         }
412
413         winbindd_set_locator_kdc_envs(domain);
414
415         /* If we are waiting to get a krb5 ticket, trigger immediately. */
416         ccache_regain_all_now();
417
418         /* Ok, we're out of any startup mode now... */
419         domain->startup = False;
420
421         if (domain->online == False) {
422                 /* We were offline - now we're online. We default to
423                    using the MS-RPC backend if we started offline,
424                    and if we're going online for the first time we
425                    should really re-initialize the backends and the
426                    checks to see if we're talking to an AD or NT domain.
427                 */
428
429                 domain->initialized = False;
430
431                 /* 'reconnect_methods' is the MS-RPC backend. */
432                 if (domain->backend == &reconnect_methods) {
433                         domain->backend = NULL;
434                 }
435         }
436
437         /* Ensure we have no online timeout checks. */
438         domain->check_online_timeout = 0;
439         TALLOC_FREE(domain->check_online_event);
440
441         /* Ensure we ignore any pending child messages. */
442         messaging_deregister(winbind_messaging_context(),
443                              MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
444         messaging_deregister(winbind_messaging_context(),
445                              MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
446
447         domain->online = True;
448
449         /* Send an online message to the idmap child when our
450            primary domain comes online */
451
452         if ( domain->primary ) {
453                 struct winbindd_child *idmap = idmap_child();
454
455                 if ( idmap->pid != 0 ) {
456                         messaging_send_buf(winbind_messaging_context(),
457                                            pid_to_procid(idmap->pid), 
458                                            MSG_WINBIND_ONLINE, 
459                                            (uint8 *)domain->name, 
460                                            strlen(domain->name)+1);
461                 }                       
462         }
463
464         return; 
465 }
466
467 /****************************************************************
468  Requested to set a domain online.
469 ****************************************************************/
470
471 void set_domain_online_request(struct winbindd_domain *domain)
472 {
473         struct timeval tev;
474
475         DEBUG(10,("set_domain_online_request: called for domain %s\n",
476                 domain->name ));
477
478         if (get_global_winbindd_state_offline()) {
479                 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
480                         domain->name ));
481                 return;
482         }
483
484         /* We've been told it's safe to go online and
485            try and connect to a DC. But I don't believe it
486            because network manager seems to lie.
487            Wait at least 5 seconds. Heuristics suck... */
488
489
490         GetTimeOfDay(&tev);
491
492         /* Go into "startup" mode again. */
493         domain->startup_time = tev.tv_sec;
494         domain->startup = True;
495
496         tev.tv_sec += 5;
497
498         if (!domain->check_online_event) {
499                 /* If we've come from being globally offline we
500                    don't have a check online event handler set.
501                    We need to add one now we're trying to go
502                    back online. */
503
504                 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
505                         domain->name ));
506         }
507
508         TALLOC_FREE(domain->check_online_event);
509
510         domain->check_online_event = event_add_timed(winbind_event_context(),
511                                                      NULL,
512                                                      tev,
513                                                      check_domain_online_handler,
514                                                      domain);
515
516         /* The above *has* to succeed for winbindd to work. */
517         if (!domain->check_online_event) {
518                 smb_panic("set_domain_online_request: failed to add online handler");
519         }
520 }
521
522 /****************************************************************
523  Add -ve connection cache entries for domain and realm.
524 ****************************************************************/
525
526 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
527                                         const char *server,
528                                         NTSTATUS result)
529 {
530         add_failed_connection_entry(domain->name, server, result);
531         /* If this was the saf name for the last thing we talked to,
532            remove it. */
533         saf_delete(domain->name);
534         if (*domain->alt_name) {
535                 add_failed_connection_entry(domain->alt_name, server, result);
536                 saf_delete(domain->alt_name);
537         }
538         winbindd_unset_locator_kdc_env(domain);
539 }
540
541 /* Choose between anonymous or authenticated connections.  We need to use
542    an authenticated connection if DCs have the RestrictAnonymous registry
543    entry set > 0, or the "Additional restrictions for anonymous
544    connections" set in the win2k Local Security Policy. 
545
546    Caller to free() result in domain, username, password
547 */
548
549 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
550 {
551         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
552         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
553         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
554
555         if (*username && **username) {
556
557                 if (!*domain || !**domain)
558                         *domain = smb_xstrdup(lp_workgroup());
559
560                 if (!*password || !**password)
561                         *password = smb_xstrdup("");
562
563                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
564                           *domain, *username));
565
566         } else {
567                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
568                 *username = smb_xstrdup("");
569                 *domain = smb_xstrdup("");
570                 *password = smb_xstrdup("");
571         }
572 }
573
574 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
575                                      fstring dcname,
576                                      struct sockaddr_storage *dc_ss)
577 {
578         struct winbindd_domain *our_domain = NULL;
579         struct rpc_pipe_client *netlogon_pipe = NULL;
580         NTSTATUS result;
581         WERROR werr;
582         TALLOC_CTX *mem_ctx;
583         unsigned int orig_timeout;
584         const char *tmp = NULL;
585         const char *p;
586
587         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
588          * moment.... */
589
590         if (IS_DC) {
591                 return False;
592         }
593
594         if (domain->primary) {
595                 return False;
596         }
597
598         our_domain = find_our_domain();
599
600         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
601                 return False;
602         }
603
604         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
605         if (!NT_STATUS_IS_OK(result)) {
606                 talloc_destroy(mem_ctx);
607                 return False;
608         }
609
610         /* This call can take a long time - allow the server to time out.
611            35 seconds should do it. */
612
613         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
614
615         if (our_domain->active_directory) {
616                 struct netr_DsRGetDCNameInfo *domain_info = NULL;
617
618                 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
619                                                   mem_ctx,
620                                                   our_domain->dcname,
621                                                   domain->name,
622                                                   NULL,
623                                                   NULL,
624                                                   DS_RETURN_DNS_NAME,
625                                                   &domain_info,
626                                                   &werr);
627                 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
628                         tmp = talloc_strdup(
629                                 mem_ctx, domain_info->dc_unc);
630                         if (tmp == NULL) {
631                                 DEBUG(0, ("talloc_strdup failed\n"));
632                                 talloc_destroy(mem_ctx);
633                                 return false;
634                         }
635                         if (strlen(domain->alt_name) == 0) {
636                                 fstrcpy(domain->alt_name,
637                                         domain_info->domain_name);
638                         }
639                         if (strlen(domain->forest_name) == 0) {
640                                 fstrcpy(domain->forest_name,
641                                         domain_info->forest_name);
642                         }
643                 }
644         } else {
645                 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
646                                                   our_domain->dcname,
647                                                   domain->name,
648                                                   &tmp,
649                                                   &werr);
650         }
651
652         /* And restore our original timeout. */
653         rpccli_set_timeout(netlogon_pipe, orig_timeout);
654
655         if (!NT_STATUS_IS_OK(result)) {
656                 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
657                         nt_errstr(result)));
658                 talloc_destroy(mem_ctx);
659                 return false;
660         }
661
662         if (!W_ERROR_IS_OK(werr)) {
663                 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
664                            win_errstr(werr)));
665                 talloc_destroy(mem_ctx);
666                 return false;
667         }
668
669         /* rpccli_netr_GetAnyDCName gives us a name with \\ */
670         p = strip_hostname(tmp);
671
672         fstrcpy(dcname, p);
673
674         talloc_destroy(mem_ctx);
675
676         DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
677
678         if (!resolve_name(dcname, dc_ss, 0x20)) {
679                 return False;
680         }
681
682         return True;
683 }
684
685 /**
686  * Helper function to assemble trust password and account name
687  */
688 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
689                                 char **machine_password,
690                                 char **machine_account,
691                                 char **machine_krb5_principal)
692 {
693         const char *account_name;
694         const char *name = NULL;
695
696         /* If we are a DC and this is not our own domain */
697
698         if (IS_DC) {
699                 name = domain->name;
700         } else {
701                 struct winbindd_domain *our_domain = find_our_domain();
702
703                 if (!our_domain)
704                         return NT_STATUS_INVALID_SERVER_STATE;          
705
706                 name = our_domain->name;                
707         }       
708
709         if (!get_trust_pw_clear(name, machine_password,
710                                 &account_name, NULL))
711         {
712                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
713         }
714
715         if ((machine_account != NULL) &&
716             (asprintf(machine_account, "%s$", account_name) == -1))
717         {
718                 return NT_STATUS_NO_MEMORY;
719         }
720
721         /* For now assume our machine account only exists in our domain */
722
723         if (machine_krb5_principal != NULL)
724         {
725                 struct winbindd_domain *our_domain = find_our_domain();
726
727                 if (!our_domain) {
728                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;                       
729                 }
730
731                 if (asprintf(machine_krb5_principal, "%s$@%s",
732                              account_name, our_domain->alt_name) == -1)
733                 {
734                         return NT_STATUS_NO_MEMORY;
735                 }
736
737                 strupper_m(*machine_krb5_principal);
738         }
739
740         return NT_STATUS_OK;
741 }
742
743 /************************************************************************
744  Given a fd with a just-connected TCP connection to a DC, open a connection
745  to the pipe.
746 ************************************************************************/
747
748 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
749                                       const int sockfd,
750                                       const char *controller,
751                                       struct cli_state **cli,
752                                       bool *retry)
753 {
754         char *machine_password = NULL;
755         char *machine_krb5_principal = NULL;
756         char *machine_account = NULL;
757         char *ipc_username = NULL;
758         char *ipc_domain = NULL;
759         char *ipc_password = NULL;
760
761         struct named_mutex *mutex;
762
763         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
764
765         struct sockaddr peeraddr;
766         socklen_t peeraddr_len;
767
768         struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
769
770         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
771                 controller, domain->name ));
772
773         *retry = True;
774
775         mutex = grab_named_mutex(talloc_tos(), controller,
776                                  WINBIND_SERVER_MUTEX_WAIT_TIME);
777         if (mutex == NULL) {
778                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
779                          controller));
780                 result = NT_STATUS_POSSIBLE_DEADLOCK;
781                 goto done;
782         }
783
784         if ((*cli = cli_initialise()) == NULL) {
785                 DEBUG(1, ("Could not cli_initialize\n"));
786                 result = NT_STATUS_NO_MEMORY;
787                 goto done;
788         }
789
790         (*cli)->timeout = 10000;        /* 10 seconds */
791         (*cli)->fd = sockfd;
792         fstrcpy((*cli)->desthost, controller);
793         (*cli)->use_kerberos = True;
794
795         peeraddr_len = sizeof(peeraddr);
796
797         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
798                 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
799                         strerror(errno)));
800                 result = NT_STATUS_UNSUCCESSFUL;
801                 goto done;
802         }
803
804         if ((peeraddr_len != sizeof(struct sockaddr_in))
805 #ifdef HAVE_IPV6
806             && (peeraddr_len != sizeof(struct sockaddr_in6))
807 #endif
808             ) {
809                 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
810                         peeraddr_len));
811                 result = NT_STATUS_UNSUCCESSFUL;
812                 goto done;
813         }
814
815         if ((peeraddr_in->sin_family != PF_INET)
816 #ifdef HAVE_IPV6
817             && (peeraddr_in->sin_family != PF_INET6)
818 #endif
819             ) {
820                 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
821                         peeraddr_in->sin_family));
822                 result = NT_STATUS_UNSUCCESSFUL;
823                 goto done;
824         }
825
826         if (ntohs(peeraddr_in->sin_port) == 139) {
827                 struct nmb_name calling;
828                 struct nmb_name called;
829
830                 make_nmb_name(&calling, global_myname(), 0x0);
831                 make_nmb_name(&called, "*SMBSERVER", 0x20);
832
833                 if (!cli_session_request(*cli, &calling, &called)) {
834                         DEBUG(8, ("cli_session_request failed for %s\n",
835                                   controller));
836                         result = NT_STATUS_UNSUCCESSFUL;
837                         goto done;
838                 }
839         }
840
841         result = cli_negprot(*cli);
842
843         if (!NT_STATUS_IS_OK(result)) {
844                 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
845                 goto done;
846         }
847
848         if (!is_dc_trusted_domain_situation(domain->name) &&
849             (*cli)->protocol >= PROTOCOL_NT1 &&
850             (*cli)->capabilities & CAP_EXTENDED_SECURITY)
851         {
852                 ADS_STATUS ads_status;
853
854                 result = get_trust_creds(domain, &machine_password,
855                                          &machine_account,
856                                          &machine_krb5_principal);
857                 if (!NT_STATUS_IS_OK(result)) {
858                         goto anon_fallback;
859                 }
860
861                 if (lp_security() == SEC_ADS) {
862
863                         /* Try a krb5 session */
864
865                         (*cli)->use_kerberos = True;
866                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
867                                   "[%s] and realm [%s]\n", controller, global_myname(),
868                                   machine_krb5_principal, domain->alt_name));
869
870                         winbindd_set_locator_kdc_envs(domain);
871
872                         ads_status = cli_session_setup_spnego(*cli,
873                                                               machine_krb5_principal, 
874                                                               machine_password,
875                                                               lp_workgroup(),
876                                                               domain->alt_name);
877
878                         if (!ADS_ERR_OK(ads_status)) {
879                                 DEBUG(4,("failed kerberos session setup with %s\n",
880                                          ads_errstr(ads_status)));
881                         }
882
883                         result = ads_ntstatus(ads_status);
884                         if (NT_STATUS_IS_OK(result)) {
885                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
886                                 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
887                                 if (!NT_STATUS_IS_OK(result)) {
888                                         goto done;
889                                 }
890                                 goto session_setup_done;
891                         }
892                 }
893
894                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
895                 (*cli)->use_kerberos = False;
896
897                 DEBUG(5, ("connecting to %s from %s with username "
898                           "[%s]\\[%s]\n",  controller, global_myname(),
899                           lp_workgroup(), machine_account));
900
901                 ads_status = cli_session_setup_spnego(*cli,
902                                                       machine_account, 
903                                                       machine_password, 
904                                                       lp_workgroup(),
905                                                       NULL);
906                 if (!ADS_ERR_OK(ads_status)) {
907                         DEBUG(4, ("authenticated session setup failed with %s\n",
908                                 ads_errstr(ads_status)));
909                 }
910
911                 result = ads_ntstatus(ads_status);
912                 if (NT_STATUS_IS_OK(result)) {
913                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
914                         result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
915                         if (!NT_STATUS_IS_OK(result)) {
916                                 goto done;
917                         }
918                         goto session_setup_done;
919                 }
920         }
921
922         /* Fall back to non-kerberos session setup with auth_user */
923
924         (*cli)->use_kerberos = False;
925
926         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
927
928         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
929             (strlen(ipc_username) > 0)) {
930
931                 /* Only try authenticated if we have a username */
932
933                 DEBUG(5, ("connecting to %s from %s with username "
934                           "[%s]\\[%s]\n",  controller, global_myname(),
935                           ipc_domain, ipc_username));
936
937                 if (NT_STATUS_IS_OK(cli_session_setup(
938                                             *cli, ipc_username,
939                                             ipc_password, strlen(ipc_password)+1,
940                                             ipc_password, strlen(ipc_password)+1,
941                                             ipc_domain))) {
942                         /* Successful logon with given username. */
943                         result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
944                         if (!NT_STATUS_IS_OK(result)) {
945                                 goto done;
946                         }
947                         goto session_setup_done;
948                 } else {
949                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
950                                 ipc_domain, ipc_username ));
951                 }
952         }
953
954  anon_fallback:
955
956         /* Fall back to anonymous connection, this might fail later */
957         DEBUG(10,("cm_prepare_connection: falling back to anonymous "
958                 "connection for DC %s\n",
959                 controller ));
960
961         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
962                                               NULL, 0, ""))) {
963                 DEBUG(5, ("Connected anonymously\n"));
964                 result = cli_init_creds(*cli, "", "", "");
965                 if (!NT_STATUS_IS_OK(result)) {
966                         goto done;
967                 }
968                 goto session_setup_done;
969         }
970
971         result = cli_nt_error(*cli);
972
973         if (NT_STATUS_IS_OK(result))
974                 result = NT_STATUS_UNSUCCESSFUL;
975
976         /* We can't session setup */
977
978         goto done;
979
980  session_setup_done:
981
982         /* cache the server name for later connections */
983
984         saf_store( domain->name, (*cli)->desthost );
985         if (domain->alt_name && (*cli)->use_kerberos) {
986                 saf_store( domain->alt_name, (*cli)->desthost );
987         }
988
989         winbindd_set_locator_kdc_envs(domain);
990
991         result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
992
993         if (!NT_STATUS_IS_OK(result)) {
994                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
995                 goto done;
996         }
997
998         TALLOC_FREE(mutex);
999         *retry = False;
1000
1001         /* set the domain if empty; needed for schannel connections */
1002         if ( !(*cli)->domain[0] ) {
1003                 result = cli_set_domain((*cli), domain->name);
1004                 if (!NT_STATUS_IS_OK(result)) {
1005                         return result;
1006                 }
1007         }
1008
1009         result = NT_STATUS_OK;
1010
1011  done:
1012         TALLOC_FREE(mutex);
1013         SAFE_FREE(machine_account);
1014         SAFE_FREE(machine_password);
1015         SAFE_FREE(machine_krb5_principal);
1016         SAFE_FREE(ipc_username);
1017         SAFE_FREE(ipc_domain);
1018         SAFE_FREE(ipc_password);
1019
1020         if (!NT_STATUS_IS_OK(result)) {
1021                 winbind_add_failed_connection_entry(domain, controller, result);
1022                 if ((*cli) != NULL) {
1023                         cli_shutdown(*cli);
1024                         *cli = NULL;
1025                 }
1026         }
1027
1028         return result;
1029 }
1030
1031 /*******************************************************************
1032  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1033  array.
1034
1035  Keeps the list unique by not adding duplicate entries.
1036
1037  @param[in] mem_ctx talloc memory context to allocate from
1038  @param[in] domain_name domain of the DC
1039  @param[in] dcname name of the DC to add to the list
1040  @param[in] pss Internet address and port pair to add to the list
1041  @param[in,out] dcs array of dc_name_ip structures to add to
1042  @param[in,out] num_dcs number of dcs returned in the dcs array
1043  @return true if the list was added to, false otherwise
1044 *******************************************************************/
1045
1046 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1047                               const char *dcname, struct sockaddr_storage *pss,
1048                               struct dc_name_ip **dcs, int *num)
1049 {
1050         int i = 0;
1051
1052         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1053                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1054                 return False;
1055         }
1056
1057         /* Make sure there's no duplicates in the list */
1058         for (i=0; i<*num; i++)
1059                 if (sockaddr_equal((struct sockaddr *)&(*dcs)[i].ss, (struct sockaddr *)pss))
1060                         return False;
1061
1062         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1063
1064         if (*dcs == NULL)
1065                 return False;
1066
1067         fstrcpy((*dcs)[*num].name, dcname);
1068         (*dcs)[*num].ss = *pss;
1069         *num += 1;
1070         return True;
1071 }
1072
1073 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1074                                   struct sockaddr_storage *pss, uint16 port,
1075                                   struct sockaddr_storage **addrs, int *num)
1076 {
1077         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1078
1079         if (*addrs == NULL) {
1080                 *num = 0;
1081                 return False;
1082         }
1083
1084         (*addrs)[*num] = *pss;
1085         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1086
1087         *num += 1;
1088         return True;
1089 }
1090
1091 /*******************************************************************
1092  convert an ip to a name
1093 *******************************************************************/
1094
1095 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1096                 const struct winbindd_domain *domain,
1097                 struct sockaddr_storage *pss,
1098                 fstring name )
1099 {
1100         struct ip_service ip_list;
1101         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1102
1103         ip_list.ss = *pss;
1104         ip_list.port = 0;
1105
1106 #ifdef WITH_ADS
1107         /* For active directory servers, try to get the ldap server name.
1108            None of these failures should be considered critical for now */
1109
1110         if (lp_security() == SEC_ADS) {
1111                 ADS_STRUCT *ads;
1112                 ADS_STATUS ads_status;
1113                 char addr[INET6_ADDRSTRLEN];
1114
1115                 print_sockaddr(addr, sizeof(addr), pss);
1116
1117                 ads = ads_init(domain->alt_name, domain->name, addr);
1118                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1119
1120                 ads_status = ads_connect(ads);
1121                 if (ADS_ERR_OK(ads_status)) {
1122                         /* We got a cldap packet. */
1123                         fstrcpy(name, ads->config.ldap_server_name);
1124                         namecache_store(name, 0x20, 1, &ip_list);
1125
1126                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1127
1128                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1129                                 if (ads_closest_dc(ads)) {
1130                                         char *sitename = sitename_fetch(ads->config.realm);
1131
1132                                         /* We're going to use this KDC for this realm/domain.
1133                                            If we are using sites, then force the krb5 libs
1134                                            to use this KDC. */
1135
1136                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1137                                                                         domain->name,
1138                                                                         sitename,
1139                                                                         pss,
1140                                                                         name);
1141
1142                                         SAFE_FREE(sitename);
1143                                 } else {
1144                                         /* use an off site KDC */
1145                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1146                                                                         domain->name,
1147                                                                         NULL,
1148                                                                         pss,
1149                                                                         name);
1150                                 }
1151                                 winbindd_set_locator_kdc_envs(domain);
1152
1153                                 /* Ensure we contact this DC also. */
1154                                 saf_store( domain->name, name);
1155                                 saf_store( domain->alt_name, name);
1156                         }
1157
1158                         ads_destroy( &ads );
1159                         return True;
1160                 }
1161
1162                 ads_destroy( &ads );
1163         }
1164 #endif
1165
1166         /* try GETDC requests next */
1167
1168         if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1169                                pss, domain->name, &domain->sid,
1170                                nt_version)) {
1171                 const char *dc_name = NULL;
1172                 int i;
1173                 smb_msleep(100);
1174                 for (i=0; i<5; i++) {
1175                         if (receive_getdc_response(mem_ctx, pss, domain->name,
1176                                                    &nt_version,
1177                                                    &dc_name, NULL)) {
1178                                 fstrcpy(name, dc_name);
1179                                 namecache_store(name, 0x20, 1, &ip_list);
1180                                 return True;
1181                         }
1182                         smb_msleep(500);
1183                 }
1184         }
1185
1186         /* try node status request */
1187
1188         if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1189                 namecache_store(name, 0x20, 1, &ip_list);
1190                 return True;
1191         }
1192         return False;
1193 }
1194
1195 /*******************************************************************
1196  Retrieve a list of IP addresses for domain controllers.
1197
1198  The array is sorted in the preferred connection order.
1199
1200  @param[in] mem_ctx talloc memory context to allocate from
1201  @param[in] domain domain to retrieve DCs for
1202  @param[out] dcs array of dcs that will be returned
1203  @param[out] num_dcs number of dcs returned in the dcs array
1204  @return always true
1205 *******************************************************************/
1206
1207 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1208                     struct dc_name_ip **dcs, int *num_dcs)
1209 {
1210         fstring dcname;
1211         struct  sockaddr_storage ss;
1212         struct  ip_service *ip_list = NULL;
1213         int     iplist_size = 0;
1214         int     i;
1215         bool    is_our_domain;
1216         enum security_types sec = (enum security_types)lp_security();
1217
1218         is_our_domain = strequal(domain->name, lp_workgroup());
1219
1220         /* If not our domain, get the preferred DC, by asking our primary DC */
1221         if ( !is_our_domain
1222                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1223                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1224                        num_dcs) )
1225         {
1226                 char addr[INET6_ADDRSTRLEN];
1227                 print_sockaddr(addr, sizeof(addr), &ss);
1228                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1229                            dcname, addr));
1230                 return True;
1231         }
1232
1233         if (sec == SEC_ADS) {
1234                 char *sitename = NULL;
1235
1236                 /* We need to make sure we know the local site before
1237                    doing any DNS queries, as this will restrict the
1238                    get_sorted_dc_list() call below to only fetching
1239                    DNS records for the correct site. */
1240
1241                 /* Find any DC to get the site record.
1242                    We deliberately don't care about the
1243                    return here. */
1244
1245                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1246
1247                 sitename = sitename_fetch(domain->alt_name);
1248                 if (sitename) {
1249
1250                         /* Do the site-specific AD dns lookup first. */
1251                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1252                                &iplist_size, True);
1253
1254                         /* Add ips to the DC array.  We don't look up the name
1255                            of the DC in this function, but we fill in the char*
1256                            of the ip now to make the failed connection cache
1257                            work */
1258                         for ( i=0; i<iplist_size; i++ ) {
1259                                 char addr[INET6_ADDRSTRLEN];
1260                                 print_sockaddr(addr, sizeof(addr),
1261                                                 &ip_list[i].ss);
1262                                 add_one_dc_unique(mem_ctx,
1263                                                 domain->name,
1264                                                 addr,
1265                                                 &ip_list[i].ss,
1266                                                 dcs,
1267                                                 num_dcs);
1268                         }
1269
1270                         SAFE_FREE(ip_list);
1271                         SAFE_FREE(sitename);
1272                         iplist_size = 0;
1273                 }
1274
1275                 /* Now we add DCs from the main AD DNS lookup. */
1276                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1277                         &iplist_size, True);
1278
1279                 for ( i=0; i<iplist_size; i++ ) {
1280                         char addr[INET6_ADDRSTRLEN];
1281                         print_sockaddr(addr, sizeof(addr),
1282                                         &ip_list[i].ss);
1283                         add_one_dc_unique(mem_ctx,
1284                                         domain->name,
1285                                         addr,
1286                                         &ip_list[i].ss,
1287                                         dcs,
1288                                         num_dcs);
1289                 }
1290
1291                 SAFE_FREE(ip_list);
1292                 iplist_size = 0;
1293         }
1294
1295         /* Try standard netbios queries if no ADS */
1296         if (*num_dcs == 0) {
1297                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1298                        False);
1299
1300                 for ( i=0; i<iplist_size; i++ ) {
1301                         char addr[INET6_ADDRSTRLEN];
1302                         print_sockaddr(addr, sizeof(addr),
1303                                         &ip_list[i].ss);
1304                         add_one_dc_unique(mem_ctx,
1305                                         domain->name,
1306                                         addr,
1307                                         &ip_list[i].ss,
1308                                         dcs,
1309                                         num_dcs);
1310                 }
1311
1312                 SAFE_FREE(ip_list);
1313                 iplist_size = 0;
1314         }
1315
1316         return True;
1317 }
1318
1319 /*******************************************************************
1320  Find and make a connection to a DC in the given domain.
1321
1322  @param[in] mem_ctx talloc memory context to allocate from
1323  @param[in] domain domain to find a dc in
1324  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1325  @param[out] pss DC Internet address and port
1326  @param[out] fd fd of the open socket connected to the newly found dc
1327  @return true when a DC connection is made, false otherwise
1328 *******************************************************************/
1329
1330 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1331                         struct winbindd_domain *domain,
1332                         fstring dcname, struct sockaddr_storage *pss, int *fd)
1333 {
1334         struct dc_name_ip *dcs = NULL;
1335         int num_dcs = 0;
1336
1337         const char **dcnames = NULL;
1338         int num_dcnames = 0;
1339
1340         struct sockaddr_storage *addrs = NULL;
1341         int num_addrs = 0;
1342
1343         int i, fd_index;
1344
1345         *fd = -1;
1346
1347  again:
1348         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1349                 return False;
1350
1351         for (i=0; i<num_dcs; i++) {
1352
1353                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1354                                     &dcnames, &num_dcnames)) {
1355                         return False;
1356                 }
1357                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1358                                       &addrs, &num_addrs)) {
1359                         return False;
1360                 }
1361
1362                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1363                                     &dcnames, &num_dcnames)) {
1364                         return False;
1365                 }
1366                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1367                                       &addrs, &num_addrs)) {
1368                         return False;
1369                 }
1370         }
1371
1372         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1373                 return False;
1374
1375         if ((addrs == NULL) || (dcnames == NULL))
1376                 return False;
1377
1378         /* 5 second timeout. */
1379         if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1380                 for (i=0; i<num_dcs; i++) {
1381                         char ab[INET6_ADDRSTRLEN];
1382                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1383                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1384                                 "domain %s address %s. Error was %s\n",
1385                                 domain->name, ab, strerror(errno) ));
1386                         winbind_add_failed_connection_entry(domain,
1387                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1388                 }
1389                 return False;
1390         }
1391
1392         *pss = addrs[fd_index];
1393
1394         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1395                 /* Ok, we've got a name for the DC */
1396                 fstrcpy(dcname, dcnames[fd_index]);
1397                 return True;
1398         }
1399
1400         /* Try to figure out the name */
1401         if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1402                 return True;
1403         }
1404
1405         /* We can not continue without the DC's name */
1406         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1407                                     NT_STATUS_UNSUCCESSFUL);
1408
1409         /* Throw away all arrays as we're doing this again. */
1410         TALLOC_FREE(dcs);
1411         num_dcs = 0;
1412
1413         TALLOC_FREE(dcnames);
1414         num_dcnames = 0;
1415
1416         TALLOC_FREE(addrs);
1417         num_addrs = 0;
1418
1419         close(*fd);
1420         *fd = -1;
1421
1422         goto again;
1423 }
1424
1425 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1426                                    struct winbindd_cm_conn *new_conn)
1427 {
1428         TALLOC_CTX *mem_ctx;
1429         NTSTATUS result;
1430         char *saf_servername = saf_fetch( domain->name );
1431         int retries;
1432
1433         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1434                 SAFE_FREE(saf_servername);
1435                 set_domain_offline(domain);
1436                 return NT_STATUS_NO_MEMORY;
1437         }
1438
1439         /* we have to check the server affinity cache here since 
1440            later we selecte a DC based on response time and not preference */
1441
1442         /* Check the negative connection cache
1443            before talking to it. It going down may have
1444            triggered the reconnection. */
1445
1446         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1447
1448                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1449                         saf_servername, domain->name ));
1450
1451                 /* convert an ip address to a name */
1452                 if (is_ipaddress( saf_servername ) ) {
1453                         fstring saf_name;
1454                         struct sockaddr_storage ss;
1455
1456                         if (!interpret_string_addr(&ss, saf_servername,
1457                                                 AI_NUMERICHOST)) {
1458                                 return NT_STATUS_UNSUCCESSFUL;
1459                         }
1460                         if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1461                                 fstrcpy( domain->dcname, saf_name );
1462                         } else {
1463                                 winbind_add_failed_connection_entry(
1464                                         domain, saf_servername,
1465                                         NT_STATUS_UNSUCCESSFUL);
1466                         }
1467                 } else {
1468                         fstrcpy( domain->dcname, saf_servername );
1469                 }
1470
1471                 SAFE_FREE( saf_servername );
1472         }
1473
1474         for (retries = 0; retries < 3; retries++) {
1475                 int fd = -1;
1476                 bool retry = False;
1477
1478                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1479
1480                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1481                         domain->dcname, domain->name ));
1482
1483                 if (*domain->dcname 
1484                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1485                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1486                 {
1487                         struct sockaddr_storage *addrs = NULL;
1488                         int num_addrs = 0;
1489                         int dummy = 0;
1490
1491                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1492                                 set_domain_offline(domain);
1493                                 talloc_destroy(mem_ctx);
1494                                 return NT_STATUS_NO_MEMORY;
1495                         }
1496                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1497                                 set_domain_offline(domain);
1498                                 talloc_destroy(mem_ctx);
1499                                 return NT_STATUS_NO_MEMORY;
1500                         }
1501
1502                         /* 5 second timeout. */
1503                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1504                                 fd = -1;
1505                         }
1506                 }
1507
1508                 if ((fd == -1) 
1509                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1510                 {
1511                         /* This is the one place where we will
1512                            set the global winbindd offline state
1513                            to true, if a "WINBINDD_OFFLINE" entry
1514                            is found in the winbindd cache. */
1515                         set_global_winbindd_state_offline();
1516                         break;
1517                 }
1518
1519                 new_conn->cli = NULL;
1520
1521                 result = cm_prepare_connection(domain, fd, domain->dcname,
1522                         &new_conn->cli, &retry);
1523
1524                 if (!retry)
1525                         break;
1526         }
1527
1528         if (NT_STATUS_IS_OK(result)) {
1529
1530                 winbindd_set_locator_kdc_envs(domain);
1531
1532                 if (domain->online == False) {
1533                         /* We're changing state from offline to online. */
1534                         set_global_winbindd_state_online();
1535                 }
1536                 set_domain_online(domain);
1537         } else {
1538                 /* Ensure we setup the retry handler. */
1539                 set_domain_offline(domain);
1540         }
1541
1542         talloc_destroy(mem_ctx);
1543         return result;
1544 }
1545
1546 /* Close down all open pipes on a connection. */
1547
1548 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1549 {
1550         /* We're closing down a possibly dead
1551            connection. Don't have impossibly long (10s) timeouts. */
1552
1553         if (conn->cli) {
1554                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1555         }
1556
1557         if (conn->samr_pipe != NULL) {
1558                 TALLOC_FREE(conn->samr_pipe);
1559                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1560                 if (conn->cli) {
1561                         cli_set_timeout(conn->cli, 500);
1562                 }
1563         }
1564
1565         if (conn->lsa_pipe != NULL) {
1566                 TALLOC_FREE(conn->lsa_pipe);
1567                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1568                 if (conn->cli) {
1569                         cli_set_timeout(conn->cli, 500);
1570                 }
1571         }
1572
1573         if (conn->lsa_pipe_tcp != NULL) {
1574                 TALLOC_FREE(conn->lsa_pipe_tcp);
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
1581         if (conn->netlogon_pipe != NULL) {
1582                 TALLOC_FREE(conn->netlogon_pipe);
1583                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1584                 if (conn->cli) {
1585                         cli_set_timeout(conn->cli, 500);
1586                 }
1587         }
1588
1589         if (conn->cli) {
1590                 cli_shutdown(conn->cli);
1591         }
1592
1593         conn->cli = NULL;
1594 }
1595
1596 void close_conns_after_fork(void)
1597 {
1598         struct winbindd_domain *domain;
1599
1600         for (domain = domain_list(); domain; domain = domain->next) {
1601                 if (domain->conn.cli == NULL)
1602                         continue;
1603
1604                 if (domain->conn.cli->fd == -1)
1605                         continue;
1606
1607                 close(domain->conn.cli->fd);
1608                 domain->conn.cli->fd = -1;
1609         }
1610 }
1611
1612 static bool connection_ok(struct winbindd_domain *domain)
1613 {
1614         bool ok;
1615
1616         ok = cli_state_is_connected(domain->conn.cli);
1617         if (!ok) {
1618                 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1619                           domain->dcname, domain->name));
1620                 return False;
1621         }
1622
1623         if (domain->online == False) {
1624                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1625                 return False;
1626         }
1627
1628         return True;
1629 }
1630
1631 /* Initialize a new connection up to the RPC BIND.
1632    Bypass online status check so always does network calls. */
1633
1634 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1635 {
1636         NTSTATUS result;
1637
1638         /* Internal connections never use the network. */
1639         if (domain->internal) {
1640                 domain->initialized = True;
1641                 return NT_STATUS_OK;
1642         }
1643
1644         if (!winbindd_can_contact_domain(domain)) {
1645                 invalidate_cm_connection(&domain->conn);
1646                 domain->initialized = True;
1647                 return NT_STATUS_OK;
1648         }
1649
1650         if (connection_ok(domain)) {
1651                 if (!domain->initialized) {
1652                         set_dc_type_and_flags(domain);
1653                 }
1654                 return NT_STATUS_OK;
1655         }
1656
1657         invalidate_cm_connection(&domain->conn);
1658
1659         result = cm_open_connection(domain, &domain->conn);
1660
1661         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1662                 set_dc_type_and_flags(domain);
1663         }
1664
1665         return result;
1666 }
1667
1668 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1669 {
1670         if (domain->initialized && !domain->online) {
1671                 /* We check for online status elsewhere. */
1672                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1673         }
1674
1675         return init_dc_connection_network(domain);
1676 }
1677
1678 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1679 {
1680         NTSTATUS status;
1681
1682         status = init_dc_connection(domain);
1683         if (!NT_STATUS_IS_OK(status)) {
1684                 return status;
1685         }
1686
1687         if (!domain->internal && domain->conn.cli == NULL) {
1688                 /* happens for trusted domains without inbound trust */
1689                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1690         }
1691
1692         return NT_STATUS_OK;
1693 }
1694
1695 /******************************************************************************
1696  Set the trust flags (direction and forest location) for a domain
1697 ******************************************************************************/
1698
1699 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1700 {
1701         struct winbindd_domain *our_domain;
1702         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1703         struct netr_DomainTrustList trusts;
1704         int i;
1705         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1706                         NETR_TRUST_FLAG_OUTBOUND |
1707                         NETR_TRUST_FLAG_INBOUND);
1708         struct rpc_pipe_client *cli;
1709         TALLOC_CTX *mem_ctx = NULL;
1710
1711         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1712
1713         /* Our primary domain doesn't need to worry about trust flags.
1714            Force it to go through the network setup */
1715         if ( domain->primary ) {                
1716                 return False;           
1717         }
1718
1719         our_domain = find_our_domain();
1720
1721         if ( !connection_ok(our_domain) ) {
1722                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1723                 return False;
1724         }
1725
1726         /* This won't work unless our domain is AD */
1727
1728         if ( !our_domain->active_directory ) {
1729                 return False;
1730         }
1731
1732         /* Use DsEnumerateDomainTrusts to get us the trust direction
1733            and type */
1734
1735         result = cm_connect_netlogon(our_domain, &cli);
1736
1737         if (!NT_STATUS_IS_OK(result)) {
1738                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1739                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1740                           domain->name, nt_errstr(result)));
1741                 return False;
1742         }
1743
1744         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1745                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1746                 return False;
1747         }       
1748
1749         result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1750                                                       cli->desthost,
1751                                                       flags,
1752                                                       &trusts,
1753                                                       NULL);
1754         if (!NT_STATUS_IS_OK(result)) {
1755                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1756                         "failed to query trusted domain list: %s\n",
1757                         nt_errstr(result)));
1758                 talloc_destroy(mem_ctx);
1759                 return false;
1760         }
1761
1762         /* Now find the domain name and get the flags */
1763
1764         for ( i=0; i<trusts.count; i++ ) {
1765                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1766                         domain->domain_flags          = trusts.array[i].trust_flags;
1767                         domain->domain_type           = trusts.array[i].trust_type;
1768                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1769
1770                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1771                                 domain->active_directory = True;
1772
1773                         /* This flag is only set if the domain is *our* 
1774                            primary domain and the primary domain is in
1775                            native mode */
1776
1777                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1778
1779                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1780                                   "native mode.\n", domain->name, 
1781                                   domain->native_mode ? "" : "NOT "));
1782
1783                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1784                                  "running active directory.\n", domain->name, 
1785                                  domain->active_directory ? "" : "NOT "));
1786
1787
1788                         domain->initialized = True;
1789
1790                         break;
1791                 }               
1792         }
1793
1794         talloc_destroy( mem_ctx );
1795
1796         return domain->initialized;     
1797 }
1798
1799 /******************************************************************************
1800  We can 'sense' certain things about the DC by it's replies to certain
1801  questions.
1802
1803  This tells us if this particular remote server is Active Directory, and if it
1804  is native mode.
1805 ******************************************************************************/
1806
1807 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1808 {
1809         NTSTATUS                result;
1810         WERROR werr;
1811         TALLOC_CTX              *mem_ctx = NULL;
1812         struct rpc_pipe_client  *cli = NULL;
1813         struct policy_handle pol;
1814         union dssetup_DsRoleInfo info;
1815         union lsa_PolicyInformation *lsa_info = NULL;
1816
1817         if (!connection_ok(domain)) {
1818                 return;
1819         }
1820
1821         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1822                               domain->name);
1823         if (!mem_ctx) {
1824                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1825                 return;
1826         }
1827
1828         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1829
1830         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1831                                           &ndr_table_dssetup.syntax_id,
1832                                           &cli);
1833
1834         if (!NT_STATUS_IS_OK(result)) {
1835                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1836                           "PI_DSSETUP on domain %s: (%s)\n",
1837                           domain->name, nt_errstr(result)));
1838
1839                 /* if this is just a non-AD domain we need to continue
1840                  * identifying so that we can in the end return with
1841                  * domain->initialized = True - gd */
1842
1843                 goto no_dssetup;
1844         }
1845
1846         result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1847                                                                   DS_ROLE_BASIC_INFORMATION,
1848                                                                   &info,
1849                                                                   &werr);
1850         TALLOC_FREE(cli);
1851
1852         if (!NT_STATUS_IS_OK(result)) {
1853                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1854                           "on domain %s failed: (%s)\n",
1855                           domain->name, nt_errstr(result)));
1856
1857                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1858                  * every opcode on the DSSETUP pipe, continue with
1859                  * no_dssetup mode here as well to get domain->initialized
1860                  * set - gd */
1861
1862                 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1863                         goto no_dssetup;
1864                 }
1865
1866                 TALLOC_FREE(mem_ctx);
1867                 return;
1868         }
1869
1870         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1871             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1872                 domain->native_mode = True;
1873         } else {
1874                 domain->native_mode = False;
1875         }
1876
1877 no_dssetup:
1878         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1879                                           &ndr_table_lsarpc.syntax_id, &cli);
1880
1881         if (!NT_STATUS_IS_OK(result)) {
1882                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1883                           "PI_LSARPC on domain %s: (%s)\n",
1884                           domain->name, nt_errstr(result)));
1885                 TALLOC_FREE(cli);
1886                 TALLOC_FREE(mem_ctx);
1887                 return;
1888         }
1889
1890         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1891                                          SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1892
1893         if (NT_STATUS_IS_OK(result)) {
1894                 /* This particular query is exactly what Win2k clients use 
1895                    to determine that the DC is active directory */
1896                 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1897                                                      &pol,
1898                                                      LSA_POLICY_INFO_DNS,
1899                                                      &lsa_info);
1900         }
1901
1902         if (NT_STATUS_IS_OK(result)) {
1903                 domain->active_directory = True;
1904
1905                 if (lsa_info->dns.name.string) {
1906                         fstrcpy(domain->name, lsa_info->dns.name.string);
1907                 }
1908
1909                 if (lsa_info->dns.dns_domain.string) {
1910                         fstrcpy(domain->alt_name,
1911                                 lsa_info->dns.dns_domain.string);
1912                 }
1913
1914                 /* See if we can set some domain trust flags about
1915                    ourself */
1916
1917                 if (lsa_info->dns.dns_forest.string) {
1918                         fstrcpy(domain->forest_name,
1919                                 lsa_info->dns.dns_forest.string);
1920
1921                         if (strequal(domain->forest_name, domain->alt_name)) {
1922                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1923                         }
1924                 }
1925
1926                 if (lsa_info->dns.sid) {
1927                         sid_copy(&domain->sid, lsa_info->dns.sid);
1928                 }
1929         } else {
1930                 domain->active_directory = False;
1931
1932                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1933                                                 SEC_FLAG_MAXIMUM_ALLOWED,
1934                                                 &pol);
1935
1936                 if (!NT_STATUS_IS_OK(result)) {
1937                         goto done;
1938                 }
1939
1940                 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1941                                                     &pol,
1942                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1943                                                     &lsa_info);
1944
1945                 if (NT_STATUS_IS_OK(result)) {
1946
1947                         if (lsa_info->account_domain.name.string) {
1948                                 fstrcpy(domain->name,
1949                                         lsa_info->account_domain.name.string);
1950                         }
1951
1952                         if (lsa_info->account_domain.sid) {
1953                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1954                         }
1955                 }
1956         }
1957 done:
1958
1959         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1960                   domain->name, domain->native_mode ? "" : "NOT "));
1961
1962         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1963                   domain->name, domain->active_directory ? "" : "NOT "));
1964
1965         domain->can_do_ncacn_ip_tcp = domain->active_directory;
1966
1967         TALLOC_FREE(cli);
1968
1969         TALLOC_FREE(mem_ctx);
1970
1971         domain->initialized = True;
1972 }
1973
1974 /**********************************************************************
1975  Set the domain_flags (trust attributes, domain operating modes, etc... 
1976 ***********************************************************************/
1977
1978 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1979 {
1980         /* we always have to contact our primary domain */
1981
1982         if ( domain->primary ) {
1983                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1984                           "primary domain\n"));
1985                 set_dc_type_and_flags_connect( domain );
1986                 return;         
1987         }
1988
1989         /* Use our DC to get the information if possible */
1990
1991         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1992                 /* Otherwise, fallback to contacting the 
1993                    domain directly */
1994                 set_dc_type_and_flags_connect( domain );
1995         }
1996
1997         return;
1998 }
1999
2000
2001
2002 /**********************************************************************
2003 ***********************************************************************/
2004
2005 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
2006                                    struct dcinfo **ppdc)
2007 {
2008         NTSTATUS result;
2009         struct rpc_pipe_client *netlogon_pipe;
2010
2011         if (lp_client_schannel() == False) {
2012                 return False;
2013         }
2014
2015         result = cm_connect_netlogon(domain, &netlogon_pipe);
2016         if (!NT_STATUS_IS_OK(result)) {
2017                 return False;
2018         }
2019
2020         /* Return a pointer to the struct dcinfo from the
2021            netlogon pipe. */
2022
2023         if (!domain->conn.netlogon_pipe->dc) {
2024                 return false;
2025         }
2026
2027         *ppdc = domain->conn.netlogon_pipe->dc;
2028         return True;
2029 }
2030
2031 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2032                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2033 {
2034         struct winbindd_cm_conn *conn;
2035         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2036         struct dcinfo *p_dcinfo;
2037         char *machine_password = NULL;
2038         char *machine_account = NULL;
2039         char *domain_name = NULL;
2040
2041         result = init_dc_connection_rpc(domain);
2042         if (!NT_STATUS_IS_OK(result)) {
2043                 return result;
2044         }
2045
2046         conn = &domain->conn;
2047
2048         if (rpccli_is_connected(conn->samr_pipe)) {
2049                 goto done;
2050         }
2051
2052         TALLOC_FREE(conn->samr_pipe);
2053
2054         /*
2055          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2056          * sign and sealed pipe using the machine account password by
2057          * preference. If we can't - try schannel, if that fails, try
2058          * anonymous.
2059          */
2060
2061         if ((conn->cli->user_name[0] == '\0') ||
2062             (conn->cli->domain[0] == '\0') || 
2063             (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2064         {
2065                 result = get_trust_creds(domain, &machine_password,
2066                                          &machine_account, NULL);
2067                 if (!NT_STATUS_IS_OK(result)) {
2068                         DEBUG(10, ("cm_connect_sam: No no user available for "
2069                                    "domain %s, trying schannel\n", conn->cli->domain));
2070                         goto schannel;
2071                 }
2072                 domain_name = domain->name;
2073         } else {
2074                 machine_password = SMB_STRDUP(conn->cli->password);
2075                 machine_account = SMB_STRDUP(conn->cli->user_name);
2076                 domain_name = conn->cli->domain;
2077         }
2078
2079         if (!machine_password || !machine_account) {
2080                 result = NT_STATUS_NO_MEMORY;
2081                 goto done;
2082         }
2083
2084         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2085            authenticated SAMR pipe with sign & seal. */
2086         result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2087                                                   &ndr_table_samr.syntax_id,
2088                                                   NCACN_NP,
2089                                                   PIPE_AUTH_LEVEL_PRIVACY,
2090                                                   domain_name,
2091                                                   machine_account,
2092                                                   machine_password,
2093                                                   &conn->samr_pipe);
2094
2095         if (!NT_STATUS_IS_OK(result)) {
2096                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2097                           "pipe for domain %s using NTLMSSP "
2098                           "authenticated pipe: user %s\\%s. Error was "
2099                           "%s\n", domain->name, domain_name,
2100                           machine_account, nt_errstr(result)));
2101                 goto schannel;
2102         }
2103
2104         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2105                   "domain %s using NTLMSSP authenticated "
2106                   "pipe: user %s\\%s\n", domain->name,
2107                   domain_name, machine_account));
2108
2109         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2110                                       conn->samr_pipe->desthost,
2111                                       SEC_FLAG_MAXIMUM_ALLOWED,
2112                                       &conn->sam_connect_handle);
2113         if (NT_STATUS_IS_OK(result)) {
2114                 goto open_domain;
2115         }
2116         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2117                   "failed for domain %s, error was %s. Trying schannel\n",
2118                   domain->name, nt_errstr(result) ));
2119         TALLOC_FREE(conn->samr_pipe);
2120
2121  schannel:
2122
2123         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2124
2125         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2126                 /* If this call fails - conn->cli can now be NULL ! */
2127                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2128                            "for domain %s, trying anon\n", domain->name));
2129                 goto anonymous;
2130         }
2131         result = cli_rpc_pipe_open_schannel_with_key
2132                 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2133                 PIPE_AUTH_LEVEL_PRIVACY,
2134                  domain->name, p_dcinfo, &conn->samr_pipe);
2135
2136         if (!NT_STATUS_IS_OK(result)) {
2137                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2138                           "domain %s using schannel. Error was %s\n",
2139                           domain->name, nt_errstr(result) ));
2140                 goto anonymous;
2141         }
2142         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2143                   "schannel.\n", domain->name ));
2144
2145         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2146                                       conn->samr_pipe->desthost,
2147                                       SEC_FLAG_MAXIMUM_ALLOWED,
2148                                       &conn->sam_connect_handle);
2149         if (NT_STATUS_IS_OK(result)) {
2150                 goto open_domain;
2151         }
2152         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2153                   "for domain %s, error was %s. Trying anonymous\n",
2154                   domain->name, nt_errstr(result) ));
2155         TALLOC_FREE(conn->samr_pipe);
2156
2157  anonymous:
2158
2159         /* Finally fall back to anonymous. */
2160         result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2161                                           &conn->samr_pipe);
2162
2163         if (!NT_STATUS_IS_OK(result)) {
2164                 goto done;
2165         }
2166
2167         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2168                                       conn->samr_pipe->desthost,
2169                                       SEC_FLAG_MAXIMUM_ALLOWED,
2170                                       &conn->sam_connect_handle);
2171         if (!NT_STATUS_IS_OK(result)) {
2172                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2173                           "for domain %s Error was %s\n",
2174                           domain->name, nt_errstr(result) ));
2175                 goto done;
2176         }
2177
2178  open_domain:
2179         result = rpccli_samr_OpenDomain(conn->samr_pipe,
2180                                         mem_ctx,
2181                                         &conn->sam_connect_handle,
2182                                         SEC_FLAG_MAXIMUM_ALLOWED,
2183                                         &domain->sid,
2184                                         &conn->sam_domain_handle);
2185
2186  done:
2187
2188         if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2189                 /*
2190                  * if we got access denied, we might just have no access rights
2191                  * to talk to the remote samr server server (e.g. when we are a
2192                  * PDC and we are connecting a w2k8 pdc via an interdomain
2193                  * trust). In that case do not invalidate the whole connection
2194                  * stack
2195                  */
2196                 TALLOC_FREE(conn->samr_pipe);
2197                 ZERO_STRUCT(conn->sam_domain_handle);
2198                 return result;
2199         } else if (!NT_STATUS_IS_OK(result)) {
2200                 invalidate_cm_connection(conn);
2201                 return result;
2202         }
2203
2204         *cli = conn->samr_pipe;
2205         *sam_handle = conn->sam_domain_handle;
2206         SAFE_FREE(machine_password);
2207         SAFE_FREE(machine_account);
2208         return result;
2209 }
2210
2211 /**********************************************************************
2212  open an schanneld ncacn_ip_tcp connection to LSA
2213 ***********************************************************************/
2214
2215 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2216                             TALLOC_CTX *mem_ctx,
2217                             struct rpc_pipe_client **cli)
2218 {
2219         struct winbindd_cm_conn *conn;
2220         struct dcinfo *dcinfo;
2221         NTSTATUS status;
2222
2223         DEBUG(10,("cm_connect_lsa_tcp\n"));
2224
2225         status = init_dc_connection_rpc(domain);
2226         if (!NT_STATUS_IS_OK(status)) {
2227                 return status;
2228         }
2229
2230         conn = &domain->conn;
2231
2232         if (conn->lsa_pipe_tcp &&
2233             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2234             conn->lsa_pipe_tcp->auth->auth_level == PIPE_AUTH_LEVEL_PRIVACY &&
2235             rpccli_is_connected(conn->lsa_pipe_tcp)) {
2236                 goto done;
2237         }
2238
2239         TALLOC_FREE(conn->lsa_pipe_tcp);
2240
2241         if (!cm_get_schannel_dcinfo(domain, &dcinfo)) {
2242                 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2243                 goto done;
2244         }
2245
2246         status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2247                                                      &ndr_table_lsarpc.syntax_id,
2248                                                      NCACN_IP_TCP,
2249                                                      PIPE_AUTH_LEVEL_PRIVACY,
2250                                                      domain->name,
2251                                                      dcinfo,
2252                                                      &conn->lsa_pipe_tcp);
2253         if (!NT_STATUS_IS_OK(status)) {
2254                 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2255                         nt_errstr(status)));
2256                 goto done;
2257         }
2258
2259  done:
2260         if (!NT_STATUS_IS_OK(status)) {
2261                 TALLOC_FREE(conn->lsa_pipe_tcp);
2262                 return status;
2263         }
2264
2265         *cli = conn->lsa_pipe_tcp;
2266
2267         return status;
2268 }
2269
2270 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2271                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2272 {
2273         struct winbindd_cm_conn *conn;
2274         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2275         struct dcinfo *p_dcinfo;
2276
2277         result = init_dc_connection_rpc(domain);
2278         if (!NT_STATUS_IS_OK(result))
2279                 return result;
2280
2281         conn = &domain->conn;
2282
2283         if (rpccli_is_connected(conn->lsa_pipe)) {
2284                 goto done;
2285         }
2286
2287         TALLOC_FREE(conn->lsa_pipe);
2288
2289         if ((conn->cli->user_name[0] == '\0') ||
2290             (conn->cli->domain[0] == '\0') || 
2291             (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2292                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2293                            "domain %s, trying schannel\n", conn->cli->domain));
2294                 goto schannel;
2295         }
2296
2297         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2298          * authenticated LSA pipe with sign & seal. */
2299         result = cli_rpc_pipe_open_spnego_ntlmssp
2300                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2301                  PIPE_AUTH_LEVEL_PRIVACY,
2302                  conn->cli->domain, conn->cli->user_name, conn->cli->password,
2303                  &conn->lsa_pipe);
2304
2305         if (!NT_STATUS_IS_OK(result)) {
2306                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2307                           "domain %s using NTLMSSP authenticated pipe: user "
2308                           "%s\\%s. Error was %s. Trying schannel.\n",
2309                           domain->name, conn->cli->domain,
2310                           conn->cli->user_name, nt_errstr(result)));
2311                 goto schannel;
2312         }
2313
2314         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2315                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2316                   domain->name, conn->cli->domain, conn->cli->user_name ));
2317
2318         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2319                                         SEC_FLAG_MAXIMUM_ALLOWED,
2320                                         &conn->lsa_policy);
2321         if (NT_STATUS_IS_OK(result)) {
2322                 goto done;
2323         }
2324
2325         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2326                   "schannel\n"));
2327
2328         TALLOC_FREE(conn->lsa_pipe);
2329
2330  schannel:
2331
2332         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2333
2334         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2335                 /* If this call fails - conn->cli can now be NULL ! */
2336                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2337                            "for domain %s, trying anon\n", domain->name));
2338                 goto anonymous;
2339         }
2340         result = cli_rpc_pipe_open_schannel_with_key
2341                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2342                  PIPE_AUTH_LEVEL_PRIVACY,
2343                  domain->name, p_dcinfo, &conn->lsa_pipe);
2344
2345         if (!NT_STATUS_IS_OK(result)) {
2346                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2347                           "domain %s using schannel. Error was %s\n",
2348                           domain->name, nt_errstr(result) ));
2349                 goto anonymous;
2350         }
2351         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2352                   "schannel.\n", domain->name ));
2353
2354         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2355                                         SEC_FLAG_MAXIMUM_ALLOWED,
2356                                         &conn->lsa_policy);
2357         if (NT_STATUS_IS_OK(result)) {
2358                 goto done;
2359         }
2360
2361         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2362                   "anonymous\n"));
2363
2364         TALLOC_FREE(conn->lsa_pipe);
2365
2366  anonymous:
2367
2368         result = cli_rpc_pipe_open_noauth(conn->cli,
2369                                           &ndr_table_lsarpc.syntax_id,
2370                                           &conn->lsa_pipe);
2371         if (!NT_STATUS_IS_OK(result)) {
2372                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2373                 goto done;
2374         }
2375
2376         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2377                                         SEC_FLAG_MAXIMUM_ALLOWED,
2378                                         &conn->lsa_policy);
2379  done:
2380         if (!NT_STATUS_IS_OK(result)) {
2381                 invalidate_cm_connection(conn);
2382                 return result;
2383         }
2384
2385         *cli = conn->lsa_pipe;
2386         *lsa_policy = conn->lsa_policy;
2387         return result;
2388 }
2389
2390 /****************************************************************************
2391  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2392  session key stored in conn->netlogon_pipe->dc->sess_key.
2393 ****************************************************************************/
2394
2395 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2396                              struct rpc_pipe_client **cli)
2397 {
2398         struct winbindd_cm_conn *conn;
2399         NTSTATUS result;
2400
2401         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2402         uint8  mach_pwd[16];
2403         uint32  sec_chan_type;
2404         const char *account_name;
2405         struct rpc_pipe_client *netlogon_pipe = NULL;
2406
2407         *cli = NULL;
2408
2409         result = init_dc_connection_rpc(domain);
2410         if (!NT_STATUS_IS_OK(result)) {
2411                 return result;
2412         }
2413
2414         conn = &domain->conn;
2415
2416         if (rpccli_is_connected(conn->netlogon_pipe)) {
2417                 *cli = conn->netlogon_pipe;
2418                 return NT_STATUS_OK;
2419         }
2420
2421         TALLOC_FREE(conn->netlogon_pipe);
2422
2423         result = cli_rpc_pipe_open_noauth(conn->cli,
2424                                           &ndr_table_netlogon.syntax_id,
2425                                           &netlogon_pipe);
2426         if (!NT_STATUS_IS_OK(result)) {
2427                 return result;
2428         }
2429
2430         if ((!IS_DC) && (!domain->primary)) {
2431                 /* Clear the schannel request bit and drop down */
2432                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2433                 goto no_schannel;
2434         }
2435
2436         if (lp_client_schannel() != False) {
2437                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2438         }
2439
2440         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2441                                &sec_chan_type))
2442         {
2443                 TALLOC_FREE(netlogon_pipe);
2444                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2445         }
2446
2447         result = rpccli_netlogon_setup_creds(
2448                  netlogon_pipe,
2449                  domain->dcname, /* server name. */
2450                  domain->name,   /* domain name */
2451                  global_myname(), /* client name */
2452                  account_name,   /* machine account */
2453                  mach_pwd,       /* machine password */
2454                  sec_chan_type,  /* from get_trust_pw */
2455                  &neg_flags);
2456
2457         if (!NT_STATUS_IS_OK(result)) {
2458                 TALLOC_FREE(netlogon_pipe);
2459                 return result;
2460         }
2461
2462         if ((lp_client_schannel() == True) &&
2463                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2464                 DEBUG(3, ("Server did not offer schannel\n"));
2465                 TALLOC_FREE(netlogon_pipe);
2466                 return NT_STATUS_ACCESS_DENIED;
2467         }
2468
2469  no_schannel:
2470         if ((lp_client_schannel() == False) ||
2471                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2472                 /*
2473                  * NetSamLogonEx only works for schannel
2474                  */
2475                 domain->can_do_samlogon_ex = False;
2476
2477                 /* We're done - just keep the existing connection to NETLOGON
2478                  * open */
2479                 conn->netlogon_pipe = netlogon_pipe;
2480                 *cli = conn->netlogon_pipe;
2481                 return NT_STATUS_OK;
2482         }
2483
2484         /* Using the credentials from the first pipe, open a signed and sealed
2485            second netlogon pipe. The session key is stored in the schannel
2486            part of the new pipe auth struct.
2487         */
2488
2489         result = cli_rpc_pipe_open_schannel_with_key(
2490                 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2491                 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2492                 &conn->netlogon_pipe);
2493
2494         /* We can now close the initial netlogon pipe. */
2495         TALLOC_FREE(netlogon_pipe);
2496
2497         if (!NT_STATUS_IS_OK(result)) {
2498                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2499                           "was %s\n", nt_errstr(result)));
2500
2501                 invalidate_cm_connection(conn);
2502                 return result;
2503         }
2504
2505         /*
2506          * Try NetSamLogonEx for AD domains
2507          */
2508         domain->can_do_samlogon_ex = domain->active_directory;
2509
2510         *cli = conn->netlogon_pipe;
2511         return NT_STATUS_OK;
2512 }