ace0160a1cf80bbbbdbe772d6952357606a544d2
[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, *value, *p;
1569         bool ret = false;
1570         char *dc_name = NULL;
1571         char *dc_ip = NULL;
1572
1573         key = current_dc_key(talloc_tos(), domain_name);
1574         if (key == NULL) {
1575                 goto done;
1576         }
1577         if (!gencache_get(key, mem_ctx, &value, NULL)) {
1578                 goto done;
1579         }
1580         p = strchr(value, ' ');
1581         if (p == NULL) {
1582                 goto done;
1583         }
1584         dc_ip = talloc_strndup(mem_ctx, value, p - value);
1585         if (dc_ip == NULL) {
1586                 goto done;
1587         }
1588         dc_name = talloc_strdup(mem_ctx, p+1);
1589         if (dc_name == NULL) {
1590                 goto done;
1591         }
1592
1593         if (p_dc_ip != NULL) {
1594                 *p_dc_ip = dc_ip;
1595                 dc_ip = NULL;
1596         }
1597         if (p_dc_name != NULL) {
1598                 *p_dc_name = dc_name;
1599                 dc_name = NULL;
1600         }
1601         ret = true;
1602 done:
1603         TALLOC_FREE(dc_name);
1604         TALLOC_FREE(dc_ip);
1605         TALLOC_FREE(key);
1606         TALLOC_FREE(value);
1607         return ret;
1608 }
1609
1610 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1611                                    struct winbindd_cm_conn *new_conn)
1612 {
1613         TALLOC_CTX *mem_ctx;
1614         NTSTATUS result;
1615         char *saf_servername;
1616         int retries;
1617
1618         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1619                 set_domain_offline(domain);
1620                 return NT_STATUS_NO_MEMORY;
1621         }
1622
1623         saf_servername = saf_fetch(mem_ctx, domain->name );
1624
1625         /* we have to check the server affinity cache here since 
1626            later we select a DC based on response time and not preference */
1627
1628         /* Check the negative connection cache
1629            before talking to it. It going down may have
1630            triggered the reconnection. */
1631
1632         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1633
1634                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1635                         saf_servername, domain->name ));
1636
1637                 /* convert an ip address to a name */
1638                 if (is_ipaddress( saf_servername ) ) {
1639                         char *dcname = NULL;
1640                         struct sockaddr_storage ss;
1641
1642                         if (!interpret_string_addr(&ss, saf_servername,
1643                                                 AI_NUMERICHOST)) {
1644                                 TALLOC_FREE(mem_ctx);
1645                                 return NT_STATUS_UNSUCCESSFUL;
1646                         }
1647                         if (dcip_to_name(mem_ctx, domain, &ss, &dcname)) {
1648                                 domain->dcname = talloc_strdup(domain,
1649                                                                dcname);
1650                                 if (domain->dcname == NULL) {
1651                                         TALLOC_FREE(mem_ctx);
1652                                         return NT_STATUS_NO_MEMORY;
1653                                 }
1654                         } else {
1655                                 winbind_add_failed_connection_entry(
1656                                         domain, saf_servername,
1657                                         NT_STATUS_UNSUCCESSFUL);
1658                         }
1659                 } else {
1660                         domain->dcname = talloc_strdup(domain, saf_servername);
1661                         if (domain->dcname == NULL) {
1662                                 TALLOC_FREE(mem_ctx);
1663                                 return NT_STATUS_NO_MEMORY;
1664                         }
1665                 }
1666         }
1667
1668         for (retries = 0; retries < 3; retries++) {
1669                 int fd = -1;
1670                 bool retry = False;
1671                 char *dcname = NULL;
1672
1673                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1674
1675                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1676                         domain->dcname ? domain->dcname : "", domain->name ));
1677
1678                 if (domain->dcname != NULL
1679                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1680                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1681                 {
1682                         NTSTATUS status;
1683
1684                         status = smbsock_connect(&domain->dcaddr, 0,
1685                                                  NULL, -1, NULL, -1,
1686                                                  &fd, NULL, 10);
1687                         if (!NT_STATUS_IS_OK(status)) {
1688                                 fd = -1;
1689                         }
1690                 }
1691
1692                 if ((fd == -1) &&
1693                     !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd))
1694                 {
1695                         /* This is the one place where we will
1696                            set the global winbindd offline state
1697                            to true, if a "WINBINDD_OFFLINE" entry
1698                            is found in the winbindd cache. */
1699                         set_global_winbindd_state_offline();
1700                         break;
1701                 }
1702                 if (dcname != NULL) {
1703                         talloc_free(domain->dcname);
1704
1705                         domain->dcname = talloc_move(domain, &dcname);
1706                         if (domain->dcname == NULL) {
1707                                 result = NT_STATUS_NO_MEMORY;
1708                                 break;
1709                         }
1710                 }
1711
1712                 new_conn->cli = NULL;
1713
1714                 result = cm_prepare_connection(domain, fd, domain->dcname,
1715                         &new_conn->cli, &retry);
1716                 if (!NT_STATUS_IS_OK(result)) {
1717                         /* Don't leak the smb connection socket */
1718                         close(fd);
1719                 }
1720
1721                 if (!retry)
1722                         break;
1723         }
1724
1725         if (NT_STATUS_IS_OK(result)) {
1726
1727                 winbindd_set_locator_kdc_envs(domain);
1728
1729                 if (domain->online == False) {
1730                         /* We're changing state from offline to online. */
1731                         set_global_winbindd_state_online();
1732                 }
1733                 set_domain_online(domain);
1734
1735                 /*
1736                  * Much as I hate global state, this seems to be the point
1737                  * where we can be certain that we have a proper connection to
1738                  * a DC. wbinfo --dc-info needs that information, store it in
1739                  * gencache with a looong timeout. This will need revisiting
1740                  * once we start to connect to multiple DCs, wbcDcInfo is
1741                  * already prepared for that.
1742                  */
1743                 store_current_dc_in_gencache(domain->name, domain->dcname,
1744                                              new_conn->cli);
1745         } else {
1746                 /* Ensure we setup the retry handler. */
1747                 set_domain_offline(domain);
1748         }
1749
1750         talloc_destroy(mem_ctx);
1751         return result;
1752 }
1753
1754 /* Close down all open pipes on a connection. */
1755
1756 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1757 {
1758         NTSTATUS result;
1759
1760         /* We're closing down a possibly dead
1761            connection. Don't have impossibly long (10s) timeouts. */
1762
1763         if (conn->cli) {
1764                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1765         }
1766
1767         if (conn->samr_pipe != NULL) {
1768                 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1769                         dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1770                                           talloc_tos(),
1771                                           &conn->sam_connect_handle,
1772                                           &result);
1773                 }
1774                 TALLOC_FREE(conn->samr_pipe);
1775                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1776                 if (conn->cli) {
1777                         cli_set_timeout(conn->cli, 500);
1778                 }
1779         }
1780
1781         if (conn->lsa_pipe != NULL) {
1782                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1783                         dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1784                                          talloc_tos(),
1785                                          &conn->lsa_policy,
1786                                          &result);
1787                 }
1788                 TALLOC_FREE(conn->lsa_pipe);
1789                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1790                 if (conn->cli) {
1791                         cli_set_timeout(conn->cli, 500);
1792                 }
1793         }
1794
1795         if (conn->lsa_pipe_tcp != NULL) {
1796                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1797                         dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1798                                          talloc_tos(),
1799                                          &conn->lsa_policy,
1800                                          &result);
1801                 }
1802                 TALLOC_FREE(conn->lsa_pipe_tcp);
1803                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1804                 if (conn->cli) {
1805                         cli_set_timeout(conn->cli, 500);
1806                 }
1807         }
1808
1809         if (conn->netlogon_pipe != NULL) {
1810                 TALLOC_FREE(conn->netlogon_pipe);
1811                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1812                 if (conn->cli) {
1813                         cli_set_timeout(conn->cli, 500);
1814                 }
1815         }
1816
1817         if (conn->cli) {
1818                 cli_shutdown(conn->cli);
1819         }
1820
1821         conn->cli = NULL;
1822 }
1823
1824 void close_conns_after_fork(void)
1825 {
1826         struct winbindd_domain *domain;
1827         struct winbindd_cli_state *cli_state;
1828
1829         for (domain = domain_list(); domain; domain = domain->next) {
1830                 /*
1831                  * first close the low level SMB TCP connection
1832                  * so that we don't generate any SMBclose
1833                  * requests in invalidate_cm_connection()
1834                  */
1835                 if (cli_state_is_connected(domain->conn.cli)) {
1836                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1837                 }
1838
1839                 invalidate_cm_connection(&domain->conn);
1840         }
1841
1842         for (cli_state = winbindd_client_list();
1843              cli_state != NULL;
1844              cli_state = cli_state->next) {
1845                 if (cli_state->sock >= 0) {
1846                         close(cli_state->sock);
1847                         cli_state->sock = -1;
1848                 }
1849         }
1850 }
1851
1852 static bool connection_ok(struct winbindd_domain *domain)
1853 {
1854         bool ok;
1855
1856         ok = cli_state_is_connected(domain->conn.cli);
1857         if (!ok) {
1858                 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1859                           domain->dcname, domain->name));
1860                 return False;
1861         }
1862
1863         if (domain->online == False) {
1864                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1865                 return False;
1866         }
1867
1868         return True;
1869 }
1870
1871 /* Initialize a new connection up to the RPC BIND.
1872    Bypass online status check so always does network calls. */
1873
1874 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1875 {
1876         NTSTATUS result;
1877
1878         /* Internal connections never use the network. */
1879         if (domain->internal) {
1880                 domain->initialized = True;
1881                 return NT_STATUS_OK;
1882         }
1883
1884         if (connection_ok(domain)) {
1885                 if (!domain->initialized) {
1886                         set_dc_type_and_flags(domain);
1887                 }
1888                 return NT_STATUS_OK;
1889         }
1890
1891         invalidate_cm_connection(&domain->conn);
1892
1893         result = cm_open_connection(domain, &domain->conn);
1894
1895         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1896                 set_dc_type_and_flags(domain);
1897         }
1898
1899         return result;
1900 }
1901
1902 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1903 {
1904         if (domain->internal) {
1905                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1906         }
1907
1908         if (domain->initialized && !domain->online) {
1909                 /* We check for online status elsewhere. */
1910                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1911         }
1912
1913         return init_dc_connection_network(domain);
1914 }
1915
1916 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1917 {
1918         NTSTATUS status;
1919
1920         status = init_dc_connection(domain);
1921         if (!NT_STATUS_IS_OK(status)) {
1922                 return status;
1923         }
1924
1925         if (!domain->internal && domain->conn.cli == NULL) {
1926                 /* happens for trusted domains without inbound trust */
1927                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1928         }
1929
1930         return NT_STATUS_OK;
1931 }
1932
1933 /******************************************************************************
1934  Set the trust flags (direction and forest location) for a domain
1935 ******************************************************************************/
1936
1937 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1938 {
1939         struct winbindd_domain *our_domain;
1940         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1941         WERROR werr;
1942         struct netr_DomainTrustList trusts;
1943         int i;
1944         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1945                         NETR_TRUST_FLAG_OUTBOUND |
1946                         NETR_TRUST_FLAG_INBOUND);
1947         struct rpc_pipe_client *cli;
1948         TALLOC_CTX *mem_ctx = NULL;
1949         struct dcerpc_binding_handle *b;
1950
1951         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1952
1953         /* Our primary domain doesn't need to worry about trust flags.
1954            Force it to go through the network setup */
1955         if ( domain->primary ) {                
1956                 return False;           
1957         }
1958
1959         our_domain = find_our_domain();
1960
1961         if ( !connection_ok(our_domain) ) {
1962                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1963                 return False;
1964         }
1965
1966         /* This won't work unless our domain is AD */
1967
1968         if ( !our_domain->active_directory ) {
1969                 return False;
1970         }
1971
1972         /* Use DsEnumerateDomainTrusts to get us the trust direction
1973            and type */
1974
1975         result = cm_connect_netlogon(our_domain, &cli);
1976
1977         if (!NT_STATUS_IS_OK(result)) {
1978                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1979                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1980                           domain->name, nt_errstr(result)));
1981                 return False;
1982         }
1983
1984         b = cli->binding_handle;
1985
1986         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1987                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1988                 return False;
1989         }       
1990
1991         result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1992                                                       cli->desthost,
1993                                                       flags,
1994                                                       &trusts,
1995                                                       &werr);
1996         if (!NT_STATUS_IS_OK(result)) {
1997                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1998                         "failed to query trusted domain list: %s\n",
1999                         nt_errstr(result)));
2000                 talloc_destroy(mem_ctx);
2001                 return false;
2002         }
2003         if (!W_ERROR_IS_OK(werr)) {
2004                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2005                         "failed to query trusted domain list: %s\n",
2006                         win_errstr(werr)));
2007                 talloc_destroy(mem_ctx);
2008                 return false;
2009         }
2010
2011         /* Now find the domain name and get the flags */
2012
2013         for ( i=0; i<trusts.count; i++ ) {
2014                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2015                         domain->domain_flags          = trusts.array[i].trust_flags;
2016                         domain->domain_type           = trusts.array[i].trust_type;
2017                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
2018
2019                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
2020                                 domain->active_directory = True;
2021
2022                         /* This flag is only set if the domain is *our* 
2023                            primary domain and the primary domain is in
2024                            native mode */
2025
2026                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2027
2028                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2029                                   "native mode.\n", domain->name, 
2030                                   domain->native_mode ? "" : "NOT "));
2031
2032                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2033                                  "running active directory.\n", domain->name, 
2034                                  domain->active_directory ? "" : "NOT "));
2035
2036                         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2037                         domain->can_do_validation6 = domain->active_directory;
2038
2039                         domain->initialized = True;
2040
2041                         break;
2042                 }               
2043         }
2044
2045         talloc_destroy( mem_ctx );
2046
2047         return domain->initialized;     
2048 }
2049
2050 /******************************************************************************
2051  We can 'sense' certain things about the DC by it's replies to certain
2052  questions.
2053
2054  This tells us if this particular remote server is Active Directory, and if it
2055  is native mode.
2056 ******************************************************************************/
2057
2058 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2059 {
2060         NTSTATUS status, result;
2061         WERROR werr;
2062         TALLOC_CTX              *mem_ctx = NULL;
2063         struct rpc_pipe_client  *cli = NULL;
2064         struct policy_handle pol;
2065         union dssetup_DsRoleInfo info;
2066         union lsa_PolicyInformation *lsa_info = NULL;
2067
2068         if (!connection_ok(domain)) {
2069                 return;
2070         }
2071
2072         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2073                               domain->name);
2074         if (!mem_ctx) {
2075                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2076                 return;
2077         }
2078
2079         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2080
2081         status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2082                                           &ndr_table_dssetup,
2083                                           &cli);
2084
2085         if (!NT_STATUS_IS_OK(status)) {
2086                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2087                           "PI_DSSETUP on domain %s: (%s)\n",
2088                           domain->name, nt_errstr(status)));
2089
2090                 /* if this is just a non-AD domain we need to continue
2091                  * identifying so that we can in the end return with
2092                  * domain->initialized = True - gd */
2093
2094                 goto no_dssetup;
2095         }
2096
2097         status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2098                                                                   DS_ROLE_BASIC_INFORMATION,
2099                                                                   &info,
2100                                                                   &werr);
2101         TALLOC_FREE(cli);
2102
2103         if (NT_STATUS_IS_OK(status)) {
2104                 result = werror_to_ntstatus(werr);
2105         }
2106         if (!NT_STATUS_IS_OK(status)) {
2107                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2108                           "on domain %s failed: (%s)\n",
2109                           domain->name, nt_errstr(status)));
2110
2111                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2112                  * every opcode on the DSSETUP pipe, continue with
2113                  * no_dssetup mode here as well to get domain->initialized
2114                  * set - gd */
2115
2116                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2117                         goto no_dssetup;
2118                 }
2119
2120                 TALLOC_FREE(mem_ctx);
2121                 return;
2122         }
2123
2124         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2125             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2126                 domain->native_mode = True;
2127         } else {
2128                 domain->native_mode = False;
2129         }
2130
2131 no_dssetup:
2132         status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2133                                           &ndr_table_lsarpc, &cli);
2134
2135         if (!NT_STATUS_IS_OK(status)) {
2136                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2137                           "PI_LSARPC on domain %s: (%s)\n",
2138                           domain->name, nt_errstr(status)));
2139                 TALLOC_FREE(cli);
2140                 TALLOC_FREE(mem_ctx);
2141                 return;
2142         }
2143
2144         status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2145                                          SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2146
2147         if (NT_STATUS_IS_OK(status)) {
2148                 /* This particular query is exactly what Win2k clients use 
2149                    to determine that the DC is active directory */
2150                 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2151                                                      &pol,
2152                                                      LSA_POLICY_INFO_DNS,
2153                                                      &lsa_info,
2154                                                      &result);
2155         }
2156
2157         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2158                 domain->active_directory = True;
2159
2160                 if (lsa_info->dns.name.string) {
2161                         talloc_free(domain->name);
2162                         domain->name = talloc_strdup(domain,
2163                                                      lsa_info->dns.name.string);
2164                         if (domain->name == NULL) {
2165                                 goto done;
2166                         }
2167                 }
2168
2169                 if (lsa_info->dns.dns_domain.string) {
2170                         talloc_free(domain->alt_name);
2171                         domain->alt_name =
2172                                 talloc_strdup(domain,
2173                                               lsa_info->dns.dns_domain.string);
2174                         if (domain->alt_name == NULL) {
2175                                 goto done;
2176                         }
2177                 }
2178
2179                 /* See if we can set some domain trust flags about
2180                    ourself */
2181
2182                 if (lsa_info->dns.dns_forest.string) {
2183                         talloc_free(domain->forest_name);
2184                         domain->forest_name =
2185                                 talloc_strdup(domain,
2186                                               lsa_info->dns.dns_forest.string);
2187                         if (domain->forest_name == NULL) {
2188                                 goto done;
2189                         }
2190
2191                         if (strequal(domain->forest_name, domain->alt_name)) {
2192                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2193                         }
2194                 }
2195
2196                 if (lsa_info->dns.sid) {
2197                         sid_copy(&domain->sid, lsa_info->dns.sid);
2198                 }
2199         } else {
2200                 domain->active_directory = False;
2201
2202                 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2203                                                 SEC_FLAG_MAXIMUM_ALLOWED,
2204                                                 &pol);
2205
2206                 if (!NT_STATUS_IS_OK(status)) {
2207                         goto done;
2208                 }
2209
2210                 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2211                                                     &pol,
2212                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2213                                                     &lsa_info,
2214                                                     &result);
2215                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2216
2217                         if (lsa_info->account_domain.name.string) {
2218                                 talloc_free(domain->name);
2219                                 domain->name =
2220                                         talloc_strdup(domain,
2221                                                       lsa_info->account_domain.name.string);
2222                         }
2223
2224                         if (lsa_info->account_domain.sid) {
2225                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2226                         }
2227                 }
2228         }
2229 done:
2230
2231         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2232                   domain->name, domain->native_mode ? "" : "NOT "));
2233
2234         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2235                   domain->name, domain->active_directory ? "" : "NOT "));
2236
2237         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2238         domain->can_do_validation6 = domain->active_directory;
2239
2240         TALLOC_FREE(cli);
2241
2242         TALLOC_FREE(mem_ctx);
2243
2244         domain->initialized = True;
2245 }
2246
2247 /**********************************************************************
2248  Set the domain_flags (trust attributes, domain operating modes, etc... 
2249 ***********************************************************************/
2250
2251 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2252 {
2253         /* we always have to contact our primary domain */
2254
2255         if ( domain->primary ) {
2256                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2257                           "primary domain\n"));
2258                 set_dc_type_and_flags_connect( domain );
2259                 return;         
2260         }
2261
2262         /* Use our DC to get the information if possible */
2263
2264         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2265                 /* Otherwise, fallback to contacting the 
2266                    domain directly */
2267                 set_dc_type_and_flags_connect( domain );
2268         }
2269
2270         return;
2271 }
2272
2273
2274
2275 /**********************************************************************
2276 ***********************************************************************/
2277
2278 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2279                                    struct netlogon_creds_CredentialState **ppdc)
2280 {
2281         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2282         struct rpc_pipe_client *netlogon_pipe;
2283
2284         if (lp_client_schannel() == False) {
2285                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2286         }
2287
2288         result = cm_connect_netlogon(domain, &netlogon_pipe);
2289         if (!NT_STATUS_IS_OK(result)) {
2290                 return result;
2291         }
2292
2293         /* Return a pointer to the struct netlogon_creds_CredentialState from the
2294            netlogon pipe. */
2295
2296         if (!domain->conn.netlogon_pipe->dc) {
2297                 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2298         }
2299
2300         *ppdc = domain->conn.netlogon_pipe->dc;
2301         return NT_STATUS_OK;
2302 }
2303
2304 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2305                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2306 {
2307         struct winbindd_cm_conn *conn;
2308         NTSTATUS status, result;
2309         struct netlogon_creds_CredentialState *p_creds;
2310         char *machine_password = NULL;
2311         char *machine_account = NULL;
2312         const char *domain_name = NULL;
2313
2314         if (sid_check_is_our_sam(&domain->sid)) {
2315                 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2316         }
2317
2318         status = init_dc_connection_rpc(domain);
2319         if (!NT_STATUS_IS_OK(status)) {
2320                 return status;
2321         }
2322
2323         conn = &domain->conn;
2324
2325         if (rpccli_is_connected(conn->samr_pipe)) {
2326                 goto done;
2327         }
2328
2329         TALLOC_FREE(conn->samr_pipe);
2330
2331         /*
2332          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2333          * sign and sealed pipe using the machine account password by
2334          * preference. If we can't - try schannel, if that fails, try
2335          * anonymous.
2336          */
2337
2338         if ((conn->cli->user_name[0] == '\0') ||
2339             (conn->cli->domain[0] == '\0') || 
2340             (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2341         {
2342                 status = get_trust_creds(domain, &machine_password,
2343                                          &machine_account, NULL);
2344                 if (!NT_STATUS_IS_OK(status)) {
2345                         DEBUG(10, ("cm_connect_sam: No no user available for "
2346                                    "domain %s, trying schannel\n", conn->cli->domain));
2347                         goto schannel;
2348                 }
2349                 domain_name = domain->name;
2350         } else {
2351                 machine_password = SMB_STRDUP(conn->cli->password);
2352                 machine_account = SMB_STRDUP(conn->cli->user_name);
2353                 domain_name = conn->cli->domain;
2354         }
2355
2356         if (!machine_password || !machine_account) {
2357                 status = NT_STATUS_NO_MEMORY;
2358                 goto done;
2359         }
2360
2361         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2362            authenticated SAMR pipe with sign & seal. */
2363         status = cli_rpc_pipe_open_spnego(conn->cli,
2364                                           &ndr_table_samr,
2365                                           NCACN_NP,
2366                                           GENSEC_OID_NTLMSSP,
2367                                           DCERPC_AUTH_LEVEL_PRIVACY,
2368                                           smbXcli_conn_remote_name(conn->cli->conn),
2369                                           domain_name,
2370                                           machine_account,
2371                                           machine_password,
2372                                           &conn->samr_pipe);
2373
2374         if (!NT_STATUS_IS_OK(status)) {
2375                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2376                           "pipe for domain %s using NTLMSSP "
2377                           "authenticated pipe: user %s\\%s. Error was "
2378                           "%s\n", domain->name, domain_name,
2379                           machine_account, nt_errstr(status)));
2380                 goto schannel;
2381         }
2382
2383         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2384                   "domain %s using NTLMSSP authenticated "
2385                   "pipe: user %s\\%s\n", domain->name,
2386                   domain_name, machine_account));
2387
2388         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2389                                       conn->samr_pipe->desthost,
2390                                       SEC_FLAG_MAXIMUM_ALLOWED,
2391                                       &conn->sam_connect_handle,
2392                                       &result);
2393         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2394                 goto open_domain;
2395         }
2396         if (NT_STATUS_IS_OK(status)) {
2397                 status = result;
2398         }
2399
2400         DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2401                   "failed for domain %s, error was %s. Trying schannel\n",
2402                   domain->name, nt_errstr(status) ));
2403         TALLOC_FREE(conn->samr_pipe);
2404
2405  schannel:
2406
2407         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2408
2409         status = cm_get_schannel_creds(domain, &p_creds);
2410         if (!NT_STATUS_IS_OK(status)) {
2411                 /* If this call fails - conn->cli can now be NULL ! */
2412                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2413                            "for domain %s (error %s), trying anon\n",
2414                         domain->name,
2415                         nt_errstr(status) ));
2416                 goto anonymous;
2417         }
2418         status = cli_rpc_pipe_open_schannel_with_key
2419                 (conn->cli, &ndr_table_samr, NCACN_NP,
2420                  DCERPC_AUTH_LEVEL_PRIVACY,
2421                  domain->name, &p_creds, &conn->samr_pipe);
2422
2423         if (!NT_STATUS_IS_OK(status)) {
2424                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2425                           "domain %s using schannel. Error was %s\n",
2426                           domain->name, nt_errstr(status) ));
2427                 goto anonymous;
2428         }
2429         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2430                   "schannel.\n", domain->name ));
2431
2432         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2433                                       conn->samr_pipe->desthost,
2434                                       SEC_FLAG_MAXIMUM_ALLOWED,
2435                                       &conn->sam_connect_handle,
2436                                       &result);
2437         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2438                 goto open_domain;
2439         }
2440         if (NT_STATUS_IS_OK(status)) {
2441                 status = result;
2442         }
2443         DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2444                   "for domain %s, error was %s. Trying anonymous\n",
2445                   domain->name, nt_errstr(status) ));
2446         TALLOC_FREE(conn->samr_pipe);
2447
2448  anonymous:
2449
2450         /* Finally fall back to anonymous. */
2451         status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2452                                           &conn->samr_pipe);
2453
2454         if (!NT_STATUS_IS_OK(status)) {
2455                 goto done;
2456         }
2457
2458         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2459                                       conn->samr_pipe->desthost,
2460                                       SEC_FLAG_MAXIMUM_ALLOWED,
2461                                       &conn->sam_connect_handle,
2462                                       &result);
2463         if (!NT_STATUS_IS_OK(status)) {
2464                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2465                           "for domain %s Error was %s\n",
2466                           domain->name, nt_errstr(status) ));
2467                 goto done;
2468         }
2469         if (!NT_STATUS_IS_OK(result)) {
2470                 status = result;
2471                 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2472                           "for domain %s Error was %s\n",
2473                           domain->name, nt_errstr(result)));
2474                 goto done;
2475         }
2476
2477  open_domain:
2478         status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2479                                         mem_ctx,
2480                                         &conn->sam_connect_handle,
2481                                         SEC_FLAG_MAXIMUM_ALLOWED,
2482                                         &domain->sid,
2483                                         &conn->sam_domain_handle,
2484                                         &result);
2485         if (!NT_STATUS_IS_OK(status)) {
2486                 goto done;
2487         }
2488
2489         status = result;
2490  done:
2491
2492         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2493                 /*
2494                  * if we got access denied, we might just have no access rights
2495                  * to talk to the remote samr server server (e.g. when we are a
2496                  * PDC and we are connecting a w2k8 pdc via an interdomain
2497                  * trust). In that case do not invalidate the whole connection
2498                  * stack
2499                  */
2500                 TALLOC_FREE(conn->samr_pipe);
2501                 ZERO_STRUCT(conn->sam_domain_handle);
2502                 return status;
2503         } else if (!NT_STATUS_IS_OK(status)) {
2504                 invalidate_cm_connection(conn);
2505                 return status;
2506         }
2507
2508         *cli = conn->samr_pipe;
2509         *sam_handle = conn->sam_domain_handle;
2510         SAFE_FREE(machine_password);
2511         SAFE_FREE(machine_account);
2512         return status;
2513 }
2514
2515 /**********************************************************************
2516  open an schanneld ncacn_ip_tcp connection to LSA
2517 ***********************************************************************/
2518
2519 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2520                             TALLOC_CTX *mem_ctx,
2521                             struct rpc_pipe_client **cli)
2522 {
2523         struct winbindd_cm_conn *conn;
2524         struct netlogon_creds_CredentialState *creds;
2525         NTSTATUS status;
2526
2527         DEBUG(10,("cm_connect_lsa_tcp\n"));
2528
2529         status = init_dc_connection_rpc(domain);
2530         if (!NT_STATUS_IS_OK(status)) {
2531                 return status;
2532         }
2533
2534         conn = &domain->conn;
2535
2536         if (conn->lsa_pipe_tcp &&
2537             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2538             conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2539             rpccli_is_connected(conn->lsa_pipe_tcp)) {
2540                 goto done;
2541         }
2542
2543         TALLOC_FREE(conn->lsa_pipe_tcp);
2544
2545         status = cm_get_schannel_creds(domain, &creds);
2546         if (!NT_STATUS_IS_OK(status)) {
2547                 goto done;
2548         }
2549
2550         status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2551                                                      &ndr_table_lsarpc,
2552                                                      NCACN_IP_TCP,
2553                                                      DCERPC_AUTH_LEVEL_PRIVACY,
2554                                                      domain->name,
2555                                                      &creds,
2556                                                      &conn->lsa_pipe_tcp);
2557         if (!NT_STATUS_IS_OK(status)) {
2558                 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2559                         nt_errstr(status)));
2560                 goto done;
2561         }
2562
2563  done:
2564         if (!NT_STATUS_IS_OK(status)) {
2565                 TALLOC_FREE(conn->lsa_pipe_tcp);
2566                 return status;
2567         }
2568
2569         *cli = conn->lsa_pipe_tcp;
2570
2571         return status;
2572 }
2573
2574 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2575                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2576 {
2577         struct winbindd_cm_conn *conn;
2578         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2579         struct netlogon_creds_CredentialState *p_creds;
2580
2581         result = init_dc_connection_rpc(domain);
2582         if (!NT_STATUS_IS_OK(result))
2583                 return result;
2584
2585         conn = &domain->conn;
2586
2587         if (rpccli_is_connected(conn->lsa_pipe)) {
2588                 goto done;
2589         }
2590
2591         TALLOC_FREE(conn->lsa_pipe);
2592
2593         if ((conn->cli->user_name[0] == '\0') ||
2594             (conn->cli->domain[0] == '\0') || 
2595             (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2596                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2597                            "domain %s, trying schannel\n", conn->cli->domain));
2598                 goto schannel;
2599         }
2600
2601         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2602          * authenticated LSA pipe with sign & seal. */
2603         result = cli_rpc_pipe_open_spnego
2604                 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2605                  GENSEC_OID_NTLMSSP,
2606                  DCERPC_AUTH_LEVEL_PRIVACY,
2607                  smbXcli_conn_remote_name(conn->cli->conn),
2608                  conn->cli->domain, conn->cli->user_name, conn->cli->password,
2609                  &conn->lsa_pipe);
2610
2611         if (!NT_STATUS_IS_OK(result)) {
2612                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2613                           "domain %s using NTLMSSP authenticated pipe: user "
2614                           "%s\\%s. Error was %s. Trying schannel.\n",
2615                           domain->name, conn->cli->domain,
2616                           conn->cli->user_name, nt_errstr(result)));
2617                 goto schannel;
2618         }
2619
2620         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2621                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2622                   domain->name, conn->cli->domain, conn->cli->user_name ));
2623
2624         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2625                                         SEC_FLAG_MAXIMUM_ALLOWED,
2626                                         &conn->lsa_policy);
2627         if (NT_STATUS_IS_OK(result)) {
2628                 goto done;
2629         }
2630
2631         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2632                   "schannel\n"));
2633
2634         TALLOC_FREE(conn->lsa_pipe);
2635
2636  schannel:
2637
2638         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2639
2640         result = cm_get_schannel_creds(domain, &p_creds);
2641         if (!NT_STATUS_IS_OK(result)) {
2642                 /* If this call fails - conn->cli can now be NULL ! */
2643                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2644                            "for domain %s (error %s), trying anon\n",
2645                         domain->name,
2646                         nt_errstr(result) ));
2647                 goto anonymous;
2648         }
2649         result = cli_rpc_pipe_open_schannel_with_key
2650                 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2651                  DCERPC_AUTH_LEVEL_PRIVACY,
2652                  domain->name, &p_creds, &conn->lsa_pipe);
2653
2654         if (!NT_STATUS_IS_OK(result)) {
2655                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2656                           "domain %s using schannel. Error was %s\n",
2657                           domain->name, nt_errstr(result) ));
2658                 goto anonymous;
2659         }
2660         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2661                   "schannel.\n", domain->name ));
2662
2663         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2664                                         SEC_FLAG_MAXIMUM_ALLOWED,
2665                                         &conn->lsa_policy);
2666         if (NT_STATUS_IS_OK(result)) {
2667                 goto done;
2668         }
2669
2670         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2671                   "anonymous\n"));
2672
2673         TALLOC_FREE(conn->lsa_pipe);
2674
2675  anonymous:
2676
2677         result = cli_rpc_pipe_open_noauth(conn->cli,
2678                                           &ndr_table_lsarpc,
2679                                           &conn->lsa_pipe);
2680         if (!NT_STATUS_IS_OK(result)) {
2681                 goto done;
2682         }
2683
2684         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2685                                         SEC_FLAG_MAXIMUM_ALLOWED,
2686                                         &conn->lsa_policy);
2687  done:
2688         if (!NT_STATUS_IS_OK(result)) {
2689                 invalidate_cm_connection(conn);
2690                 return result;
2691         }
2692
2693         *cli = conn->lsa_pipe;
2694         *lsa_policy = conn->lsa_policy;
2695         return result;
2696 }
2697
2698 /****************************************************************************
2699 Open a LSA connection to a DC, suiteable for LSA lookup calls.
2700 ****************************************************************************/
2701
2702 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
2703                          TALLOC_CTX *mem_ctx,
2704                          struct rpc_pipe_client **cli,
2705                          struct policy_handle *lsa_policy)
2706 {
2707         NTSTATUS status;
2708
2709         if (domain->can_do_ncacn_ip_tcp) {
2710                 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2711                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
2712                     NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
2713                     NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
2714                         invalidate_cm_connection(&domain->conn);
2715                         status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2716                 }
2717                 if (NT_STATUS_IS_OK(status)) {
2718                         return status;
2719                 }
2720
2721                 /*
2722                  * we tried twice to connect via ncan_ip_tcp and schannel and
2723                  * failed - maybe it is a trusted domain we can't connect to ?
2724                  * do not try tcp next time - gd
2725                  */
2726                 domain->can_do_ncacn_ip_tcp = false;
2727         }
2728
2729         status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
2730
2731         return status;
2732 }
2733
2734 /****************************************************************************
2735  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2736  session key stored in conn->netlogon_pipe->dc->sess_key.
2737 ****************************************************************************/
2738
2739 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2740                              struct rpc_pipe_client **cli)
2741 {
2742         struct winbindd_cm_conn *conn;
2743         NTSTATUS result;
2744
2745         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
2746         uint8_t  mach_pwd[16];
2747         enum netr_SchannelType sec_chan_type;
2748         const char *account_name;
2749         struct rpc_pipe_client *netlogon_pipe = NULL;
2750
2751         *cli = NULL;
2752
2753         result = init_dc_connection_rpc(domain);
2754         if (!NT_STATUS_IS_OK(result)) {
2755                 return result;
2756         }
2757
2758         conn = &domain->conn;
2759
2760         if (rpccli_is_connected(conn->netlogon_pipe)) {
2761                 *cli = conn->netlogon_pipe;
2762                 return NT_STATUS_OK;
2763         }
2764
2765         TALLOC_FREE(conn->netlogon_pipe);
2766
2767         result = cli_rpc_pipe_open_noauth(conn->cli,
2768                                           &ndr_table_netlogon,
2769                                           &netlogon_pipe);
2770         if (!NT_STATUS_IS_OK(result)) {
2771                 return result;
2772         }
2773
2774         if ((!IS_DC) && (!domain->primary)) {
2775                 /* Clear the schannel request bit and drop down */
2776                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2777                 goto no_schannel;
2778         }
2779
2780         if (lp_client_schannel() != False) {
2781                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2782         }
2783
2784         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2785                                &sec_chan_type))
2786         {
2787                 TALLOC_FREE(netlogon_pipe);
2788                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2789         }
2790
2791         result = rpccli_netlogon_setup_creds(
2792                  netlogon_pipe,
2793                  domain->dcname, /* server name. */
2794                  domain->name,   /* domain name */
2795                  lp_netbios_name(), /* client name */
2796                  account_name,   /* machine account */
2797                  mach_pwd,       /* machine password */
2798                  sec_chan_type,  /* from get_trust_pw */
2799                  &neg_flags);
2800
2801         if (!NT_STATUS_IS_OK(result)) {
2802                 TALLOC_FREE(netlogon_pipe);
2803                 return result;
2804         }
2805
2806         if ((lp_client_schannel() == True) &&
2807                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2808                 DEBUG(3, ("Server did not offer schannel\n"));
2809                 TALLOC_FREE(netlogon_pipe);
2810                 return NT_STATUS_ACCESS_DENIED;
2811         }
2812
2813  no_schannel:
2814         if ((lp_client_schannel() == False) ||
2815                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2816                 /*
2817                  * NetSamLogonEx only works for schannel
2818                  */
2819                 domain->can_do_samlogon_ex = False;
2820
2821                 /* We're done - just keep the existing connection to NETLOGON
2822                  * open */
2823                 conn->netlogon_pipe = netlogon_pipe;
2824                 *cli = conn->netlogon_pipe;
2825                 return NT_STATUS_OK;
2826         }
2827
2828         /* Using the credentials from the first pipe, open a signed and sealed
2829            second netlogon pipe. The session key is stored in the schannel
2830            part of the new pipe auth struct.
2831         */
2832
2833         result = cli_rpc_pipe_open_schannel_with_key(
2834                 conn->cli, &ndr_table_netlogon, NCACN_NP,
2835                 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2836                 &conn->netlogon_pipe);
2837
2838         /* We can now close the initial netlogon pipe. */
2839         TALLOC_FREE(netlogon_pipe);
2840
2841         if (!NT_STATUS_IS_OK(result)) {
2842                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2843                           "was %s\n", nt_errstr(result)));
2844
2845                 invalidate_cm_connection(conn);
2846                 return result;
2847         }
2848
2849         /*
2850          * Always try netr_LogonSamLogonEx. We will fall back for NT4
2851          * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2852          * supported). We used to only try SamLogonEx for AD, but
2853          * Samba DCs can also do it. And because we don't distinguish
2854          * between Samba and NT4, always try it once.
2855          */
2856         domain->can_do_samlogon_ex = true;
2857
2858         *cli = conn->netlogon_pipe;
2859         return NT_STATUS_OK;
2860 }
2861
2862 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2863                             void *private_data,
2864                             uint32_t msg_type,
2865                             struct server_id server_id,
2866                             DATA_BLOB *data)
2867 {
2868         struct winbindd_domain *domain;
2869         char *freeit = NULL;
2870         char *addr;
2871
2872         if ((data == NULL)
2873             || (data->data == NULL)
2874             || (data->length == 0)
2875             || (data->data[data->length-1] != '\0')) {
2876                 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2877                           "string\n"));
2878                 return;
2879         }
2880
2881         addr = (char *)data->data;
2882         DEBUG(10, ("IP %s dropped\n", addr));
2883
2884         if (!is_ipaddress(addr)) {
2885                 char *slash;
2886                 /*
2887                  * Some code sends us ip addresses with the /netmask
2888                  * suffix
2889                  */
2890                 slash = strchr(addr, '/');
2891                 if (slash == NULL) {
2892                         DEBUG(1, ("invalid msg_ip_dropped message: %s",
2893                                   addr));
2894                         return;
2895                 }
2896                 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2897                 if (freeit == NULL) {
2898                         DEBUG(1, ("talloc failed\n"));
2899                         return;
2900                 }
2901                 addr = freeit;
2902                 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2903         }
2904
2905         for (domain = domain_list(); domain != NULL; domain = domain->next) {
2906                 char sockaddr[INET6_ADDRSTRLEN];
2907
2908                 if (!cli_state_is_connected(domain->conn.cli)) {
2909                         continue;
2910                 }
2911
2912                 print_sockaddr(sockaddr, sizeof(sockaddr),
2913                                smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
2914
2915                 if (strequal(sockaddr, addr)) {
2916                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2917                 }
2918         }
2919         TALLOC_FREE(freeit);
2920 }