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