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