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