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