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