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