Second part of fix for bug 8953 - winbind can hang as nbt_getdc() has no timeout.
[ddiss/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                         return result;
1027                 }
1028         }
1029
1030         result = NT_STATUS_OK;
1031
1032  done:
1033         TALLOC_FREE(mutex);
1034         SAFE_FREE(machine_account);
1035         SAFE_FREE(machine_password);
1036         SAFE_FREE(machine_krb5_principal);
1037         SAFE_FREE(ipc_username);
1038         SAFE_FREE(ipc_domain);
1039         SAFE_FREE(ipc_password);
1040
1041         if (!NT_STATUS_IS_OK(result)) {
1042                 winbind_add_failed_connection_entry(domain, controller, result);
1043                 if ((*cli) != NULL) {
1044                         cli_shutdown(*cli);
1045                         *cli = NULL;
1046                 }
1047         }
1048
1049         return result;
1050 }
1051
1052 /*******************************************************************
1053  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1054  array.
1055
1056  Keeps the list unique by not adding duplicate entries.
1057
1058  @param[in] mem_ctx talloc memory context to allocate from
1059  @param[in] domain_name domain of the DC
1060  @param[in] dcname name of the DC to add to the list
1061  @param[in] pss Internet address and port pair to add to the list
1062  @param[in,out] dcs array of dc_name_ip structures to add to
1063  @param[in,out] num_dcs number of dcs returned in the dcs array
1064  @return true if the list was added to, false otherwise
1065 *******************************************************************/
1066
1067 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1068                               const char *dcname, struct sockaddr_storage *pss,
1069                               struct dc_name_ip **dcs, int *num)
1070 {
1071         int i = 0;
1072
1073         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1074                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1075                 return False;
1076         }
1077
1078         /* Make sure there's no duplicates in the list */
1079         for (i=0; i<*num; i++)
1080                 if (sockaddr_equal(
1081                             (struct sockaddr *)(void *)&(*dcs)[i].ss,
1082                             (struct sockaddr *)(void *)pss))
1083                         return False;
1084
1085         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1086
1087         if (*dcs == NULL)
1088                 return False;
1089
1090         fstrcpy((*dcs)[*num].name, dcname);
1091         (*dcs)[*num].ss = *pss;
1092         *num += 1;
1093         return True;
1094 }
1095
1096 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1097                                   struct sockaddr_storage *pss, uint16 port,
1098                                   struct sockaddr_storage **addrs, int *num)
1099 {
1100         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1101
1102         if (*addrs == NULL) {
1103                 *num = 0;
1104                 return False;
1105         }
1106
1107         (*addrs)[*num] = *pss;
1108         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1109
1110         *num += 1;
1111         return True;
1112 }
1113
1114 /*******************************************************************
1115  convert an ip to a name
1116 *******************************************************************/
1117
1118 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1119                 const struct winbindd_domain *domain,
1120                 struct sockaddr_storage *pss,
1121                 fstring name )
1122 {
1123         struct ip_service ip_list;
1124         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1125         NTSTATUS status;
1126         const char *dc_name;
1127
1128         ip_list.ss = *pss;
1129         ip_list.port = 0;
1130
1131 #ifdef HAVE_ADS
1132         /* For active directory servers, try to get the ldap server name.
1133            None of these failures should be considered critical for now */
1134
1135         if (lp_security() == SEC_ADS) {
1136                 ADS_STRUCT *ads;
1137                 ADS_STATUS ads_status;
1138                 char addr[INET6_ADDRSTRLEN];
1139
1140                 print_sockaddr(addr, sizeof(addr), pss);
1141
1142                 ads = ads_init(domain->alt_name, domain->name, addr);
1143                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1144
1145                 ads_status = ads_connect(ads);
1146                 if (ADS_ERR_OK(ads_status)) {
1147                         /* We got a cldap packet. */
1148                         fstrcpy(name, ads->config.ldap_server_name);
1149                         namecache_store(name, 0x20, 1, &ip_list);
1150
1151                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1152
1153                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1154                                 if (ads_closest_dc(ads)) {
1155                                         char *sitename = sitename_fetch(ads->config.realm);
1156
1157                                         /* We're going to use this KDC for this realm/domain.
1158                                            If we are using sites, then force the krb5 libs
1159                                            to use this KDC. */
1160
1161                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1162                                                                         domain->name,
1163                                                                         sitename,
1164                                                                         pss,
1165                                                                         name);
1166
1167                                         SAFE_FREE(sitename);
1168                                 } else {
1169                                         /* use an off site KDC */
1170                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1171                                                                         domain->name,
1172                                                                         NULL,
1173                                                                         pss,
1174                                                                         name);
1175                                 }
1176                                 winbindd_set_locator_kdc_envs(domain);
1177
1178                                 /* Ensure we contact this DC also. */
1179                                 saf_store( domain->name, name);
1180                                 saf_store( domain->alt_name, name);
1181                         }
1182
1183                         ads_destroy( &ads );
1184                         return True;
1185                 }
1186
1187                 ads_destroy( &ads );
1188                 return false;
1189         }
1190 #endif
1191
1192         status = nbt_getdc(winbind_messaging_context(), 10, pss, domain->name,
1193                            &domain->sid, nt_version, mem_ctx, &nt_version,
1194                            &dc_name, NULL);
1195         if (NT_STATUS_IS_OK(status)) {
1196                 fstrcpy(name, dc_name);
1197                 namecache_store(name, 0x20, 1, &ip_list);
1198                 return True;
1199         }
1200
1201         /* try node status request */
1202
1203         if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1204                 namecache_store(name, 0x20, 1, &ip_list);
1205                 return True;
1206         }
1207         return False;
1208 }
1209
1210 /*******************************************************************
1211  Retrieve a list of IP addresses for domain controllers.
1212
1213  The array is sorted in the preferred connection order.
1214
1215  @param[in] mem_ctx talloc memory context to allocate from
1216  @param[in] domain domain to retrieve DCs for
1217  @param[out] dcs array of dcs that will be returned
1218  @param[out] num_dcs number of dcs returned in the dcs array
1219  @return always true
1220 *******************************************************************/
1221
1222 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1223                     struct dc_name_ip **dcs, int *num_dcs)
1224 {
1225         fstring dcname;
1226         struct  sockaddr_storage ss;
1227         struct  ip_service *ip_list = NULL;
1228         int     iplist_size = 0;
1229         int     i;
1230         bool    is_our_domain;
1231         enum security_types sec = (enum security_types)lp_security();
1232
1233         is_our_domain = strequal(domain->name, lp_workgroup());
1234
1235         /* If not our domain, get the preferred DC, by asking our primary DC */
1236         if ( !is_our_domain
1237                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1238                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1239                        num_dcs) )
1240         {
1241                 char addr[INET6_ADDRSTRLEN];
1242                 print_sockaddr(addr, sizeof(addr), &ss);
1243                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1244                            dcname, addr));
1245                 return True;
1246         }
1247
1248         if (sec == SEC_ADS) {
1249                 char *sitename = NULL;
1250
1251                 /* We need to make sure we know the local site before
1252                    doing any DNS queries, as this will restrict the
1253                    get_sorted_dc_list() call below to only fetching
1254                    DNS records for the correct site. */
1255
1256                 /* Find any DC to get the site record.
1257                    We deliberately don't care about the
1258                    return here. */
1259
1260                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1261
1262                 sitename = sitename_fetch(domain->alt_name);
1263                 if (sitename) {
1264
1265                         /* Do the site-specific AD dns lookup first. */
1266                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1267                                &iplist_size, True);
1268
1269                         /* Add ips to the DC array.  We don't look up the name
1270                            of the DC in this function, but we fill in the char*
1271                            of the ip now to make the failed connection cache
1272                            work */
1273                         for ( i=0; i<iplist_size; i++ ) {
1274                                 char addr[INET6_ADDRSTRLEN];
1275                                 print_sockaddr(addr, sizeof(addr),
1276                                                 &ip_list[i].ss);
1277                                 add_one_dc_unique(mem_ctx,
1278                                                 domain->name,
1279                                                 addr,
1280                                                 &ip_list[i].ss,
1281                                                 dcs,
1282                                                 num_dcs);
1283                         }
1284
1285                         SAFE_FREE(ip_list);
1286                         SAFE_FREE(sitename);
1287                         iplist_size = 0;
1288                 }
1289
1290                 /* Now we add DCs from the main AD DNS lookup. */
1291                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1292                         &iplist_size, True);
1293
1294                 for ( i=0; i<iplist_size; i++ ) {
1295                         char addr[INET6_ADDRSTRLEN];
1296                         print_sockaddr(addr, sizeof(addr),
1297                                         &ip_list[i].ss);
1298                         add_one_dc_unique(mem_ctx,
1299                                         domain->name,
1300                                         addr,
1301                                         &ip_list[i].ss,
1302                                         dcs,
1303                                         num_dcs);
1304                 }
1305
1306                 SAFE_FREE(ip_list);
1307                 iplist_size = 0;
1308         }
1309
1310         /* Try standard netbios queries if no ADS */
1311         if (*num_dcs == 0) {
1312                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1313                        False);
1314
1315                 for ( i=0; i<iplist_size; i++ ) {
1316                         char addr[INET6_ADDRSTRLEN];
1317                         print_sockaddr(addr, sizeof(addr),
1318                                         &ip_list[i].ss);
1319                         add_one_dc_unique(mem_ctx,
1320                                         domain->name,
1321                                         addr,
1322                                         &ip_list[i].ss,
1323                                         dcs,
1324                                         num_dcs);
1325                 }
1326
1327                 SAFE_FREE(ip_list);
1328                 iplist_size = 0;
1329         }
1330
1331         return True;
1332 }
1333
1334 /*******************************************************************
1335  Find and make a connection to a DC in the given domain.
1336
1337  @param[in] mem_ctx talloc memory context to allocate from
1338  @param[in] domain domain to find a dc in
1339  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1340  @param[out] pss DC Internet address and port
1341  @param[out] fd fd of the open socket connected to the newly found dc
1342  @return true when a DC connection is made, false otherwise
1343 *******************************************************************/
1344
1345 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1346                         struct winbindd_domain *domain,
1347                         fstring dcname, struct sockaddr_storage *pss, int *fd)
1348 {
1349         struct dc_name_ip *dcs = NULL;
1350         int num_dcs = 0;
1351
1352         const char **dcnames = NULL;
1353         int num_dcnames = 0;
1354
1355         struct sockaddr_storage *addrs = NULL;
1356         int num_addrs = 0;
1357
1358         int i;
1359         size_t fd_index;
1360
1361         NTSTATUS status;
1362
1363         *fd = -1;
1364
1365  again:
1366         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1367                 return False;
1368
1369         for (i=0; i<num_dcs; i++) {
1370
1371                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1372                                     &dcnames, &num_dcnames)) {
1373                         return False;
1374                 }
1375                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1376                                       &addrs, &num_addrs)) {
1377                         return False;
1378                 }
1379         }
1380
1381         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1382                 return False;
1383
1384         if ((addrs == NULL) || (dcnames == NULL))
1385                 return False;
1386
1387         status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1388                                      num_addrs, 0, 10, fd, &fd_index, NULL);
1389         if (!NT_STATUS_IS_OK(status)) {
1390                 for (i=0; i<num_dcs; i++) {
1391                         char ab[INET6_ADDRSTRLEN];
1392                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1393                         DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1394                                 "domain %s address %s. Error was %s\n",
1395                                    domain->name, ab, nt_errstr(status) ));
1396                         winbind_add_failed_connection_entry(domain,
1397                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1398                 }
1399                 return False;
1400         }
1401
1402         *pss = addrs[fd_index];
1403
1404         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1405                 /* Ok, we've got a name for the DC */
1406                 fstrcpy(dcname, dcnames[fd_index]);
1407                 return True;
1408         }
1409
1410         /* Try to figure out the name */
1411         if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1412                 return True;
1413         }
1414
1415         /* We can not continue without the DC's name */
1416         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1417                                     NT_STATUS_UNSUCCESSFUL);
1418
1419         /* Throw away all arrays as we're doing this again. */
1420         TALLOC_FREE(dcs);
1421         num_dcs = 0;
1422
1423         TALLOC_FREE(dcnames);
1424         num_dcnames = 0;
1425
1426         TALLOC_FREE(addrs);
1427         num_addrs = 0;
1428
1429         close(*fd);
1430         *fd = -1;
1431
1432         goto again;
1433 }
1434
1435 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1436 {
1437         return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1438                                           domain_name);
1439 }
1440
1441 static void store_current_dc_in_gencache(const char *domain_name,
1442                                          const char *dc_name,
1443                                          struct cli_state *cli)
1444 {
1445         char addr[INET6_ADDRSTRLEN];
1446         char *key = NULL;
1447         char *value = NULL;
1448
1449         if (cli == NULL) {
1450                 return;
1451         }
1452         if (cli->fd == -1) {
1453                 return;
1454         }
1455         get_peer_addr(cli->fd, addr, sizeof(addr));
1456
1457         key = current_dc_key(talloc_tos(), domain_name);
1458         if (key == NULL) {
1459                 goto done;
1460         }
1461
1462         value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1463         if (value == NULL) {
1464                 goto done;
1465         }
1466
1467         gencache_set(key, value, 0x7fffffff);
1468 done:
1469         TALLOC_FREE(value);
1470         TALLOC_FREE(key);
1471 }
1472
1473 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1474                                     const char *domain_name,
1475                                     char **p_dc_name, char **p_dc_ip)
1476 {
1477         char *key, *value, *p;
1478         bool ret = false;
1479         char *dc_name = NULL;
1480         char *dc_ip = NULL;
1481
1482         key = current_dc_key(talloc_tos(), domain_name);
1483         if (key == NULL) {
1484                 goto done;
1485         }
1486         if (!gencache_get(key, &value, NULL)) {
1487                 goto done;
1488         }
1489         p = strchr(value, ' ');
1490         if (p == NULL) {
1491                 goto done;
1492         }
1493         dc_ip = talloc_strndup(mem_ctx, value, p - value);
1494         if (dc_ip == NULL) {
1495                 goto done;
1496         }
1497         dc_name = talloc_strdup(mem_ctx, p+1);
1498         if (dc_name == NULL) {
1499                 goto done;
1500         }
1501
1502         if (p_dc_ip != NULL) {
1503                 *p_dc_ip = dc_ip;
1504                 dc_ip = NULL;
1505         }
1506         if (p_dc_name != NULL) {
1507                 *p_dc_name = dc_name;
1508                 dc_name = NULL;
1509         }
1510         ret = true;
1511 done:
1512         TALLOC_FREE(dc_name);
1513         TALLOC_FREE(dc_ip);
1514         TALLOC_FREE(key);
1515         return ret;
1516 }
1517
1518 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1519                                    struct winbindd_cm_conn *new_conn)
1520 {
1521         TALLOC_CTX *mem_ctx;
1522         NTSTATUS result;
1523         char *saf_servername = saf_fetch( domain->name );
1524         int retries;
1525
1526         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1527                 SAFE_FREE(saf_servername);
1528                 set_domain_offline(domain);
1529                 return NT_STATUS_NO_MEMORY;
1530         }
1531
1532         /* we have to check the server affinity cache here since 
1533            later we select a DC based on response time and not preference */
1534
1535         /* Check the negative connection cache
1536            before talking to it. It going down may have
1537            triggered the reconnection. */
1538
1539         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1540
1541                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1542                         saf_servername, domain->name ));
1543
1544                 /* convert an ip address to a name */
1545                 if (is_ipaddress( saf_servername ) ) {
1546                         fstring saf_name;
1547                         struct sockaddr_storage ss;
1548
1549                         if (!interpret_string_addr(&ss, saf_servername,
1550                                                 AI_NUMERICHOST)) {
1551                                 return NT_STATUS_UNSUCCESSFUL;
1552                         }
1553                         if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1554                                 fstrcpy( domain->dcname, saf_name );
1555                         } else {
1556                                 winbind_add_failed_connection_entry(
1557                                         domain, saf_servername,
1558                                         NT_STATUS_UNSUCCESSFUL);
1559                         }
1560                 } else {
1561                         fstrcpy( domain->dcname, saf_servername );
1562                 }
1563
1564                 SAFE_FREE( saf_servername );
1565         }
1566
1567         for (retries = 0; retries < 3; retries++) {
1568                 int fd = -1;
1569                 bool retry = False;
1570
1571                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1572
1573                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1574                         domain->dcname, domain->name ));
1575
1576                 if (*domain->dcname 
1577                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1578                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1579                 {
1580                         NTSTATUS status;
1581
1582                         status = smbsock_connect(&domain->dcaddr, 0,
1583                                                  NULL, -1, NULL, -1,
1584                                                  &fd, NULL, 10);
1585                         if (!NT_STATUS_IS_OK(status)) {
1586                                 fd = -1;
1587                         }
1588                 }
1589
1590                 if ((fd == -1) 
1591                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1592                 {
1593                         /* This is the one place where we will
1594                            set the global winbindd offline state
1595                            to true, if a "WINBINDD_OFFLINE" entry
1596                            is found in the winbindd cache. */
1597                         set_global_winbindd_state_offline();
1598                         break;
1599                 }
1600
1601                 new_conn->cli = NULL;
1602
1603                 result = cm_prepare_connection(domain, fd, domain->dcname,
1604                         &new_conn->cli, &retry);
1605
1606                 if (!retry)
1607                         break;
1608         }
1609
1610         if (NT_STATUS_IS_OK(result)) {
1611
1612                 winbindd_set_locator_kdc_envs(domain);
1613
1614                 if (domain->online == False) {
1615                         /* We're changing state from offline to online. */
1616                         set_global_winbindd_state_online();
1617                 }
1618                 set_domain_online(domain);
1619
1620                 /*
1621                  * Much as I hate global state, this seems to be the point
1622                  * where we can be certain that we have a proper connection to
1623                  * a DC. wbinfo --dc-info needs that information, store it in
1624                  * gencache with a looong timeout. This will need revisiting
1625                  * once we start to connect to multiple DCs, wbcDcInfo is
1626                  * already prepared for that.
1627                  */
1628                 store_current_dc_in_gencache(domain->name, domain->dcname,
1629                                              new_conn->cli);
1630         } else {
1631                 /* Ensure we setup the retry handler. */
1632                 set_domain_offline(domain);
1633         }
1634
1635         talloc_destroy(mem_ctx);
1636         return result;
1637 }
1638
1639 /* Close down all open pipes on a connection. */
1640
1641 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1642 {
1643         NTSTATUS result;
1644
1645         /* We're closing down a possibly dead
1646            connection. Don't have impossibly long (10s) timeouts. */
1647
1648         if (conn->cli) {
1649                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1650         }
1651
1652         if (conn->samr_pipe != NULL) {
1653                 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1654                         dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1655                                           talloc_tos(),
1656                                           &conn->sam_connect_handle,
1657                                           &result);
1658                 }
1659                 TALLOC_FREE(conn->samr_pipe);
1660                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1661                 if (conn->cli) {
1662                         cli_set_timeout(conn->cli, 500);
1663                 }
1664         }
1665
1666         if (conn->lsa_pipe != NULL) {
1667                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1668                         dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1669                                          talloc_tos(),
1670                                          &conn->lsa_policy,
1671                                          &result);
1672                 }
1673                 TALLOC_FREE(conn->lsa_pipe);
1674                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1675                 if (conn->cli) {
1676                         cli_set_timeout(conn->cli, 500);
1677                 }
1678         }
1679
1680         if (conn->lsa_pipe_tcp != NULL) {
1681                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1682                         dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1683                                          talloc_tos(),
1684                                          &conn->lsa_policy,
1685                                          &result);
1686                 }
1687                 TALLOC_FREE(conn->lsa_pipe_tcp);
1688                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1689                 if (conn->cli) {
1690                         cli_set_timeout(conn->cli, 500);
1691                 }
1692         }
1693
1694         if (conn->netlogon_pipe != NULL) {
1695                 TALLOC_FREE(conn->netlogon_pipe);
1696                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1697                 if (conn->cli) {
1698                         cli_set_timeout(conn->cli, 500);
1699                 }
1700         }
1701
1702         if (conn->cli) {
1703                 cli_shutdown(conn->cli);
1704         }
1705
1706         conn->cli = NULL;
1707 }
1708
1709 void close_conns_after_fork(void)
1710 {
1711         struct winbindd_domain *domain;
1712         struct winbindd_cli_state *cli_state;
1713
1714         for (domain = domain_list(); domain; domain = domain->next) {
1715                 struct cli_state *cli = domain->conn.cli;
1716
1717                 /*
1718                  * first close the low level SMB TCP connection
1719                  * so that we don't generate any SMBclose
1720                  * requests in invalidate_cm_connection()
1721                  */
1722                 if (cli && cli->fd != -1) {
1723                         close(domain->conn.cli->fd);
1724                         domain->conn.cli->fd = -1;
1725                 }
1726
1727                 invalidate_cm_connection(&domain->conn);
1728         }
1729
1730         for (cli_state = winbindd_client_list();
1731              cli_state != NULL;
1732              cli_state = cli_state->next) {
1733                 if (cli_state->sock >= 0) {
1734                         close(cli_state->sock);
1735                         cli_state->sock = -1;
1736                 }
1737         }
1738 }
1739
1740 static bool connection_ok(struct winbindd_domain *domain)
1741 {
1742         bool ok;
1743
1744         ok = cli_state_is_connected(domain->conn.cli);
1745         if (!ok) {
1746                 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1747                           domain->dcname, domain->name));
1748                 return False;
1749         }
1750
1751         if (domain->online == False) {
1752                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1753                 return False;
1754         }
1755
1756         return True;
1757 }
1758
1759 /* Initialize a new connection up to the RPC BIND.
1760    Bypass online status check so always does network calls. */
1761
1762 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1763 {
1764         NTSTATUS result;
1765
1766         /* Internal connections never use the network. */
1767         if (domain->internal) {
1768                 domain->initialized = True;
1769                 return NT_STATUS_OK;
1770         }
1771
1772         if (!winbindd_can_contact_domain(domain)) {
1773                 invalidate_cm_connection(&domain->conn);
1774                 domain->initialized = True;
1775                 return NT_STATUS_OK;
1776         }
1777
1778         if (connection_ok(domain)) {
1779                 if (!domain->initialized) {
1780                         set_dc_type_and_flags(domain);
1781                 }
1782                 return NT_STATUS_OK;
1783         }
1784
1785         invalidate_cm_connection(&domain->conn);
1786
1787         result = cm_open_connection(domain, &domain->conn);
1788
1789         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1790                 set_dc_type_and_flags(domain);
1791         }
1792
1793         return result;
1794 }
1795
1796 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1797 {
1798         if (domain->internal) {
1799                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1800         }
1801
1802         if (domain->initialized && !domain->online) {
1803                 /* We check for online status elsewhere. */
1804                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1805         }
1806
1807         return init_dc_connection_network(domain);
1808 }
1809
1810 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1811 {
1812         NTSTATUS status;
1813
1814         status = init_dc_connection(domain);
1815         if (!NT_STATUS_IS_OK(status)) {
1816                 return status;
1817         }
1818
1819         if (!domain->internal && domain->conn.cli == NULL) {
1820                 /* happens for trusted domains without inbound trust */
1821                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1822         }
1823
1824         return NT_STATUS_OK;
1825 }
1826
1827 /******************************************************************************
1828  Set the trust flags (direction and forest location) for a domain
1829 ******************************************************************************/
1830
1831 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1832 {
1833         struct winbindd_domain *our_domain;
1834         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1835         WERROR werr;
1836         struct netr_DomainTrustList trusts;
1837         int i;
1838         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1839                         NETR_TRUST_FLAG_OUTBOUND |
1840                         NETR_TRUST_FLAG_INBOUND);
1841         struct rpc_pipe_client *cli;
1842         TALLOC_CTX *mem_ctx = NULL;
1843         struct dcerpc_binding_handle *b;
1844
1845         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1846
1847         /* Our primary domain doesn't need to worry about trust flags.
1848            Force it to go through the network setup */
1849         if ( domain->primary ) {                
1850                 return False;           
1851         }
1852
1853         our_domain = find_our_domain();
1854
1855         if ( !connection_ok(our_domain) ) {
1856                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1857                 return False;
1858         }
1859
1860         /* This won't work unless our domain is AD */
1861
1862         if ( !our_domain->active_directory ) {
1863                 return False;
1864         }
1865
1866         /* Use DsEnumerateDomainTrusts to get us the trust direction
1867            and type */
1868
1869         result = cm_connect_netlogon(our_domain, &cli);
1870
1871         if (!NT_STATUS_IS_OK(result)) {
1872                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1873                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1874                           domain->name, nt_errstr(result)));
1875                 return False;
1876         }
1877
1878         b = cli->binding_handle;
1879
1880         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1881                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1882                 return False;
1883         }       
1884
1885         result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1886                                                       cli->desthost,
1887                                                       flags,
1888                                                       &trusts,
1889                                                       &werr);
1890         if (!NT_STATUS_IS_OK(result)) {
1891                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1892                         "failed to query trusted domain list: %s\n",
1893                         nt_errstr(result)));
1894                 talloc_destroy(mem_ctx);
1895                 return false;
1896         }
1897         if (!W_ERROR_IS_OK(werr)) {
1898                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1899                         "failed to query trusted domain list: %s\n",
1900                         win_errstr(werr)));
1901                 talloc_destroy(mem_ctx);
1902                 return false;
1903         }
1904
1905         /* Now find the domain name and get the flags */
1906
1907         for ( i=0; i<trusts.count; i++ ) {
1908                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1909                         domain->domain_flags          = trusts.array[i].trust_flags;
1910                         domain->domain_type           = trusts.array[i].trust_type;
1911                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1912
1913                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1914                                 domain->active_directory = True;
1915
1916                         /* This flag is only set if the domain is *our* 
1917                            primary domain and the primary domain is in
1918                            native mode */
1919
1920                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1921
1922                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1923                                   "native mode.\n", domain->name, 
1924                                   domain->native_mode ? "" : "NOT "));
1925
1926                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1927                                  "running active directory.\n", domain->name, 
1928                                  domain->active_directory ? "" : "NOT "));
1929
1930                         domain->can_do_ncacn_ip_tcp = domain->active_directory;
1931                         domain->can_do_validation6 = domain->active_directory;
1932
1933                         domain->initialized = True;
1934
1935                         break;
1936                 }               
1937         }
1938
1939         talloc_destroy( mem_ctx );
1940
1941         return domain->initialized;     
1942 }
1943
1944 /******************************************************************************
1945  We can 'sense' certain things about the DC by it's replies to certain
1946  questions.
1947
1948  This tells us if this particular remote server is Active Directory, and if it
1949  is native mode.
1950 ******************************************************************************/
1951
1952 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1953 {
1954         NTSTATUS status, result;
1955         WERROR werr;
1956         TALLOC_CTX              *mem_ctx = NULL;
1957         struct rpc_pipe_client  *cli = NULL;
1958         struct policy_handle pol;
1959         union dssetup_DsRoleInfo info;
1960         union lsa_PolicyInformation *lsa_info = NULL;
1961
1962         if (!connection_ok(domain)) {
1963                 return;
1964         }
1965
1966         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1967                               domain->name);
1968         if (!mem_ctx) {
1969                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1970                 return;
1971         }
1972
1973         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1974
1975         status = cli_rpc_pipe_open_noauth(domain->conn.cli,
1976                                           &ndr_table_dssetup.syntax_id,
1977                                           &cli);
1978
1979         if (!NT_STATUS_IS_OK(status)) {
1980                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1981                           "PI_DSSETUP on domain %s: (%s)\n",
1982                           domain->name, nt_errstr(status)));
1983
1984                 /* if this is just a non-AD domain we need to continue
1985                  * identifying so that we can in the end return with
1986                  * domain->initialized = True - gd */
1987
1988                 goto no_dssetup;
1989         }
1990
1991         status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
1992                                                                   DS_ROLE_BASIC_INFORMATION,
1993                                                                   &info,
1994                                                                   &werr);
1995         TALLOC_FREE(cli);
1996
1997         if (NT_STATUS_IS_OK(status)) {
1998                 result = werror_to_ntstatus(werr);
1999         }
2000         if (!NT_STATUS_IS_OK(status)) {
2001                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2002                           "on domain %s failed: (%s)\n",
2003                           domain->name, nt_errstr(status)));
2004
2005                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2006                  * every opcode on the DSSETUP pipe, continue with
2007                  * no_dssetup mode here as well to get domain->initialized
2008                  * set - gd */
2009
2010                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2011                         goto no_dssetup;
2012                 }
2013
2014                 TALLOC_FREE(mem_ctx);
2015                 return;
2016         }
2017
2018         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2019             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2020                 domain->native_mode = True;
2021         } else {
2022                 domain->native_mode = False;
2023         }
2024
2025 no_dssetup:
2026         status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2027                                           &ndr_table_lsarpc.syntax_id, &cli);
2028
2029         if (!NT_STATUS_IS_OK(status)) {
2030                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2031                           "PI_LSARPC on domain %s: (%s)\n",
2032                           domain->name, nt_errstr(status)));
2033                 TALLOC_FREE(cli);
2034                 TALLOC_FREE(mem_ctx);
2035                 return;
2036         }
2037
2038         status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2039                                          SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2040
2041         if (NT_STATUS_IS_OK(status)) {
2042                 /* This particular query is exactly what Win2k clients use 
2043                    to determine that the DC is active directory */
2044                 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2045                                                      &pol,
2046                                                      LSA_POLICY_INFO_DNS,
2047                                                      &lsa_info,
2048                                                      &result);
2049         }
2050
2051         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2052                 domain->active_directory = True;
2053
2054                 if (lsa_info->dns.name.string) {
2055                         fstrcpy(domain->name, lsa_info->dns.name.string);
2056                 }
2057
2058                 if (lsa_info->dns.dns_domain.string) {
2059                         fstrcpy(domain->alt_name,
2060                                 lsa_info->dns.dns_domain.string);
2061                 }
2062
2063                 /* See if we can set some domain trust flags about
2064                    ourself */
2065
2066                 if (lsa_info->dns.dns_forest.string) {
2067                         fstrcpy(domain->forest_name,
2068                                 lsa_info->dns.dns_forest.string);
2069
2070                         if (strequal(domain->forest_name, domain->alt_name)) {
2071                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2072                         }
2073                 }
2074
2075                 if (lsa_info->dns.sid) {
2076                         sid_copy(&domain->sid, lsa_info->dns.sid);
2077                 }
2078         } else {
2079                 domain->active_directory = False;
2080
2081                 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2082                                                 SEC_FLAG_MAXIMUM_ALLOWED,
2083                                                 &pol);
2084
2085                 if (!NT_STATUS_IS_OK(status)) {
2086                         goto done;
2087                 }
2088
2089                 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2090                                                     &pol,
2091                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2092                                                     &lsa_info,
2093                                                     &result);
2094                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2095
2096                         if (lsa_info->account_domain.name.string) {
2097                                 fstrcpy(domain->name,
2098                                         lsa_info->account_domain.name.string);
2099                         }
2100
2101                         if (lsa_info->account_domain.sid) {
2102                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2103                         }
2104                 }
2105         }
2106 done:
2107
2108         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2109                   domain->name, domain->native_mode ? "" : "NOT "));
2110
2111         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2112                   domain->name, domain->active_directory ? "" : "NOT "));
2113
2114         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2115         domain->can_do_validation6 = domain->active_directory;
2116
2117         TALLOC_FREE(cli);
2118
2119         TALLOC_FREE(mem_ctx);
2120
2121         domain->initialized = True;
2122 }
2123
2124 /**********************************************************************
2125  Set the domain_flags (trust attributes, domain operating modes, etc... 
2126 ***********************************************************************/
2127
2128 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2129 {
2130         /* we always have to contact our primary domain */
2131
2132         if ( domain->primary ) {
2133                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2134                           "primary domain\n"));
2135                 set_dc_type_and_flags_connect( domain );
2136                 return;         
2137         }
2138
2139         /* Use our DC to get the information if possible */
2140
2141         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2142                 /* Otherwise, fallback to contacting the 
2143                    domain directly */
2144                 set_dc_type_and_flags_connect( domain );
2145         }
2146
2147         return;
2148 }
2149
2150
2151
2152 /**********************************************************************
2153 ***********************************************************************/
2154
2155 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2156                                    struct netlogon_creds_CredentialState **ppdc)
2157 {
2158         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2159         struct rpc_pipe_client *netlogon_pipe;
2160
2161         if (lp_client_schannel() == False) {
2162                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2163         }
2164
2165         result = cm_connect_netlogon(domain, &netlogon_pipe);
2166         if (!NT_STATUS_IS_OK(result)) {
2167                 return result;
2168         }
2169
2170         /* Return a pointer to the struct netlogon_creds_CredentialState from the
2171            netlogon pipe. */
2172
2173         if (!domain->conn.netlogon_pipe->dc) {
2174                 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2175         }
2176
2177         *ppdc = domain->conn.netlogon_pipe->dc;
2178         return NT_STATUS_OK;
2179 }
2180
2181 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2182                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2183 {
2184         struct winbindd_cm_conn *conn;
2185         NTSTATUS status, result;
2186         struct netlogon_creds_CredentialState *p_creds;
2187         char *machine_password = NULL;
2188         char *machine_account = NULL;
2189         char *domain_name = NULL;
2190
2191         if (sid_check_is_domain(&domain->sid)) {
2192                 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2193         }
2194
2195         status = init_dc_connection_rpc(domain);
2196         if (!NT_STATUS_IS_OK(status)) {
2197                 return status;
2198         }
2199
2200         conn = &domain->conn;
2201
2202         if (rpccli_is_connected(conn->samr_pipe)) {
2203                 goto done;
2204         }
2205
2206         TALLOC_FREE(conn->samr_pipe);
2207
2208         /*
2209          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2210          * sign and sealed pipe using the machine account password by
2211          * preference. If we can't - try schannel, if that fails, try
2212          * anonymous.
2213          */
2214
2215         if ((conn->cli->user_name[0] == '\0') ||
2216             (conn->cli->domain[0] == '\0') || 
2217             (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2218         {
2219                 status = get_trust_creds(domain, &machine_password,
2220                                          &machine_account, NULL);
2221                 if (!NT_STATUS_IS_OK(status)) {
2222                         DEBUG(10, ("cm_connect_sam: No no user available for "
2223                                    "domain %s, trying schannel\n", conn->cli->domain));
2224                         goto schannel;
2225                 }
2226                 domain_name = domain->name;
2227         } else {
2228                 machine_password = SMB_STRDUP(conn->cli->password);
2229                 machine_account = SMB_STRDUP(conn->cli->user_name);
2230                 domain_name = conn->cli->domain;
2231         }
2232
2233         if (!machine_password || !machine_account) {
2234                 status = NT_STATUS_NO_MEMORY;
2235                 goto done;
2236         }
2237
2238         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2239            authenticated SAMR pipe with sign & seal. */
2240         status = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2241                                                   &ndr_table_samr.syntax_id,
2242                                                   NCACN_NP,
2243                                                   DCERPC_AUTH_LEVEL_PRIVACY,
2244                                                   domain_name,
2245                                                   machine_account,
2246                                                   machine_password,
2247                                                   &conn->samr_pipe);
2248
2249         if (!NT_STATUS_IS_OK(status)) {
2250                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2251                           "pipe for domain %s using NTLMSSP "
2252                           "authenticated pipe: user %s\\%s. Error was "
2253                           "%s\n", domain->name, domain_name,
2254                           machine_account, nt_errstr(status)));
2255                 goto schannel;
2256         }
2257
2258         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2259                   "domain %s using NTLMSSP authenticated "
2260                   "pipe: user %s\\%s\n", domain->name,
2261                   domain_name, machine_account));
2262
2263         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2264                                       conn->samr_pipe->desthost,
2265                                       SEC_FLAG_MAXIMUM_ALLOWED,
2266                                       &conn->sam_connect_handle,
2267                                       &result);
2268         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2269                 goto open_domain;
2270         }
2271         if (NT_STATUS_IS_OK(status)) {
2272                 status = result;
2273         }
2274
2275         DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2276                   "failed for domain %s, error was %s. Trying schannel\n",
2277                   domain->name, nt_errstr(status) ));
2278         TALLOC_FREE(conn->samr_pipe);
2279
2280  schannel:
2281
2282         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2283
2284         status = cm_get_schannel_creds(domain, &p_creds);
2285         if (!NT_STATUS_IS_OK(status)) {
2286                 /* If this call fails - conn->cli can now be NULL ! */
2287                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2288                            "for domain %s (error %s), trying anon\n",
2289                         domain->name,
2290                         nt_errstr(status) ));
2291                 goto anonymous;
2292         }
2293         status = cli_rpc_pipe_open_schannel_with_key
2294                 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2295                  DCERPC_AUTH_LEVEL_PRIVACY,
2296                  domain->name, &p_creds, &conn->samr_pipe);
2297
2298         if (!NT_STATUS_IS_OK(status)) {
2299                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2300                           "domain %s using schannel. Error was %s\n",
2301                           domain->name, nt_errstr(status) ));
2302                 goto anonymous;
2303         }
2304         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2305                   "schannel.\n", domain->name ));
2306
2307         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2308                                       conn->samr_pipe->desthost,
2309                                       SEC_FLAG_MAXIMUM_ALLOWED,
2310                                       &conn->sam_connect_handle,
2311                                       &result);
2312         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2313                 goto open_domain;
2314         }
2315         if (NT_STATUS_IS_OK(status)) {
2316                 status = result;
2317         }
2318         DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2319                   "for domain %s, error was %s. Trying anonymous\n",
2320                   domain->name, nt_errstr(status) ));
2321         TALLOC_FREE(conn->samr_pipe);
2322
2323  anonymous:
2324
2325         /* Finally fall back to anonymous. */
2326         status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2327                                           &conn->samr_pipe);
2328
2329         if (!NT_STATUS_IS_OK(status)) {
2330                 goto done;
2331         }
2332
2333         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2334                                       conn->samr_pipe->desthost,
2335                                       SEC_FLAG_MAXIMUM_ALLOWED,
2336                                       &conn->sam_connect_handle,
2337                                       &result);
2338         if (!NT_STATUS_IS_OK(status)) {
2339                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2340                           "for domain %s Error was %s\n",
2341                           domain->name, nt_errstr(status) ));
2342                 goto done;
2343         }
2344         if (!NT_STATUS_IS_OK(result)) {
2345                 status = result;
2346                 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2347                           "for domain %s Error was %s\n",
2348                           domain->name, nt_errstr(result)));
2349                 goto done;
2350         }
2351
2352  open_domain:
2353         status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2354                                         mem_ctx,
2355                                         &conn->sam_connect_handle,
2356                                         SEC_FLAG_MAXIMUM_ALLOWED,
2357                                         &domain->sid,
2358                                         &conn->sam_domain_handle,
2359                                         &result);
2360         if (!NT_STATUS_IS_OK(status)) {
2361                 goto done;
2362         }
2363
2364         status = result;
2365  done:
2366
2367         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2368                 /*
2369                  * if we got access denied, we might just have no access rights
2370                  * to talk to the remote samr server server (e.g. when we are a
2371                  * PDC and we are connecting a w2k8 pdc via an interdomain
2372                  * trust). In that case do not invalidate the whole connection
2373                  * stack
2374                  */
2375                 TALLOC_FREE(conn->samr_pipe);
2376                 ZERO_STRUCT(conn->sam_domain_handle);
2377                 return status;
2378         } else if (!NT_STATUS_IS_OK(status)) {
2379                 invalidate_cm_connection(conn);
2380                 return status;
2381         }
2382
2383         *cli = conn->samr_pipe;
2384         *sam_handle = conn->sam_domain_handle;
2385         SAFE_FREE(machine_password);
2386         SAFE_FREE(machine_account);
2387         return status;
2388 }
2389
2390 /**********************************************************************
2391  open an schanneld ncacn_ip_tcp connection to LSA
2392 ***********************************************************************/
2393
2394 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2395                             TALLOC_CTX *mem_ctx,
2396                             struct rpc_pipe_client **cli)
2397 {
2398         struct winbindd_cm_conn *conn;
2399         struct netlogon_creds_CredentialState *creds;
2400         NTSTATUS status;
2401
2402         DEBUG(10,("cm_connect_lsa_tcp\n"));
2403
2404         status = init_dc_connection_rpc(domain);
2405         if (!NT_STATUS_IS_OK(status)) {
2406                 return status;
2407         }
2408
2409         conn = &domain->conn;
2410
2411         if (conn->lsa_pipe_tcp &&
2412             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2413             conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2414             rpccli_is_connected(conn->lsa_pipe_tcp)) {
2415                 goto done;
2416         }
2417
2418         TALLOC_FREE(conn->lsa_pipe_tcp);
2419
2420         status = cm_get_schannel_creds(domain, &creds);
2421         if (!NT_STATUS_IS_OK(status)) {
2422                 goto done;
2423         }
2424
2425         status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2426                                                      &ndr_table_lsarpc.syntax_id,
2427                                                      NCACN_IP_TCP,
2428                                                      DCERPC_AUTH_LEVEL_PRIVACY,
2429                                                      domain->name,
2430                                                      &creds,
2431                                                      &conn->lsa_pipe_tcp);
2432         if (!NT_STATUS_IS_OK(status)) {
2433                 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2434                         nt_errstr(status)));
2435                 goto done;
2436         }
2437
2438  done:
2439         if (!NT_STATUS_IS_OK(status)) {
2440                 TALLOC_FREE(conn->lsa_pipe_tcp);
2441                 return status;
2442         }
2443
2444         *cli = conn->lsa_pipe_tcp;
2445
2446         return status;
2447 }
2448
2449 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2450                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2451 {
2452         struct winbindd_cm_conn *conn;
2453         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2454         struct netlogon_creds_CredentialState *p_creds;
2455
2456         result = init_dc_connection_rpc(domain);
2457         if (!NT_STATUS_IS_OK(result))
2458                 return result;
2459
2460         conn = &domain->conn;
2461
2462         if (rpccli_is_connected(conn->lsa_pipe)) {
2463                 goto done;
2464         }
2465
2466         TALLOC_FREE(conn->lsa_pipe);
2467
2468         if ((conn->cli->user_name[0] == '\0') ||
2469             (conn->cli->domain[0] == '\0') || 
2470             (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2471                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2472                            "domain %s, trying schannel\n", conn->cli->domain));
2473                 goto schannel;
2474         }
2475
2476         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2477          * authenticated LSA pipe with sign & seal. */
2478         result = cli_rpc_pipe_open_spnego_ntlmssp
2479                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2480                  DCERPC_AUTH_LEVEL_PRIVACY,
2481                  conn->cli->domain, conn->cli->user_name, conn->cli->password,
2482                  &conn->lsa_pipe);
2483
2484         if (!NT_STATUS_IS_OK(result)) {
2485                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2486                           "domain %s using NTLMSSP authenticated pipe: user "
2487                           "%s\\%s. Error was %s. Trying schannel.\n",
2488                           domain->name, conn->cli->domain,
2489                           conn->cli->user_name, nt_errstr(result)));
2490                 goto schannel;
2491         }
2492
2493         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2494                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2495                   domain->name, conn->cli->domain, conn->cli->user_name ));
2496
2497         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2498                                         SEC_FLAG_MAXIMUM_ALLOWED,
2499                                         &conn->lsa_policy);
2500         if (NT_STATUS_IS_OK(result)) {
2501                 goto done;
2502         }
2503
2504         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2505                   "schannel\n"));
2506
2507         TALLOC_FREE(conn->lsa_pipe);
2508
2509  schannel:
2510
2511         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2512
2513         result = cm_get_schannel_creds(domain, &p_creds);
2514         if (!NT_STATUS_IS_OK(result)) {
2515                 /* If this call fails - conn->cli can now be NULL ! */
2516                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2517                            "for domain %s (error %s), trying anon\n",
2518                         domain->name,
2519                         nt_errstr(result) ));
2520                 goto anonymous;
2521         }
2522         result = cli_rpc_pipe_open_schannel_with_key
2523                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2524                  DCERPC_AUTH_LEVEL_PRIVACY,
2525                  domain->name, &p_creds, &conn->lsa_pipe);
2526
2527         if (!NT_STATUS_IS_OK(result)) {
2528                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2529                           "domain %s using schannel. Error was %s\n",
2530                           domain->name, nt_errstr(result) ));
2531                 goto anonymous;
2532         }
2533         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2534                   "schannel.\n", domain->name ));
2535
2536         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2537                                         SEC_FLAG_MAXIMUM_ALLOWED,
2538                                         &conn->lsa_policy);
2539         if (NT_STATUS_IS_OK(result)) {
2540                 goto done;
2541         }
2542
2543         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2544                   "anonymous\n"));
2545
2546         TALLOC_FREE(conn->lsa_pipe);
2547
2548  anonymous:
2549
2550         result = cli_rpc_pipe_open_noauth(conn->cli,
2551                                           &ndr_table_lsarpc.syntax_id,
2552                                           &conn->lsa_pipe);
2553         if (!NT_STATUS_IS_OK(result)) {
2554                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2555                 goto done;
2556         }
2557
2558         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2559                                         SEC_FLAG_MAXIMUM_ALLOWED,
2560                                         &conn->lsa_policy);
2561  done:
2562         if (!NT_STATUS_IS_OK(result)) {
2563                 invalidate_cm_connection(conn);
2564                 return result;
2565         }
2566
2567         *cli = conn->lsa_pipe;
2568         *lsa_policy = conn->lsa_policy;
2569         return result;
2570 }
2571
2572 /****************************************************************************
2573  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2574  session key stored in conn->netlogon_pipe->dc->sess_key.
2575 ****************************************************************************/
2576
2577 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2578                              struct rpc_pipe_client **cli)
2579 {
2580         struct winbindd_cm_conn *conn;
2581         NTSTATUS result;
2582
2583         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2584         uint8  mach_pwd[16];
2585         enum netr_SchannelType sec_chan_type;
2586         const char *account_name;
2587         struct rpc_pipe_client *netlogon_pipe = NULL;
2588
2589         *cli = NULL;
2590
2591         result = init_dc_connection_rpc(domain);
2592         if (!NT_STATUS_IS_OK(result)) {
2593                 return result;
2594         }
2595
2596         conn = &domain->conn;
2597
2598         if (rpccli_is_connected(conn->netlogon_pipe)) {
2599                 *cli = conn->netlogon_pipe;
2600                 return NT_STATUS_OK;
2601         }
2602
2603         TALLOC_FREE(conn->netlogon_pipe);
2604
2605         result = cli_rpc_pipe_open_noauth(conn->cli,
2606                                           &ndr_table_netlogon.syntax_id,
2607                                           &netlogon_pipe);
2608         if (!NT_STATUS_IS_OK(result)) {
2609                 return result;
2610         }
2611
2612         if ((!IS_DC) && (!domain->primary)) {
2613                 /* Clear the schannel request bit and drop down */
2614                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2615                 goto no_schannel;
2616         }
2617
2618         if (lp_client_schannel() != False) {
2619                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2620         }
2621
2622         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2623                                &sec_chan_type))
2624         {
2625                 TALLOC_FREE(netlogon_pipe);
2626                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2627         }
2628
2629         result = rpccli_netlogon_setup_creds(
2630                  netlogon_pipe,
2631                  domain->dcname, /* server name. */
2632                  domain->name,   /* domain name */
2633                  global_myname(), /* client name */
2634                  account_name,   /* machine account */
2635                  mach_pwd,       /* machine password */
2636                  sec_chan_type,  /* from get_trust_pw */
2637                  &neg_flags);
2638
2639         if (!NT_STATUS_IS_OK(result)) {
2640                 TALLOC_FREE(netlogon_pipe);
2641                 return result;
2642         }
2643
2644         if ((lp_client_schannel() == True) &&
2645                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2646                 DEBUG(3, ("Server did not offer schannel\n"));
2647                 TALLOC_FREE(netlogon_pipe);
2648                 return NT_STATUS_ACCESS_DENIED;
2649         }
2650
2651  no_schannel:
2652         if ((lp_client_schannel() == False) ||
2653                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2654                 /*
2655                  * NetSamLogonEx only works for schannel
2656                  */
2657                 domain->can_do_samlogon_ex = False;
2658
2659                 /* We're done - just keep the existing connection to NETLOGON
2660                  * open */
2661                 conn->netlogon_pipe = netlogon_pipe;
2662                 *cli = conn->netlogon_pipe;
2663                 return NT_STATUS_OK;
2664         }
2665
2666         /* Using the credentials from the first pipe, open a signed and sealed
2667            second netlogon pipe. The session key is stored in the schannel
2668            part of the new pipe auth struct.
2669         */
2670
2671         result = cli_rpc_pipe_open_schannel_with_key(
2672                 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2673                 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2674                 &conn->netlogon_pipe);
2675
2676         /* We can now close the initial netlogon pipe. */
2677         TALLOC_FREE(netlogon_pipe);
2678
2679         if (!NT_STATUS_IS_OK(result)) {
2680                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2681                           "was %s\n", nt_errstr(result)));
2682
2683                 invalidate_cm_connection(conn);
2684                 return result;
2685         }
2686
2687         /*
2688          * Always try netr_LogonSamLogonEx. We will fall back for NT4
2689          * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2690          * supported). We used to only try SamLogonEx for AD, but
2691          * Samba DCs can also do it. And because we don't distinguish
2692          * between Samba and NT4, always try it once.
2693          */
2694         domain->can_do_samlogon_ex = true;
2695
2696         *cli = conn->netlogon_pipe;
2697         return NT_STATUS_OK;
2698 }
2699
2700 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2701                             void *private_data,
2702                             uint32_t msg_type,
2703                             struct server_id server_id,
2704                             DATA_BLOB *data)
2705 {
2706         struct winbindd_domain *domain;
2707         char *freeit = NULL;
2708         char *addr;
2709
2710         if ((data == NULL)
2711             || (data->data == NULL)
2712             || (data->length == 0)
2713             || (data->data[data->length-1] != '\0')) {
2714                 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2715                           "string\n"));
2716                 return;
2717         }
2718
2719         addr = (char *)data->data;
2720         DEBUG(10, ("IP %s dropped\n", addr));
2721
2722         if (!is_ipaddress(addr)) {
2723                 char *slash;
2724                 /*
2725                  * Some code sends us ip addresses with the /netmask
2726                  * suffix
2727                  */
2728                 slash = strchr(addr, '/');
2729                 if (slash == NULL) {
2730                         DEBUG(1, ("invalid msg_ip_dropped message: %s",
2731                                   addr));
2732                         return;
2733                 }
2734                 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2735                 if (freeit == NULL) {
2736                         DEBUG(1, ("talloc failed\n"));
2737                         return;
2738                 }
2739                 addr = freeit;
2740                 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2741         }
2742
2743         for (domain = domain_list(); domain != NULL; domain = domain->next) {
2744                 char sockaddr[INET6_ADDRSTRLEN];
2745                 if (domain->conn.cli == NULL) {
2746                         continue;
2747                 }
2748                 if (domain->conn.cli->fd == -1) {
2749                         continue;
2750                 }
2751                 client_socket_addr(domain->conn.cli->fd, sockaddr,
2752                                    sizeof(sockaddr));
2753                 if (strequal(sockaddr, addr)) {
2754                         close(domain->conn.cli->fd);
2755                         domain->conn.cli->fd = -1;
2756                 }
2757         }
2758         TALLOC_FREE(freeit);
2759 }