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