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