s4:torture/smb2/session: Fix expire tests
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob2e98c7634e8804d1b812a9aec938c68b1504be52
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
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
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.
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.
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/>.
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:
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
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.
45 The TNG design is quite good but I disagree with some aspects of the
46 implementation. -tpot
51 TODO:
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
57 various sam handles.
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "libsmb/namequery.h"
64 #include "../libcli/auth/libcli_auth.h"
65 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
66 #include "rpc_client/cli_pipe.h"
67 #include "rpc_client/cli_netlogon.h"
68 #include "../librpc/gen_ndr/ndr_samr_c.h"
69 #include "../librpc/gen_ndr/ndr_lsa_c.h"
70 #include "rpc_client/cli_lsarpc.h"
71 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
72 #include "libads/sitename_cache.h"
73 #include "libsmb/libsmb.h"
74 #include "libsmb/clidgram.h"
75 #include "ads.h"
76 #include "secrets.h"
77 #include "../libcli/security/security.h"
78 #include "passdb.h"
79 #include "messages.h"
80 #include "auth/gensec/gensec.h"
81 #include "../libcli/smb/smbXcli_base.h"
82 #include "libcli/auth/netlogon_creds_cli.h"
83 #include "auth.h"
84 #include "rpc_server/rpc_ncacn_np.h"
85 #include "auth/credentials/credentials.h"
86 #include "lib/param/param.h"
87 #include "lib/gencache.h"
89 #undef DBGC_CLASS
90 #define DBGC_CLASS DBGC_WINBIND
92 struct dc_name_ip {
93 fstring name;
94 struct sockaddr_storage ss;
97 extern struct winbindd_methods reconnect_methods;
98 extern bool override_logfile;
100 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
101 static void set_dc_type_and_flags( struct winbindd_domain *domain );
102 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
103 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
104 struct dc_name_ip **dcs, int *num_dcs,
105 uint32_t request_flags);
107 /****************************************************************
108 Child failed to find DC's. Reschedule check.
109 ****************************************************************/
111 static void msg_failed_to_go_online(struct messaging_context *msg,
112 void *private_data,
113 uint32_t msg_type,
114 struct server_id server_id,
115 DATA_BLOB *data)
117 struct winbindd_domain *domain;
118 const char *domainname = (const char *)data->data;
120 if (data->data == NULL || data->length == 0) {
121 return;
124 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
126 for (domain = domain_list(); domain; domain = domain->next) {
127 if (domain->internal) {
128 continue;
131 if (strequal(domain->name, domainname)) {
132 if (domain->online) {
133 /* We're already online, ignore. */
134 DEBUG(5,("msg_fail_to_go_online: domain %s "
135 "already online.\n", domainname));
136 continue;
139 /* Reschedule the online check. */
140 set_domain_offline(domain);
141 break;
146 /****************************************************************
147 Actually cause a reconnect from a message.
148 ****************************************************************/
150 static void msg_try_to_go_online(struct messaging_context *msg,
151 void *private_data,
152 uint32_t msg_type,
153 struct server_id server_id,
154 DATA_BLOB *data)
156 struct winbindd_domain *domain;
157 const char *domainname = (const char *)data->data;
159 if (data->data == NULL || data->length == 0) {
160 return;
163 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
165 for (domain = domain_list(); domain; domain = domain->next) {
166 if (domain->internal) {
167 continue;
170 if (strequal(domain->name, domainname)) {
172 if (domain->online) {
173 /* We're already online, ignore. */
174 DEBUG(5,("msg_try_to_go_online: domain %s "
175 "already online.\n", domainname));
176 continue;
179 /* This call takes care of setting the online
180 flag to true if we connected, or re-adding
181 the offline handler if false. Bypasses online
182 check so always does network calls. */
184 init_dc_connection_network(domain, true);
185 break;
190 /****************************************************************
191 Fork a child to try and contact a DC. Do this as contacting a
192 DC requires blocking lookups and we don't want to block our
193 parent.
194 ****************************************************************/
196 static bool fork_child_dc_connect(struct winbindd_domain *domain)
198 struct dc_name_ip *dcs = NULL;
199 int num_dcs = 0;
200 TALLOC_CTX *mem_ctx = NULL;
201 pid_t parent_pid = getpid();
202 char *lfile = NULL;
203 NTSTATUS status;
204 bool ok;
206 if (domain->dc_probe_pid != (pid_t)-1) {
208 * We might already have a DC probe
209 * child working, check.
211 if (process_exists_by_pid(domain->dc_probe_pid)) {
212 DEBUG(10,("fork_child_dc_connect: pid %u already "
213 "checking for DC's.\n",
214 (unsigned int)domain->dc_probe_pid));
215 return true;
217 domain->dc_probe_pid = (pid_t)-1;
220 domain->dc_probe_pid = fork();
222 if (domain->dc_probe_pid == (pid_t)-1) {
223 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
224 return False;
227 if (domain->dc_probe_pid != (pid_t)0) {
228 /* Parent */
229 messaging_register(global_messaging_context(), NULL,
230 MSG_WINBIND_TRY_TO_GO_ONLINE,
231 msg_try_to_go_online);
232 messaging_register(global_messaging_context(), NULL,
233 MSG_WINBIND_FAILED_TO_GO_ONLINE,
234 msg_failed_to_go_online);
235 return True;
238 /* Child. */
240 /* Leave messages blocked - we will never process one. */
242 if (!override_logfile) {
243 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
244 DBG_ERR("fork_child_dc_connect: "
245 "out of memory in asprintf().\n");
246 _exit(1);
250 status = winbindd_reinit_after_fork(NULL, lfile);
251 if (!NT_STATUS_IS_OK(status)) {
252 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
253 nt_errstr(status)));
254 messaging_send_buf(global_messaging_context(),
255 pid_to_procid(parent_pid),
256 MSG_WINBIND_FAILED_TO_GO_ONLINE,
257 (const uint8_t *)domain->name,
258 strlen(domain->name)+1);
259 _exit(1);
261 SAFE_FREE(lfile);
263 setproctitle("dc-connect child");
265 mem_ctx = talloc_init("fork_child_dc_connect");
266 if (!mem_ctx) {
267 DEBUG(0,("talloc_init failed.\n"));
268 messaging_send_buf(global_messaging_context(),
269 pid_to_procid(parent_pid),
270 MSG_WINBIND_FAILED_TO_GO_ONLINE,
271 (const uint8_t *)domain->name,
272 strlen(domain->name)+1);
273 _exit(1);
276 ok = get_dcs(mem_ctx, domain, &dcs, &num_dcs, 0);
277 TALLOC_FREE(mem_ctx);
278 if (!ok || (num_dcs == 0)) {
279 /* Still offline ? Can't find DC's. */
280 messaging_send_buf(global_messaging_context(),
281 pid_to_procid(parent_pid),
282 MSG_WINBIND_FAILED_TO_GO_ONLINE,
283 (const uint8_t *)domain->name,
284 strlen(domain->name)+1);
285 _exit(0);
288 /* We got a DC. Send a message to our parent to get it to
289 try and do the same. */
291 messaging_send_buf(global_messaging_context(),
292 pid_to_procid(parent_pid),
293 MSG_WINBIND_TRY_TO_GO_ONLINE,
294 (const uint8_t *)domain->name,
295 strlen(domain->name)+1);
296 _exit(0);
299 /****************************************************************
300 Handler triggered if we're offline to try and detect a DC.
301 ****************************************************************/
303 static void check_domain_online_handler(struct tevent_context *ctx,
304 struct tevent_timer *te,
305 struct timeval now,
306 void *private_data)
308 struct winbindd_domain *domain =
309 (struct winbindd_domain *)private_data;
311 DEBUG(10,("check_domain_online_handler: called for domain "
312 "%s (online = %s)\n", domain->name,
313 domain->online ? "True" : "False" ));
315 TALLOC_FREE(domain->check_online_event);
317 /* Are we still in "startup" mode ? */
319 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
320 /* No longer in "startup" mode. */
321 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
322 domain->name ));
323 domain->startup = False;
326 /* We've been told to stay offline, so stay
327 that way. */
329 if (get_global_winbindd_state_offline()) {
330 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
331 domain->name ));
332 return;
335 /* Fork a child to test if it can contact a DC.
336 If it can then send ourselves a message to
337 cause a reconnect. */
339 fork_child_dc_connect(domain);
342 /****************************************************************
343 If we're still offline setup the timeout check.
344 ****************************************************************/
346 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
348 int wbr = lp_winbind_reconnect_delay();
350 if (domain->startup) {
351 domain->check_online_timeout = 10;
352 } else if (domain->check_online_timeout < wbr) {
353 domain->check_online_timeout = wbr;
357 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
358 void *private_data,
359 uint32_t msg_type,
360 struct server_id server_id,
361 DATA_BLOB *data)
363 const char *domain_name = (const char *)data->data;
364 struct winbindd_domain *domain;
366 domain = find_domain_from_name_noinit(domain_name);
367 if (domain == NULL) {
368 return;
371 domain->online = false;
373 DEBUG(10, ("Domain %s is marked as offline now.\n",
374 domain_name));
377 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
378 void *private_data,
379 uint32_t msg_type,
380 struct server_id server_id,
381 DATA_BLOB *data)
383 const char *domain_name = (const char *)data->data;
384 struct winbindd_domain *domain;
386 domain = find_domain_from_name_noinit(domain_name);
387 if (domain == NULL) {
388 return;
391 domain->online = true;
393 DEBUG(10, ("Domain %s is marked as online now.\n",
394 domain_name));
397 /****************************************************************
398 Set domain offline and also add handler to put us back online
399 if we detect a DC.
400 ****************************************************************/
402 void set_domain_offline(struct winbindd_domain *domain)
404 pid_t parent_pid = getppid();
406 DEBUG(10,("set_domain_offline: called for domain %s\n",
407 domain->name ));
409 TALLOC_FREE(domain->check_online_event);
411 if (domain->internal) {
412 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
413 domain->name ));
414 return;
417 domain->online = False;
419 /* Offline domains are always initialized. They're
420 re-initialized when they go back online. */
422 domain->initialized = True;
424 /* We only add the timeout handler that checks and
425 allows us to go back online when we've not
426 been told to remain offline. */
428 if (get_global_winbindd_state_offline()) {
429 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
430 domain->name ));
431 return;
434 /* If we're in startup mode, check again in 10 seconds, not in
435 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
437 calc_new_online_timeout_check(domain);
439 domain->check_online_event = tevent_add_timer(global_event_context(),
440 NULL,
441 timeval_current_ofs(domain->check_online_timeout,0),
442 check_domain_online_handler,
443 domain);
445 /* The above *has* to succeed for winbindd to work. */
446 if (!domain->check_online_event) {
447 smb_panic("set_domain_offline: failed to add online handler");
450 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
451 domain->name ));
453 /* Send a message to the parent that the domain is offline. */
454 if (parent_pid > 1 && !domain->internal) {
455 messaging_send_buf(global_messaging_context(),
456 pid_to_procid(parent_pid),
457 MSG_WINBIND_DOMAIN_OFFLINE,
458 (uint8_t *)domain->name,
459 strlen(domain->name) + 1);
462 /* Send an offline message to the idmap child when our
463 primary domain goes offline */
465 if ( domain->primary ) {
466 struct winbindd_child *idmap = idmap_child();
468 if ( idmap->pid != 0 ) {
469 messaging_send_buf(global_messaging_context(),
470 pid_to_procid(idmap->pid),
471 MSG_WINBIND_OFFLINE,
472 (const uint8_t *)domain->name,
473 strlen(domain->name)+1);
477 return;
480 /****************************************************************
481 Set domain online - if allowed.
482 ****************************************************************/
484 static void set_domain_online(struct winbindd_domain *domain)
486 pid_t parent_pid = getppid();
488 DEBUG(10,("set_domain_online: called for domain %s\n",
489 domain->name ));
491 if (domain->internal) {
492 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
493 domain->name ));
494 return;
497 if (get_global_winbindd_state_offline()) {
498 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
499 domain->name ));
500 return;
503 winbindd_set_locator_kdc_envs(domain);
505 /* If we are waiting to get a krb5 ticket, trigger immediately. */
506 ccache_regain_all_now();
508 /* Ok, we're out of any startup mode now... */
509 domain->startup = False;
511 if (domain->online == False) {
512 /* We were offline - now we're online. We default to
513 using the MS-RPC backend if we started offline,
514 and if we're going online for the first time we
515 should really re-initialize the backends and the
516 checks to see if we're talking to an AD or NT domain.
519 domain->initialized = False;
521 /* 'reconnect_methods' is the MS-RPC backend. */
522 if (domain->backend == &reconnect_methods) {
523 domain->backend = NULL;
527 /* Ensure we have no online timeout checks. */
528 domain->check_online_timeout = 0;
529 TALLOC_FREE(domain->check_online_event);
531 /* Ensure we ignore any pending child messages. */
532 messaging_deregister(global_messaging_context(),
533 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
534 messaging_deregister(global_messaging_context(),
535 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
537 domain->online = True;
539 /* Send a message to the parent that the domain is online. */
540 if (parent_pid > 1 && !domain->internal) {
541 messaging_send_buf(global_messaging_context(),
542 pid_to_procid(parent_pid),
543 MSG_WINBIND_DOMAIN_ONLINE,
544 (uint8_t *)domain->name,
545 strlen(domain->name) + 1);
548 /* Send an online message to the idmap child when our
549 primary domain comes online */
551 if ( domain->primary ) {
552 struct winbindd_child *idmap = idmap_child();
554 if ( idmap->pid != 0 ) {
555 messaging_send_buf(global_messaging_context(),
556 pid_to_procid(idmap->pid),
557 MSG_WINBIND_ONLINE,
558 (const uint8_t *)domain->name,
559 strlen(domain->name)+1);
563 return;
566 /****************************************************************
567 Requested to set a domain online.
568 ****************************************************************/
570 void set_domain_online_request(struct winbindd_domain *domain)
572 struct timeval tev;
574 DEBUG(10,("set_domain_online_request: called for domain %s\n",
575 domain->name ));
577 if (get_global_winbindd_state_offline()) {
578 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
579 domain->name ));
580 return;
583 if (domain->internal) {
584 DEBUG(10, ("set_domain_online_request: Internal domains are "
585 "always online\n"));
586 return;
589 /* We've been told it's safe to go online and
590 try and connect to a DC. But I don't believe it
591 because network manager seems to lie.
592 Wait at least 5 seconds. Heuristics suck... */
595 GetTimeOfDay(&tev);
597 /* Go into "startup" mode again. */
598 domain->startup_time = time_mono(NULL);
599 domain->startup = True;
601 tev.tv_sec += 5;
603 if (!domain->check_online_event) {
604 /* If we've come from being globally offline we
605 don't have a check online event handler set.
606 We need to add one now we're trying to go
607 back online. */
609 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
610 domain->name ));
613 TALLOC_FREE(domain->check_online_event);
615 domain->check_online_event = tevent_add_timer(global_event_context(),
616 NULL,
617 tev,
618 check_domain_online_handler,
619 domain);
621 /* The above *has* to succeed for winbindd to work. */
622 if (!domain->check_online_event) {
623 smb_panic("set_domain_online_request: failed to add online handler");
627 /****************************************************************
628 Add -ve connection cache entries for domain and realm.
629 ****************************************************************/
631 static void winbind_add_failed_connection_entry(
632 const struct winbindd_domain *domain,
633 const char *server,
634 NTSTATUS result)
636 add_failed_connection_entry(domain->name, server, result);
637 /* If this was the saf name for the last thing we talked to,
638 remove it. */
639 saf_delete(domain->name);
640 if (domain->alt_name != NULL) {
641 add_failed_connection_entry(domain->alt_name, server, result);
642 saf_delete(domain->alt_name);
644 winbindd_unset_locator_kdc_env(domain);
647 /* Choose between anonymous or authenticated connections. We need to use
648 an authenticated connection if DCs have the RestrictAnonymous registry
649 entry set > 0, or the "Additional restrictions for anonymous
650 connections" set in the win2k Local Security Policy.
652 Caller to free() result in domain, username, password
655 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
657 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
658 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
659 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
661 if (*username && **username) {
663 if (!*domain || !**domain)
664 *domain = smb_xstrdup(lp_workgroup());
666 if (!*password || !**password)
667 *password = smb_xstrdup("");
669 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
670 *domain, *username));
672 } else {
673 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
674 *username = smb_xstrdup("");
675 *domain = smb_xstrdup("");
676 *password = smb_xstrdup("");
680 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
681 struct cli_credentials **_creds)
684 TALLOC_CTX *frame = talloc_stackframe();
685 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
686 struct loadparm_context *lp_ctx;
687 char *username = NULL;
688 char *netbios_domain = NULL;
689 char *password = NULL;
690 struct cli_credentials *creds = NULL;
691 bool ok;
693 cm_get_ipc_userpass(&username, &netbios_domain, &password);
695 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
696 if (lp_ctx == NULL) {
697 DEBUG(1, ("loadparm_init_s3 failed\n"));
698 status = NT_STATUS_INTERNAL_ERROR;
699 goto fail;
702 creds = cli_credentials_init(mem_ctx);
703 if (creds == NULL) {
704 status = NT_STATUS_NO_MEMORY;
705 goto fail;
708 cli_credentials_set_conf(creds, lp_ctx);
709 cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
711 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
712 if (!ok) {
713 status = NT_STATUS_NO_MEMORY;
714 goto fail;
717 ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
718 if (!ok) {
719 status = NT_STATUS_NO_MEMORY;
720 goto fail;
723 ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
724 if (!ok) {
725 status = NT_STATUS_NO_MEMORY;
726 goto fail;
729 *_creds = creds;
730 creds = NULL;
731 status = NT_STATUS_OK;
732 fail:
733 TALLOC_FREE(creds);
734 SAFE_FREE(username);
735 SAFE_FREE(netbios_domain);
736 SAFE_FREE(password);
737 TALLOC_FREE(frame);
738 return status;
741 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
743 TALLOC_CTX *frame = talloc_stackframe();
744 char *ipc_account = NULL;
745 char *ipc_domain = NULL;
746 char *ipc_password = NULL;
747 const char *creds_account = NULL;
748 const char *creds_domain = NULL;
749 const char *creds_password = NULL;
750 bool ret = false;
752 cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
754 creds_account = cli_credentials_get_username(creds);
755 creds_domain = cli_credentials_get_domain(creds);
756 creds_password = cli_credentials_get_password(creds);
758 if (!strequal(ipc_domain, creds_domain)) {
759 goto done;
762 if (!strequal(ipc_account, creds_account)) {
763 goto done;
766 if (!strcsequal(ipc_password, creds_password)) {
767 goto done;
770 ret = true;
771 done:
772 SAFE_FREE(ipc_account);
773 SAFE_FREE(ipc_domain);
774 SAFE_FREE(ipc_password);
775 TALLOC_FREE(frame);
776 return ret;
779 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
780 fstring dcname,
781 struct sockaddr_storage *dc_ss,
782 uint32_t request_flags)
784 struct winbindd_domain *our_domain = NULL;
785 struct rpc_pipe_client *netlogon_pipe = NULL;
786 NTSTATUS result;
787 WERROR werr;
788 TALLOC_CTX *mem_ctx;
789 unsigned int orig_timeout;
790 const char *tmp = NULL;
791 const char *p;
792 struct dcerpc_binding_handle *b;
794 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
795 * moment.... */
797 if (IS_DC) {
798 return False;
801 if (domain->primary) {
802 return False;
805 our_domain = find_our_domain();
807 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
808 return False;
811 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
812 if (!NT_STATUS_IS_OK(result)) {
813 talloc_destroy(mem_ctx);
814 return False;
817 b = netlogon_pipe->binding_handle;
819 /* This call can take a long time - allow the server to time out.
820 35 seconds should do it. */
822 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
824 if (our_domain->active_directory) {
825 struct netr_DsRGetDCNameInfo *domain_info = NULL;
828 * TODO request flags are not respected in the server
829 * (and in some cases, like REQUIRE_PDC, causes an error)
831 result = dcerpc_netr_DsRGetDCName(b,
832 mem_ctx,
833 our_domain->dcname,
834 domain->name,
835 NULL,
836 NULL,
837 request_flags|DS_RETURN_DNS_NAME,
838 &domain_info,
839 &werr);
840 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
841 tmp = talloc_strdup(
842 mem_ctx, domain_info->dc_unc);
843 if (tmp == NULL) {
844 DEBUG(0, ("talloc_strdup failed\n"));
845 talloc_destroy(mem_ctx);
846 return false;
848 if (domain->alt_name == NULL) {
849 domain->alt_name = talloc_strdup(domain,
850 domain_info->domain_name);
851 if (domain->alt_name == NULL) {
852 DEBUG(0, ("talloc_strdup failed\n"));
853 talloc_destroy(mem_ctx);
854 return false;
857 if (domain->forest_name == NULL) {
858 domain->forest_name = talloc_strdup(domain,
859 domain_info->forest_name);
860 if (domain->forest_name == NULL) {
861 DEBUG(0, ("talloc_strdup failed\n"));
862 talloc_destroy(mem_ctx);
863 return false;
867 } else {
868 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
869 our_domain->dcname,
870 domain->name,
871 &tmp,
872 &werr);
875 /* And restore our original timeout. */
876 rpccli_set_timeout(netlogon_pipe, orig_timeout);
878 if (!NT_STATUS_IS_OK(result)) {
879 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
880 nt_errstr(result)));
881 talloc_destroy(mem_ctx);
882 return false;
885 if (!W_ERROR_IS_OK(werr)) {
886 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
887 win_errstr(werr)));
888 talloc_destroy(mem_ctx);
889 return false;
892 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
893 p = strip_hostname(tmp);
895 fstrcpy(dcname, p);
897 talloc_destroy(mem_ctx);
899 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
901 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
902 return False;
905 return True;
909 * Helper function to assemble trust password and account name
911 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
912 TALLOC_CTX *mem_ctx,
913 bool netlogon,
914 struct cli_credentials **_creds)
916 const struct winbindd_domain *creds_domain = NULL;
917 struct cli_credentials *creds;
918 NTSTATUS status;
919 bool force_machine_account = false;
921 /* If we are a DC and this is not our own domain */
923 if (!domain->active_directory) {
924 if (!netlogon) {
926 * For non active directory domains
927 * we can only use NTLMSSP for SMB.
929 * But the trust account is not allowed
930 * to use SMB with NTLMSSP.
932 force_machine_account = true;
936 if (IS_DC && !force_machine_account) {
937 creds_domain = domain;
938 } else {
939 creds_domain = find_our_domain();
940 if (creds_domain == NULL) {
941 return NT_STATUS_INVALID_SERVER_STATE;
945 status = pdb_get_trust_credentials(creds_domain->name,
946 creds_domain->alt_name,
947 mem_ctx,
948 &creds);
949 if (!NT_STATUS_IS_OK(status)) {
950 goto ipc_fallback;
953 if (creds_domain != domain) {
955 * We can only use schannel against a direct trust
957 cli_credentials_set_secure_channel_type(creds,
958 SEC_CHAN_NULL);
961 *_creds = creds;
962 return NT_STATUS_OK;
964 ipc_fallback:
965 if (netlogon) {
966 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
969 status = cm_get_ipc_credentials(mem_ctx, &creds);
970 if (!NT_STATUS_IS_OK(status)) {
971 return status;
974 *_creds = creds;
975 return NT_STATUS_OK;
978 /************************************************************************
979 Given a fd with a just-connected TCP connection to a DC, open a connection
980 to the pipe.
981 ************************************************************************/
983 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
984 const int sockfd,
985 const char *controller,
986 struct cli_state **cli,
987 bool *retry)
989 bool try_ipc_auth = false;
990 const char *machine_principal = NULL;
991 const char *machine_realm = NULL;
992 const char *machine_account = NULL;
993 const char *machine_domain = NULL;
994 int flags = 0;
995 struct cli_credentials *creds = NULL;
997 struct named_mutex *mutex;
999 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1000 NTSTATUS tmp_status;
1001 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
1003 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
1005 if (IS_AD_DC) {
1006 if (domain->secure_channel_type == SEC_CHAN_NULL) {
1008 * Make sure we don't even try to
1009 * connect to a foreign domain
1010 * without a direct outbound trust.
1012 return NT_STATUS_NO_TRUST_LSA_SECRET;
1016 * As AD DC we only use netlogon and lsa
1017 * using schannel over an anonymous transport
1018 * (ncacn_ip_tcp or ncacn_np).
1020 * Currently we always establish the SMB connection,
1021 * even if we don't use it, because we later use ncacn_ip_tcp.
1023 * As we won't use the SMB connection there's no
1024 * need to try kerberos. And NT4 domains expect
1025 * an anonymous IPC$ connection anyway.
1027 smb_sign_client_connections = SMB_SIGNING_OFF;
1030 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
1032 * If we are connecting to our own AD domain, require
1033 * smb signing to disrupt MITM attacks
1035 if (domain->primary && lp_security() == SEC_ADS) {
1036 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1038 * If we are in or are an AD domain and connecting to another
1039 * AD domain in our forest
1040 * then require smb signing to disrupt MITM attacks
1042 } else if ((lp_security() == SEC_ADS)
1043 && domain->active_directory
1044 && (domain->domain_trust_attribs
1045 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
1046 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1050 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1051 controller, domain->name ));
1053 *retry = True;
1055 mutex = grab_named_mutex(talloc_tos(), controller,
1056 WINBIND_SERVER_MUTEX_WAIT_TIME);
1057 if (mutex == NULL) {
1058 close(sockfd);
1059 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1060 controller));
1061 result = NT_STATUS_POSSIBLE_DEADLOCK;
1062 goto done;
1065 *cli = cli_state_create(NULL, sockfd, controller,
1066 smb_sign_client_connections, flags);
1067 if (*cli == NULL) {
1068 close(sockfd);
1069 DEBUG(1, ("Could not cli_initialize\n"));
1070 result = NT_STATUS_NO_MEMORY;
1071 goto done;
1074 cli_set_timeout(*cli, 10000); /* 10 seconds */
1076 set_socket_options(sockfd, lp_socket_options());
1078 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
1079 lp_client_ipc_min_protocol(),
1080 lp_client_ipc_max_protocol());
1082 if (!NT_STATUS_IS_OK(result)) {
1083 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
1084 goto done;
1087 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
1088 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
1089 try_ipc_auth = true;
1090 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1091 try_ipc_auth = true;
1092 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1094 * If we are forcing on SMB signing, then we must
1095 * require authentication unless this is a one-way
1096 * trust, and we have no stored user/password
1098 try_ipc_auth = true;
1101 if (IS_AD_DC) {
1103 * As AD DC we only use netlogon and lsa
1104 * using schannel over an anonymous transport
1105 * (ncacn_ip_tcp or ncacn_np).
1107 * Currently we always establish the SMB connection,
1108 * even if we don't use it, because we later use ncacn_ip_tcp.
1110 * As we won't use the SMB connection there's no
1111 * need to try kerberos. And NT4 domains expect
1112 * an anonymous IPC$ connection anyway.
1114 try_ipc_auth = false;
1117 if (try_ipc_auth) {
1118 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
1119 if (!NT_STATUS_IS_OK(result)) {
1120 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1121 domain->name, nt_errstr(result)));
1122 goto done;
1124 } else {
1126 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1127 * would try and authentication with our machine
1128 * account password and fail. This is very rare in
1129 * the modern world however
1131 creds = cli_credentials_init_anon(talloc_tos());
1132 if (creds == NULL) {
1133 result = NT_STATUS_NO_MEMORY;
1134 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1135 domain->name, nt_errstr(result)));
1136 goto done;
1140 machine_principal = cli_credentials_get_principal(creds,
1141 talloc_tos());
1142 machine_realm = cli_credentials_get_realm(creds);
1143 machine_account = cli_credentials_get_username(creds);
1144 machine_domain = cli_credentials_get_domain(creds);
1146 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1147 "[%s] and realm [%s]\n",
1148 controller, domain->name, domain->alt_name,
1149 machine_domain, machine_account,
1150 machine_principal, machine_realm));
1152 if (cli_credentials_is_anonymous(creds)) {
1153 goto anon_fallback;
1156 winbindd_set_locator_kdc_envs(domain);
1158 result = cli_session_setup_creds(*cli, creds);
1159 if (NT_STATUS_IS_OK(result)) {
1160 goto session_setup_done;
1163 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1164 controller,
1165 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1166 nt_errstr(result)));
1169 * If we are not going to validiate the conneciton
1170 * with SMB signing, then allow us to fall back to
1171 * anonymous
1173 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1174 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1175 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1176 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1177 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1179 if (!cm_is_ipc_credentials(creds)) {
1180 goto ipc_fallback;
1183 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1184 goto done;
1187 goto anon_fallback;
1190 goto done;
1192 ipc_fallback:
1193 TALLOC_FREE(creds);
1194 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1195 if (!NT_STATUS_IS_OK(tmp_status)) {
1196 result = tmp_status;
1197 goto done;
1200 if (cli_credentials_is_anonymous(creds)) {
1201 goto anon_fallback;
1204 machine_account = cli_credentials_get_username(creds);
1205 machine_domain = cli_credentials_get_domain(creds);
1207 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1208 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1209 machine_domain, machine_account));
1211 result = cli_session_setup_creds(*cli, creds);
1212 if (NT_STATUS_IS_OK(result)) {
1213 goto session_setup_done;
1216 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1217 controller,
1218 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1219 nt_errstr(result)));
1222 * If we are not going to validiate the conneciton
1223 * with SMB signing, then allow us to fall back to
1224 * anonymous
1226 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1227 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1228 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1229 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1230 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1232 goto anon_fallback;
1235 goto done;
1237 anon_fallback:
1238 TALLOC_FREE(creds);
1240 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1241 goto done;
1244 /* Fall back to anonymous connection, this might fail later */
1245 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1246 "connection for DC %s\n",
1247 controller ));
1249 result = cli_session_setup_anon(*cli);
1250 if (NT_STATUS_IS_OK(result)) {
1251 DEBUG(5, ("Connected anonymously\n"));
1252 goto session_setup_done;
1255 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1256 controller, nt_errstr(result)));
1258 /* We can't session setup */
1259 goto done;
1261 session_setup_done:
1262 TALLOC_FREE(creds);
1265 * This should be a short term hack until
1266 * dynamic re-authentication is implemented.
1268 * See Bug 9175 - winbindd doesn't recover from
1269 * NT_STATUS_NETWORK_SESSION_EXPIRED
1271 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1272 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1275 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1276 if (!NT_STATUS_IS_OK(result)) {
1277 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1278 goto done;
1280 tcon_status = result;
1282 /* cache the server name for later connections */
1284 saf_store(domain->name, controller);
1285 if (domain->alt_name) {
1286 saf_store(domain->alt_name, controller);
1289 winbindd_set_locator_kdc_envs(domain);
1291 TALLOC_FREE(mutex);
1292 *retry = False;
1294 result = NT_STATUS_OK;
1296 done:
1297 TALLOC_FREE(mutex);
1298 TALLOC_FREE(creds);
1300 if (NT_STATUS_IS_OK(result)) {
1301 result = tcon_status;
1304 if (!NT_STATUS_IS_OK(result)) {
1305 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1306 controller, nt_errstr(result)));
1307 winbind_add_failed_connection_entry(domain, controller, result);
1308 if ((*cli) != NULL) {
1309 cli_shutdown(*cli);
1310 *cli = NULL;
1314 return result;
1317 /*******************************************************************
1318 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1319 array.
1321 Keeps the list unique by not adding duplicate entries.
1323 @param[in] mem_ctx talloc memory context to allocate from
1324 @param[in] domain_name domain of the DC
1325 @param[in] dcname name of the DC to add to the list
1326 @param[in] pss Internet address and port pair to add to the list
1327 @param[in,out] dcs array of dc_name_ip structures to add to
1328 @param[in,out] num_dcs number of dcs returned in the dcs array
1329 @return true if the list was added to, false otherwise
1330 *******************************************************************/
1332 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1333 const char *dcname, struct sockaddr_storage *pss,
1334 struct dc_name_ip **dcs, int *num)
1336 int i = 0;
1338 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1339 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1340 return False;
1343 /* Make sure there's no duplicates in the list */
1344 for (i=0; i<*num; i++)
1345 if (sockaddr_equal(
1346 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1347 (struct sockaddr *)(void *)pss))
1348 return False;
1350 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1352 if (*dcs == NULL)
1353 return False;
1355 fstrcpy((*dcs)[*num].name, dcname);
1356 (*dcs)[*num].ss = *pss;
1357 *num += 1;
1358 return True;
1361 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1362 struct sockaddr_storage *pss, uint16_t port,
1363 struct sockaddr_storage **addrs, int *num)
1365 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1367 if (*addrs == NULL) {
1368 *num = 0;
1369 return False;
1372 (*addrs)[*num] = *pss;
1373 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1375 *num += 1;
1376 return True;
1379 /*******************************************************************
1380 convert an ip to a name
1381 For an AD Domain, it checks the requirements of the request flags.
1382 *******************************************************************/
1384 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1385 const struct winbindd_domain *domain,
1386 struct sockaddr_storage *pss,
1387 char **name, uint32_t request_flags)
1389 struct ip_service ip_list;
1390 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1391 NTSTATUS status;
1392 const char *dc_name;
1393 fstring nbtname;
1394 #ifdef HAVE_ADS
1395 bool is_ad_domain = false;
1396 #endif
1397 ip_list.ss = *pss;
1398 ip_list.port = 0;
1400 #ifdef HAVE_ADS
1401 /* For active directory servers, try to get the ldap server name.
1402 None of these failures should be considered critical for now */
1404 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1405 is_ad_domain = true;
1406 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1407 is_ad_domain = domain->active_directory;
1410 if (is_ad_domain) {
1411 ADS_STRUCT *ads;
1412 ADS_STATUS ads_status;
1413 char addr[INET6_ADDRSTRLEN];
1415 print_sockaddr(addr, sizeof(addr), pss);
1417 ads = ads_init(domain->alt_name, domain->name, addr);
1418 ads->auth.flags |= ADS_AUTH_NO_BIND;
1419 ads->config.flags |= request_flags;
1420 ads->server.no_fallback = true;
1422 ads_status = ads_connect(ads);
1423 if (ADS_ERR_OK(ads_status)) {
1424 /* We got a cldap packet. */
1425 *name = talloc_strdup(mem_ctx,
1426 ads->config.ldap_server_name);
1427 if (*name == NULL) {
1428 return false;
1430 namecache_store(*name, 0x20, 1, &ip_list);
1432 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1434 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1435 if (ads_closest_dc(ads)) {
1436 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1438 /* We're going to use this KDC for this realm/domain.
1439 If we are using sites, then force the krb5 libs
1440 to use this KDC. */
1442 create_local_private_krb5_conf_for_domain(domain->alt_name,
1443 domain->name,
1444 sitename,
1445 pss);
1447 TALLOC_FREE(sitename);
1448 } else {
1449 /* use an off site KDC */
1450 create_local_private_krb5_conf_for_domain(domain->alt_name,
1451 domain->name,
1452 NULL,
1453 pss);
1455 winbindd_set_locator_kdc_envs(domain);
1457 /* Ensure we contact this DC also. */
1458 saf_store(domain->name, *name);
1459 saf_store(domain->alt_name, *name);
1462 ads_destroy( &ads );
1463 return True;
1466 ads_destroy( &ads );
1467 return false;
1469 #endif
1472 size_t len = strlen(lp_netbios_name());
1473 char my_acct_name[len+2];
1475 snprintf(my_acct_name,
1476 sizeof(my_acct_name),
1477 "%s$",
1478 lp_netbios_name());
1480 status = nbt_getdc(global_messaging_context(), 10, pss,
1481 domain->name, &domain->sid,
1482 my_acct_name, ACB_WSTRUST,
1483 nt_version, mem_ctx, &nt_version,
1484 &dc_name, NULL);
1486 if (NT_STATUS_IS_OK(status)) {
1487 *name = talloc_strdup(mem_ctx, dc_name);
1488 if (*name == NULL) {
1489 return false;
1491 namecache_store(*name, 0x20, 1, &ip_list);
1492 return True;
1495 /* try node status request */
1497 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1498 namecache_store(nbtname, 0x20, 1, &ip_list);
1500 if (name != NULL) {
1501 *name = talloc_strdup(mem_ctx, nbtname);
1502 if (*name == NULL) {
1503 return false;
1507 return true;
1509 return False;
1512 /*******************************************************************
1513 Retrieve a list of IP addresses for domain controllers.
1515 The array is sorted in the preferred connection order.
1517 @param[in] mem_ctx talloc memory context to allocate from
1518 @param[in] domain domain to retrieve DCs for
1519 @param[out] dcs array of dcs that will be returned
1520 @param[out] num_dcs number of dcs returned in the dcs array
1521 @return always true
1522 *******************************************************************/
1524 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1525 struct dc_name_ip **dcs, int *num_dcs,
1526 uint32_t request_flags)
1528 fstring dcname;
1529 struct sockaddr_storage ss;
1530 struct ip_service *ip_list = NULL;
1531 int iplist_size = 0;
1532 int i;
1533 bool is_our_domain;
1534 enum security_types sec = (enum security_types)lp_security();
1536 is_our_domain = strequal(domain->name, lp_workgroup());
1538 /* If not our domain, get the preferred DC, by asking our primary DC */
1539 if ( !is_our_domain
1540 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1541 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1542 num_dcs) )
1544 char addr[INET6_ADDRSTRLEN];
1545 print_sockaddr(addr, sizeof(addr), &ss);
1546 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1547 dcname, addr));
1548 return True;
1551 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1552 char *sitename = NULL;
1554 /* We need to make sure we know the local site before
1555 doing any DNS queries, as this will restrict the
1556 get_sorted_dc_list() call below to only fetching
1557 DNS records for the correct site. */
1559 /* Find any DC to get the site record.
1560 We deliberately don't care about the
1561 return here. */
1563 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1565 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1566 if (sitename) {
1568 /* Do the site-specific AD dns lookup first. */
1569 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1570 &iplist_size, True);
1572 /* Add ips to the DC array. We don't look up the name
1573 of the DC in this function, but we fill in the char*
1574 of the ip now to make the failed connection cache
1575 work */
1576 for ( i=0; i<iplist_size; i++ ) {
1577 char addr[INET6_ADDRSTRLEN];
1578 print_sockaddr(addr, sizeof(addr),
1579 &ip_list[i].ss);
1580 add_one_dc_unique(mem_ctx,
1581 domain->name,
1582 addr,
1583 &ip_list[i].ss,
1584 dcs,
1585 num_dcs);
1588 SAFE_FREE(ip_list);
1589 TALLOC_FREE(sitename);
1590 iplist_size = 0;
1593 /* Now we add DCs from the main AD DNS lookup. */
1594 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1595 &iplist_size, True);
1597 for ( i=0; i<iplist_size; i++ ) {
1598 char addr[INET6_ADDRSTRLEN];
1599 print_sockaddr(addr, sizeof(addr),
1600 &ip_list[i].ss);
1601 add_one_dc_unique(mem_ctx,
1602 domain->name,
1603 addr,
1604 &ip_list[i].ss,
1605 dcs,
1606 num_dcs);
1609 SAFE_FREE(ip_list);
1610 iplist_size = 0;
1613 /* Try standard netbios queries if no ADS and fall back to DNS queries
1614 * if alt_name is available */
1615 if (*num_dcs == 0) {
1616 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1617 false);
1618 if (iplist_size == 0) {
1619 if (domain->alt_name != NULL) {
1620 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1621 &iplist_size, true);
1625 for ( i=0; i<iplist_size; i++ ) {
1626 char addr[INET6_ADDRSTRLEN];
1627 print_sockaddr(addr, sizeof(addr),
1628 &ip_list[i].ss);
1629 add_one_dc_unique(mem_ctx,
1630 domain->name,
1631 addr,
1632 &ip_list[i].ss,
1633 dcs,
1634 num_dcs);
1637 SAFE_FREE(ip_list);
1638 iplist_size = 0;
1641 return True;
1644 /*******************************************************************
1645 Find and make a connection to a DC in the given domain.
1647 @param[in] mem_ctx talloc memory context to allocate from
1648 @param[in] domain domain to find a dc in
1649 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1650 @param[out] pss DC Internet address and port
1651 @param[out] fd fd of the open socket connected to the newly found dc
1652 @return true when a DC connection is made, false otherwise
1653 *******************************************************************/
1655 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1656 struct winbindd_domain *domain,
1657 char **dcname, struct sockaddr_storage *pss, int *fd,
1658 uint32_t request_flags)
1660 struct dc_name_ip *dcs = NULL;
1661 int num_dcs = 0;
1663 const char **dcnames = NULL;
1664 size_t num_dcnames = 0;
1666 struct sockaddr_storage *addrs = NULL;
1667 int num_addrs = 0;
1669 int i;
1670 size_t fd_index;
1672 NTSTATUS status;
1674 *fd = -1;
1676 again:
1677 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1678 return False;
1680 for (i=0; i<num_dcs; i++) {
1682 if (!add_string_to_array(mem_ctx, dcs[i].name,
1683 &dcnames, &num_dcnames)) {
1684 return False;
1686 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1687 &addrs, &num_addrs)) {
1688 return False;
1692 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1693 return False;
1695 if ((addrs == NULL) || (dcnames == NULL))
1696 return False;
1698 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1699 num_addrs, 0, 10, fd, &fd_index, NULL);
1700 if (!NT_STATUS_IS_OK(status)) {
1701 for (i=0; i<num_dcs; i++) {
1702 char ab[INET6_ADDRSTRLEN];
1703 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1704 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1705 "domain %s address %s. Error was %s\n",
1706 domain->name, ab, nt_errstr(status) ));
1707 winbind_add_failed_connection_entry(domain,
1708 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1710 return False;
1713 *pss = addrs[fd_index];
1715 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1716 /* Ok, we've got a name for the DC */
1717 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1718 if (*dcname == NULL) {
1719 return false;
1721 return true;
1724 /* Try to figure out the name */
1725 if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1726 return True;
1729 /* We can not continue without the DC's name */
1730 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1731 NT_STATUS_UNSUCCESSFUL);
1733 /* Throw away all arrays as we're doing this again. */
1734 TALLOC_FREE(dcs);
1735 num_dcs = 0;
1737 TALLOC_FREE(dcnames);
1738 num_dcnames = 0;
1740 TALLOC_FREE(addrs);
1741 num_addrs = 0;
1743 if (*fd != -1) {
1744 close(*fd);
1745 *fd = -1;
1748 goto again;
1751 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1753 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1754 domain_name);
1757 static void store_current_dc_in_gencache(const char *domain_name,
1758 const char *dc_name,
1759 struct cli_state *cli)
1761 char addr[INET6_ADDRSTRLEN];
1762 char *key = NULL;
1763 char *value = NULL;
1765 if (!cli_state_is_connected(cli)) {
1766 return;
1769 print_sockaddr(addr, sizeof(addr),
1770 smbXcli_conn_remote_sockaddr(cli->conn));
1772 key = current_dc_key(talloc_tos(), domain_name);
1773 if (key == NULL) {
1774 goto done;
1777 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1778 if (value == NULL) {
1779 goto done;
1782 gencache_set(key, value, 0x7fffffff);
1783 done:
1784 TALLOC_FREE(value);
1785 TALLOC_FREE(key);
1788 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1789 const char *domain_name,
1790 char **p_dc_name, char **p_dc_ip)
1792 char *key, *p;
1793 char *value = NULL;
1794 bool ret = false;
1795 char *dc_name = NULL;
1796 char *dc_ip = NULL;
1798 key = current_dc_key(talloc_tos(), domain_name);
1799 if (key == NULL) {
1800 goto done;
1802 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1803 goto done;
1805 p = strchr(value, ' ');
1806 if (p == NULL) {
1807 goto done;
1809 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1810 if (dc_ip == NULL) {
1811 goto done;
1813 dc_name = talloc_strdup(mem_ctx, p+1);
1814 if (dc_name == NULL) {
1815 goto done;
1818 if (p_dc_ip != NULL) {
1819 *p_dc_ip = dc_ip;
1820 dc_ip = NULL;
1822 if (p_dc_name != NULL) {
1823 *p_dc_name = dc_name;
1824 dc_name = NULL;
1826 ret = true;
1827 done:
1828 TALLOC_FREE(dc_name);
1829 TALLOC_FREE(dc_ip);
1830 TALLOC_FREE(key);
1831 TALLOC_FREE(value);
1832 return ret;
1835 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1836 const struct ndr_interface_table *table,
1837 struct rpc_pipe_client **ret_pipe)
1839 struct rpc_pipe_client *cli = NULL;
1840 const struct auth_session_info *session_info;
1841 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1844 session_info = get_session_info_system();
1845 SMB_ASSERT(session_info != NULL);
1847 /* create a connection to the specified pipe */
1848 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1849 status = rpc_pipe_open_interface(mem_ctx,
1850 table,
1851 session_info,
1852 NULL,
1853 NULL,
1854 global_messaging_context(),
1855 &cli);
1856 } else {
1857 status = rpc_pipe_open_internal(mem_ctx,
1858 table,
1859 session_info,
1860 NULL,
1861 NULL,
1862 global_messaging_context(),
1863 &cli);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1867 table->name, nt_errstr(status)));
1868 return status;
1871 if (ret_pipe) {
1872 *ret_pipe = cli;
1875 return NT_STATUS_OK;
1878 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1879 struct winbindd_cm_conn *new_conn,
1880 bool need_rw_dc)
1882 TALLOC_CTX *mem_ctx;
1883 NTSTATUS result;
1884 char *saf_servername;
1885 int retries;
1886 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1888 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1889 set_domain_offline(domain);
1890 return NT_STATUS_NO_MEMORY;
1893 saf_servername = saf_fetch(mem_ctx, domain->name );
1895 /* we have to check the server affinity cache here since
1896 later we select a DC based on response time and not preference */
1898 /* Check the negative connection cache
1899 before talking to it. It going down may have
1900 triggered the reconnection. */
1902 if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1903 struct sockaddr_storage ss;
1904 char *dcname = NULL;
1905 bool resolved = true;
1907 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1908 saf_servername, domain->name));
1910 /* convert an ip address to a name */
1911 if (is_ipaddress(saf_servername)) {
1912 if (!interpret_string_addr(&ss, saf_servername,
1913 AI_NUMERICHOST)) {
1914 TALLOC_FREE(mem_ctx);
1915 return NT_STATUS_UNSUCCESSFUL;
1917 } else {
1918 if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1919 resolved = false;
1923 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1924 domain->dcname = talloc_strdup(domain,
1925 dcname);
1926 if (domain->dcname == NULL) {
1927 TALLOC_FREE(mem_ctx);
1928 return NT_STATUS_NO_MEMORY;
1931 domain->dcaddr = ss;
1932 } else {
1933 winbind_add_failed_connection_entry(domain, saf_servername,
1934 NT_STATUS_UNSUCCESSFUL);
1938 for (retries = 0; retries < 3; retries++) {
1939 int fd = -1;
1940 bool retry = False;
1941 char *dcname = NULL;
1943 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1945 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1946 domain->dcname ? domain->dcname : "", domain->name));
1948 if (domain->dcname != NULL &&
1949 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1950 domain->dcname)))
1952 NTSTATUS status;
1954 status = smbsock_connect(&domain->dcaddr, 0,
1955 NULL, -1, NULL, -1,
1956 &fd, NULL, 10);
1957 if (!NT_STATUS_IS_OK(status)) {
1958 fd = -1;
1962 if ((fd == -1) &&
1963 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1965 /* This is the one place where we will
1966 set the global winbindd offline state
1967 to true, if a "WINBINDD_OFFLINE" entry
1968 is found in the winbindd cache. */
1969 set_global_winbindd_state_offline();
1970 break;
1972 if (dcname != NULL) {
1973 talloc_free(domain->dcname);
1975 domain->dcname = talloc_move(domain, &dcname);
1976 if (domain->dcname == NULL) {
1977 result = NT_STATUS_NO_MEMORY;
1978 break;
1982 new_conn->cli = NULL;
1984 result = cm_prepare_connection(domain, fd, domain->dcname,
1985 &new_conn->cli, &retry);
1986 if (!NT_STATUS_IS_OK(result)) {
1987 /* Don't leak the smb connection socket */
1988 if (fd != -1) {
1989 close(fd);
1990 fd = -1;
1994 if (!retry)
1995 break;
1998 if (NT_STATUS_IS_OK(result)) {
1999 bool seal_pipes = true;
2001 winbindd_set_locator_kdc_envs(domain);
2003 if (domain->online == False) {
2004 /* We're changing state from offline to online. */
2005 set_global_winbindd_state_online();
2007 set_domain_online(domain);
2010 * Much as I hate global state, this seems to be the point
2011 * where we can be certain that we have a proper connection to
2012 * a DC. wbinfo --dc-info needs that information, store it in
2013 * gencache with a looong timeout. This will need revisiting
2014 * once we start to connect to multiple DCs, wbcDcInfo is
2015 * already prepared for that.
2017 store_current_dc_in_gencache(domain->name, domain->dcname,
2018 new_conn->cli);
2020 seal_pipes = lp_winbind_sealed_pipes();
2021 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2022 domain->name,
2023 seal_pipes);
2025 if (seal_pipes) {
2026 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2027 } else {
2028 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2030 } else {
2031 /* Ensure we setup the retry handler. */
2032 set_domain_offline(domain);
2035 talloc_destroy(mem_ctx);
2036 return result;
2039 /* Close down all open pipes on a connection. */
2041 void invalidate_cm_connection(struct winbindd_domain *domain)
2043 NTSTATUS result;
2044 struct winbindd_cm_conn *conn = &domain->conn;
2046 /* We're closing down a possibly dead
2047 connection. Don't have impossibly long (10s) timeouts. */
2049 if (conn->cli) {
2050 cli_set_timeout(conn->cli, 1000); /* 1 second. */
2053 if (conn->samr_pipe != NULL) {
2054 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
2055 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
2056 talloc_tos(),
2057 &conn->sam_connect_handle,
2058 &result);
2060 TALLOC_FREE(conn->samr_pipe);
2061 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2062 if (conn->cli) {
2063 cli_set_timeout(conn->cli, 500);
2067 if (conn->lsa_pipe != NULL) {
2068 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2069 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2070 talloc_tos(),
2071 &conn->lsa_policy,
2072 &result);
2074 TALLOC_FREE(conn->lsa_pipe);
2075 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2076 if (conn->cli) {
2077 cli_set_timeout(conn->cli, 500);
2081 if (conn->lsa_pipe_tcp != NULL) {
2082 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2083 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2084 talloc_tos(),
2085 &conn->lsa_policy,
2086 &result);
2088 TALLOC_FREE(conn->lsa_pipe_tcp);
2089 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2090 if (conn->cli) {
2091 cli_set_timeout(conn->cli, 500);
2095 if (conn->netlogon_pipe != NULL) {
2096 TALLOC_FREE(conn->netlogon_pipe);
2097 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2098 if (conn->cli) {
2099 cli_set_timeout(conn->cli, 500);
2103 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2104 TALLOC_FREE(conn->netlogon_creds_ctx);
2106 if (conn->cli) {
2107 cli_shutdown(conn->cli);
2110 conn->cli = NULL;
2113 void close_conns_after_fork(void)
2115 struct winbindd_domain *domain;
2116 struct winbindd_cli_state *cli_state;
2118 for (domain = domain_list(); domain; domain = domain->next) {
2120 * first close the low level SMB TCP connection
2121 * so that we don't generate any SMBclose
2122 * requests in invalidate_cm_connection()
2124 if (cli_state_is_connected(domain->conn.cli)) {
2125 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2128 invalidate_cm_connection(domain);
2131 for (cli_state = winbindd_client_list();
2132 cli_state != NULL;
2133 cli_state = cli_state->next) {
2134 if (cli_state->sock >= 0) {
2135 close(cli_state->sock);
2136 cli_state->sock = -1;
2141 static bool connection_ok(struct winbindd_domain *domain)
2143 bool ok;
2145 ok = cli_state_is_connected(domain->conn.cli);
2146 if (!ok) {
2147 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2148 domain->dcname, domain->name));
2149 return False;
2152 if (domain->online == False) {
2153 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2154 return False;
2157 return True;
2160 /* Initialize a new connection up to the RPC BIND.
2161 Bypass online status check so always does network calls. */
2163 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2165 NTSTATUS result;
2166 bool skip_connection = domain->internal;
2167 if (need_rw_dc && domain->rodc) {
2168 skip_connection = false;
2171 /* Internal connections never use the network. */
2172 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2173 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2176 /* Still ask the internal LSA and SAMR server about the local domain */
2177 if (skip_connection || connection_ok(domain)) {
2178 if (!domain->initialized) {
2179 set_dc_type_and_flags(domain);
2181 return NT_STATUS_OK;
2184 invalidate_cm_connection(domain);
2186 if (!domain->primary && !domain->initialized) {
2188 * Before we connect to a trust, work out if it is an
2189 * AD domain by asking our own domain.
2191 set_dc_type_and_flags_trustinfo(domain);
2194 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2196 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2197 set_dc_type_and_flags(domain);
2200 return result;
2203 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2205 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2206 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2209 if (domain->initialized && !domain->online) {
2210 /* We check for online status elsewhere. */
2211 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2214 return init_dc_connection_network(domain, need_rw_dc);
2217 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2219 NTSTATUS status;
2221 status = init_dc_connection(domain, need_rw_dc);
2222 if (!NT_STATUS_IS_OK(status)) {
2223 return status;
2226 if (!domain->internal && domain->conn.cli == NULL) {
2227 /* happens for trusted domains without inbound trust */
2228 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2231 return NT_STATUS_OK;
2234 /******************************************************************************
2235 Set the trust flags (direction and forest location) for a domain
2236 ******************************************************************************/
2238 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2240 struct winbindd_domain *our_domain;
2241 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2242 WERROR werr;
2243 struct netr_DomainTrustList trusts;
2244 int i;
2245 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2246 NETR_TRUST_FLAG_OUTBOUND |
2247 NETR_TRUST_FLAG_INBOUND);
2248 struct rpc_pipe_client *cli;
2249 TALLOC_CTX *mem_ctx = NULL;
2250 struct dcerpc_binding_handle *b;
2252 if (IS_DC) {
2254 * On a DC we loaded all trusts
2255 * from configuration and never learn
2256 * new domains.
2258 return true;
2261 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2263 /* Our primary domain doesn't need to worry about trust flags.
2264 Force it to go through the network setup */
2265 if ( domain->primary ) {
2266 return False;
2269 mem_ctx = talloc_stackframe();
2270 our_domain = find_our_domain();
2271 if (our_domain->internal) {
2272 result = init_dc_connection(our_domain, false);
2273 if (!NT_STATUS_IS_OK(result)) {
2274 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2275 "Not able to make a connection to our domain: %s\n",
2276 nt_errstr(result)));
2277 TALLOC_FREE(mem_ctx);
2278 return false;
2282 /* This won't work unless our domain is AD */
2283 if ( !our_domain->active_directory ) {
2284 TALLOC_FREE(mem_ctx);
2285 return False;
2288 if (our_domain->internal) {
2289 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2290 } else if (!connection_ok(our_domain)) {
2291 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2292 "No connection to our domain!\n"));
2293 TALLOC_FREE(mem_ctx);
2294 return False;
2295 } else {
2296 result = cm_connect_netlogon(our_domain, &cli);
2299 if (!NT_STATUS_IS_OK(result)) {
2300 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2301 "a connection to %s for PIPE_NETLOGON (%s)\n",
2302 domain->name, nt_errstr(result)));
2303 TALLOC_FREE(mem_ctx);
2304 return False;
2306 b = cli->binding_handle;
2308 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2309 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2310 cli->desthost,
2311 flags,
2312 &trusts,
2313 &werr);
2314 if (!NT_STATUS_IS_OK(result)) {
2315 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2316 "failed to query trusted domain list: %s\n",
2317 nt_errstr(result)));
2318 TALLOC_FREE(mem_ctx);
2319 return false;
2321 if (!W_ERROR_IS_OK(werr)) {
2322 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2323 "failed to query trusted domain list: %s\n",
2324 win_errstr(werr)));
2325 TALLOC_FREE(mem_ctx);
2326 return false;
2329 /* Now find the domain name and get the flags */
2331 for ( i=0; i<trusts.count; i++ ) {
2332 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2333 domain->domain_flags = trusts.array[i].trust_flags;
2334 domain->domain_type = trusts.array[i].trust_type;
2335 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2337 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2338 domain->active_directory = True;
2340 /* This flag is only set if the domain is *our*
2341 primary domain and the primary domain is in
2342 native mode */
2344 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2346 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2347 "native mode.\n", domain->name,
2348 domain->native_mode ? "" : "NOT "));
2350 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2351 "running active directory.\n", domain->name,
2352 domain->active_directory ? "" : "NOT "));
2354 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2356 domain->initialized = True;
2358 break;
2362 TALLOC_FREE(mem_ctx);
2364 return domain->initialized;
2367 /******************************************************************************
2368 We can 'sense' certain things about the DC by it's replies to certain
2369 questions.
2371 This tells us if this particular remote server is Active Directory, and if it
2372 is native mode.
2373 ******************************************************************************/
2375 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2377 NTSTATUS status, result;
2378 WERROR werr;
2379 TALLOC_CTX *mem_ctx = NULL;
2380 struct rpc_pipe_client *cli = NULL;
2381 struct policy_handle pol;
2382 union dssetup_DsRoleInfo info;
2383 union lsa_PolicyInformation *lsa_info = NULL;
2385 if (!domain->internal && !connection_ok(domain)) {
2386 return;
2389 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2390 domain->name);
2391 if (!mem_ctx) {
2392 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2393 return;
2396 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2398 if (domain->internal) {
2399 status = wb_open_internal_pipe(mem_ctx,
2400 &ndr_table_dssetup,
2401 &cli);
2402 } else {
2403 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2404 &ndr_table_dssetup,
2405 &cli);
2408 if (!NT_STATUS_IS_OK(status)) {
2409 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2410 "PI_DSSETUP on domain %s: (%s)\n",
2411 domain->name, nt_errstr(status)));
2413 /* if this is just a non-AD domain we need to continue
2414 * identifying so that we can in the end return with
2415 * domain->initialized = True - gd */
2417 goto no_dssetup;
2420 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2421 DS_ROLE_BASIC_INFORMATION,
2422 &info,
2423 &werr);
2424 TALLOC_FREE(cli);
2426 if (NT_STATUS_IS_OK(status)) {
2427 result = werror_to_ntstatus(werr);
2429 if (!NT_STATUS_IS_OK(status)) {
2430 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2431 "on domain %s failed: (%s)\n",
2432 domain->name, nt_errstr(status)));
2434 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2435 * every opcode on the DSSETUP pipe, continue with
2436 * no_dssetup mode here as well to get domain->initialized
2437 * set - gd */
2439 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2440 goto no_dssetup;
2443 TALLOC_FREE(mem_ctx);
2444 return;
2447 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2448 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2449 domain->native_mode = True;
2450 } else {
2451 domain->native_mode = False;
2454 no_dssetup:
2455 if (domain->internal) {
2456 status = wb_open_internal_pipe(mem_ctx,
2457 &ndr_table_lsarpc,
2458 &cli);
2459 } else {
2460 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2461 &ndr_table_lsarpc, &cli);
2463 if (!NT_STATUS_IS_OK(status)) {
2464 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2465 "PI_LSARPC on domain %s: (%s)\n",
2466 domain->name, nt_errstr(status)));
2467 TALLOC_FREE(cli);
2468 TALLOC_FREE(mem_ctx);
2469 return;
2472 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2473 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2475 if (NT_STATUS_IS_OK(status)) {
2476 /* This particular query is exactly what Win2k clients use
2477 to determine that the DC is active directory */
2478 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2479 &pol,
2480 LSA_POLICY_INFO_DNS,
2481 &lsa_info,
2482 &result);
2485 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2486 domain->active_directory = True;
2488 if (lsa_info->dns.name.string) {
2489 if (!strequal(domain->name, lsa_info->dns.name.string))
2491 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2492 "for domain %s claimed it was a DC "
2493 "for domain %s, refusing to "
2494 "initialize\n",
2495 domain->name,
2496 lsa_info->dns.name.string));
2497 TALLOC_FREE(cli);
2498 TALLOC_FREE(mem_ctx);
2499 return;
2501 talloc_free(domain->name);
2502 domain->name = talloc_strdup(domain,
2503 lsa_info->dns.name.string);
2504 if (domain->name == NULL) {
2505 goto done;
2509 if (lsa_info->dns.dns_domain.string) {
2510 if (domain->alt_name != NULL &&
2511 !strequal(domain->alt_name,
2512 lsa_info->dns.dns_domain.string))
2514 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2515 "for domain %s (%s) claimed it was "
2516 "a DC for domain %s, refusing to "
2517 "initialize\n",
2518 domain->alt_name, domain->name,
2519 lsa_info->dns.dns_domain.string));
2520 TALLOC_FREE(cli);
2521 TALLOC_FREE(mem_ctx);
2522 return;
2524 talloc_free(domain->alt_name);
2525 domain->alt_name =
2526 talloc_strdup(domain,
2527 lsa_info->dns.dns_domain.string);
2528 if (domain->alt_name == NULL) {
2529 goto done;
2533 /* See if we can set some domain trust flags about
2534 ourself */
2536 if (lsa_info->dns.dns_forest.string) {
2537 talloc_free(domain->forest_name);
2538 domain->forest_name =
2539 talloc_strdup(domain,
2540 lsa_info->dns.dns_forest.string);
2541 if (domain->forest_name == NULL) {
2542 goto done;
2545 if (strequal(domain->forest_name, domain->alt_name)) {
2546 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2550 if (lsa_info->dns.sid) {
2551 if (!is_null_sid(&domain->sid) &&
2552 !dom_sid_equal(&domain->sid,
2553 lsa_info->dns.sid))
2555 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2556 "for domain %s (%s) claimed it was "
2557 "a DC for domain %s, refusing to "
2558 "initialize\n",
2559 dom_sid_string(talloc_tos(),
2560 &domain->sid),
2561 domain->name,
2562 dom_sid_string(talloc_tos(),
2563 lsa_info->dns.sid)));
2564 TALLOC_FREE(cli);
2565 TALLOC_FREE(mem_ctx);
2566 return;
2568 sid_copy(&domain->sid, lsa_info->dns.sid);
2570 } else {
2571 domain->active_directory = False;
2573 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2574 SEC_FLAG_MAXIMUM_ALLOWED,
2575 &pol);
2577 if (!NT_STATUS_IS_OK(status)) {
2578 goto done;
2581 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2582 &pol,
2583 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2584 &lsa_info,
2585 &result);
2586 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2588 if (lsa_info->account_domain.name.string) {
2589 if (!strequal(domain->name,
2590 lsa_info->account_domain.name.string))
2592 DEBUG(1,
2593 ("set_dc_type_and_flags_connect: "
2594 "DC for domain %s claimed it was"
2595 " a DC for domain %s, refusing "
2596 "to initialize\n", domain->name,
2597 lsa_info->
2598 account_domain.name.string));
2599 TALLOC_FREE(cli);
2600 TALLOC_FREE(mem_ctx);
2601 return;
2603 talloc_free(domain->name);
2604 domain->name =
2605 talloc_strdup(domain,
2606 lsa_info->account_domain.name.string);
2609 if (lsa_info->account_domain.sid) {
2610 if (!is_null_sid(&domain->sid) &&
2611 !dom_sid_equal(&domain->sid,
2612 lsa_info->account_domain.sid))
2614 DEBUG(1,
2615 ("set_dc_type_and_flags_connect: "
2616 "DC for domain %s (%s) claimed "
2617 "it was a DC for domain %s, "
2618 "refusing to initialize\n",
2619 dom_sid_string(talloc_tos(),
2620 &domain->sid),
2621 domain->name,
2622 dom_sid_string(talloc_tos(),
2623 lsa_info->account_domain.sid)));
2624 TALLOC_FREE(cli);
2625 TALLOC_FREE(mem_ctx);
2626 return;
2628 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2632 done:
2634 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2635 domain->name, domain->native_mode ? "" : "NOT "));
2637 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2638 domain->name, domain->active_directory ? "" : "NOT "));
2640 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2642 TALLOC_FREE(cli);
2644 TALLOC_FREE(mem_ctx);
2646 domain->initialized = True;
2649 /**********************************************************************
2650 Set the domain_flags (trust attributes, domain operating modes, etc...
2651 ***********************************************************************/
2653 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2655 if (IS_DC) {
2657 * On a DC we loaded all trusts
2658 * from configuration and never learn
2659 * new domains.
2661 return;
2664 /* we always have to contact our primary domain */
2666 if ( domain->primary || domain->internal) {
2667 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2668 "primary or internal domain\n"));
2669 set_dc_type_and_flags_connect( domain );
2670 return;
2673 /* Use our DC to get the information if possible */
2675 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2676 /* Otherwise, fallback to contacting the
2677 domain directly */
2678 set_dc_type_and_flags_connect( domain );
2681 return;
2686 /**********************************************************************
2687 ***********************************************************************/
2689 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2690 struct netlogon_creds_cli_context **ppdc)
2692 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2693 struct rpc_pipe_client *netlogon_pipe;
2695 *ppdc = NULL;
2697 if ((!IS_DC) && (!domain->primary)) {
2698 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2701 if (domain->conn.netlogon_creds_ctx != NULL) {
2702 *ppdc = domain->conn.netlogon_creds_ctx;
2703 return NT_STATUS_OK;
2706 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2707 if (!NT_STATUS_IS_OK(result)) {
2708 return result;
2711 return NT_STATUS_OK;
2714 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2715 bool need_rw_dc,
2716 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2718 struct winbindd_cm_conn *conn;
2719 NTSTATUS status, result;
2720 struct netlogon_creds_cli_context *p_creds;
2721 struct cli_credentials *creds = NULL;
2722 bool retry = false; /* allow one retry attempt for expired session */
2724 if (sid_check_is_our_sam(&domain->sid)) {
2725 if (domain->rodc == false || need_rw_dc == false) {
2726 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2730 if (IS_AD_DC) {
2732 * In theory we should not use SAMR within
2733 * winbindd at all, but that's a larger task to
2734 * remove this and avoid breaking existing
2735 * setups.
2737 * At least as AD DC we have the restriction
2738 * to avoid SAMR against trusted domains,
2739 * as there're no existing setups.
2741 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2744 retry:
2745 status = init_dc_connection_rpc(domain, need_rw_dc);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 return status;
2750 conn = &domain->conn;
2752 if (rpccli_is_connected(conn->samr_pipe)) {
2753 goto done;
2756 TALLOC_FREE(conn->samr_pipe);
2759 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2760 * sign and sealed pipe using the machine account password by
2761 * preference. If we can't - try schannel, if that fails, try
2762 * anonymous.
2765 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2766 if (!NT_STATUS_IS_OK(result)) {
2767 DEBUG(10, ("cm_connect_sam: No user available for "
2768 "domain %s, trying schannel\n", domain->name));
2769 goto schannel;
2772 if (cli_credentials_is_anonymous(creds)) {
2773 goto anonymous;
2777 * We have an authenticated connection. Use a SPNEGO
2778 * authenticated SAMR pipe with sign & seal.
2780 status = cli_rpc_pipe_open_with_creds(conn->cli,
2781 &ndr_table_samr,
2782 NCACN_NP,
2783 DCERPC_AUTH_TYPE_SPNEGO,
2784 conn->auth_level,
2785 smbXcli_conn_remote_name(conn->cli->conn),
2786 creds,
2787 &conn->samr_pipe);
2789 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2790 && !retry) {
2791 invalidate_cm_connection(domain);
2792 retry = true;
2793 goto retry;
2796 if (!NT_STATUS_IS_OK(status)) {
2797 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2798 "pipe for domain %s using NTLMSSP "
2799 "authenticated pipe: user %s. Error was "
2800 "%s\n", domain->name,
2801 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2802 nt_errstr(status)));
2803 goto schannel;
2806 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2807 "domain %s using NTLMSSP authenticated "
2808 "pipe: user %s\n", domain->name,
2809 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2811 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2812 conn->samr_pipe->desthost,
2813 SEC_FLAG_MAXIMUM_ALLOWED,
2814 &conn->sam_connect_handle,
2815 &result);
2817 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2818 invalidate_cm_connection(domain);
2819 TALLOC_FREE(conn->samr_pipe);
2820 retry = true;
2821 goto retry;
2824 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2825 goto open_domain;
2827 if (NT_STATUS_IS_OK(status)) {
2828 status = result;
2831 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2832 "failed for domain %s, error was %s. Trying schannel\n",
2833 domain->name, nt_errstr(status) ));
2834 TALLOC_FREE(conn->samr_pipe);
2836 schannel:
2838 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2840 status = cm_get_schannel_creds(domain, &p_creds);
2841 if (!NT_STATUS_IS_OK(status)) {
2842 /* If this call fails - conn->cli can now be NULL ! */
2843 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2844 "for domain %s (error %s), trying anon\n",
2845 domain->name,
2846 nt_errstr(status) ));
2847 goto anonymous;
2849 TALLOC_FREE(creds);
2850 status = cli_rpc_pipe_open_schannel_with_creds(
2851 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2852 &conn->samr_pipe);
2854 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2855 && !retry) {
2856 invalidate_cm_connection(domain);
2857 retry = true;
2858 goto retry;
2861 if (!NT_STATUS_IS_OK(status)) {
2862 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2863 "domain %s using schannel. Error was %s\n",
2864 domain->name, nt_errstr(status) ));
2865 goto anonymous;
2867 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2868 "schannel.\n", domain->name ));
2870 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2871 conn->samr_pipe->desthost,
2872 SEC_FLAG_MAXIMUM_ALLOWED,
2873 &conn->sam_connect_handle,
2874 &result);
2876 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2877 invalidate_cm_connection(domain);
2878 TALLOC_FREE(conn->samr_pipe);
2879 retry = true;
2880 goto retry;
2883 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2884 goto open_domain;
2886 if (NT_STATUS_IS_OK(status)) {
2887 status = result;
2889 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2890 "for domain %s, error was %s. Trying anonymous\n",
2891 domain->name, nt_errstr(status) ));
2892 TALLOC_FREE(conn->samr_pipe);
2894 anonymous:
2896 /* Finally fall back to anonymous. */
2897 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2898 status = NT_STATUS_DOWNGRADE_DETECTED;
2899 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2900 "without connection level security, "
2901 "must set 'winbind sealed pipes = false' and "
2902 "'require strong key = false' to proceed: %s\n",
2903 domain->name, nt_errstr(status)));
2904 goto done;
2906 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2907 &conn->samr_pipe);
2909 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2910 && !retry) {
2911 invalidate_cm_connection(domain);
2912 retry = true;
2913 goto retry;
2916 if (!NT_STATUS_IS_OK(status)) {
2917 goto done;
2920 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2921 conn->samr_pipe->desthost,
2922 SEC_FLAG_MAXIMUM_ALLOWED,
2923 &conn->sam_connect_handle,
2924 &result);
2926 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2927 invalidate_cm_connection(domain);
2928 TALLOC_FREE(conn->samr_pipe);
2929 retry = true;
2930 goto retry;
2933 if (!NT_STATUS_IS_OK(status)) {
2934 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2935 "for domain %s Error was %s\n",
2936 domain->name, nt_errstr(status) ));
2937 goto done;
2939 if (!NT_STATUS_IS_OK(result)) {
2940 status = result;
2941 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2942 "for domain %s Error was %s\n",
2943 domain->name, nt_errstr(result)));
2944 goto done;
2947 open_domain:
2948 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2949 mem_ctx,
2950 &conn->sam_connect_handle,
2951 SEC_FLAG_MAXIMUM_ALLOWED,
2952 &domain->sid,
2953 &conn->sam_domain_handle,
2954 &result);
2955 if (!NT_STATUS_IS_OK(status)) {
2956 goto done;
2959 status = result;
2960 done:
2962 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2964 * if we got access denied, we might just have no access rights
2965 * to talk to the remote samr server server (e.g. when we are a
2966 * PDC and we are connecting a w2k8 pdc via an interdomain
2967 * trust). In that case do not invalidate the whole connection
2968 * stack
2970 TALLOC_FREE(conn->samr_pipe);
2971 ZERO_STRUCT(conn->sam_domain_handle);
2972 return status;
2973 } else if (!NT_STATUS_IS_OK(status)) {
2974 invalidate_cm_connection(domain);
2975 return status;
2978 *cli = conn->samr_pipe;
2979 *sam_handle = conn->sam_domain_handle;
2980 return status;
2983 /**********************************************************************
2984 open an schanneld ncacn_ip_tcp connection to LSA
2985 ***********************************************************************/
2987 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2988 TALLOC_CTX *mem_ctx,
2989 struct rpc_pipe_client **cli)
2991 struct winbindd_cm_conn *conn;
2992 struct netlogon_creds_cli_context *p_creds = NULL;
2993 NTSTATUS status;
2995 DEBUG(10,("cm_connect_lsa_tcp\n"));
2997 status = init_dc_connection_rpc(domain, false);
2998 if (!NT_STATUS_IS_OK(status)) {
2999 return status;
3002 conn = &domain->conn;
3005 * rpccli_is_connected handles more error cases
3007 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
3008 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
3009 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
3010 goto done;
3013 TALLOC_FREE(conn->lsa_pipe_tcp);
3015 status = cm_get_schannel_creds(domain, &p_creds);
3016 if (!NT_STATUS_IS_OK(status)) {
3017 goto done;
3020 status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
3021 &ndr_table_lsarpc,
3022 NCACN_IP_TCP,
3023 p_creds,
3024 &conn->lsa_pipe_tcp);
3025 if (!NT_STATUS_IS_OK(status)) {
3026 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
3027 nt_errstr(status)));
3028 goto done;
3031 done:
3032 if (!NT_STATUS_IS_OK(status)) {
3033 TALLOC_FREE(conn->lsa_pipe_tcp);
3034 return status;
3037 *cli = conn->lsa_pipe_tcp;
3039 return status;
3042 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
3043 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
3045 struct winbindd_cm_conn *conn;
3046 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
3047 struct netlogon_creds_cli_context *p_creds;
3048 struct cli_credentials *creds = NULL;
3049 bool retry = false; /* allow one retry attempt for expired session */
3051 retry:
3052 result = init_dc_connection_rpc(domain, false);
3053 if (!NT_STATUS_IS_OK(result))
3054 return result;
3056 conn = &domain->conn;
3058 if (rpccli_is_connected(conn->lsa_pipe)) {
3059 goto done;
3062 TALLOC_FREE(conn->lsa_pipe);
3064 if (IS_AD_DC) {
3066 * Make sure we only use schannel as AD DC.
3068 goto schannel;
3071 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
3072 if (!NT_STATUS_IS_OK(result)) {
3073 DEBUG(10, ("cm_connect_lsa: No user available for "
3074 "domain %s, trying schannel\n", domain->name));
3075 goto schannel;
3078 if (cli_credentials_is_anonymous(creds)) {
3079 goto anonymous;
3083 * We have an authenticated connection. Use a SPNEGO
3084 * authenticated LSA pipe with sign & seal.
3086 result = cli_rpc_pipe_open_with_creds
3087 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
3088 DCERPC_AUTH_TYPE_SPNEGO,
3089 conn->auth_level,
3090 smbXcli_conn_remote_name(conn->cli->conn),
3091 creds,
3092 &conn->lsa_pipe);
3094 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3095 && !retry) {
3096 invalidate_cm_connection(domain);
3097 retry = true;
3098 goto retry;
3101 if (!NT_STATUS_IS_OK(result)) {
3102 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3103 "domain %s using NTLMSSP authenticated pipe: user "
3104 "%s. Error was %s. Trying schannel.\n",
3105 domain->name,
3106 cli_credentials_get_unparsed_name(creds, talloc_tos()),
3107 nt_errstr(result)));
3108 goto schannel;
3111 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3112 "NTLMSSP authenticated pipe: user %s\n",
3113 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3115 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3116 SEC_FLAG_MAXIMUM_ALLOWED,
3117 &conn->lsa_policy);
3118 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3119 invalidate_cm_connection(domain);
3120 TALLOC_FREE(conn->lsa_pipe);
3121 retry = true;
3122 goto retry;
3125 if (NT_STATUS_IS_OK(result)) {
3126 goto done;
3129 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3130 "schannel\n"));
3132 TALLOC_FREE(conn->lsa_pipe);
3134 schannel:
3136 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3138 result = cm_get_schannel_creds(domain, &p_creds);
3139 if (!NT_STATUS_IS_OK(result)) {
3140 /* If this call fails - conn->cli can now be NULL ! */
3141 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3142 "for domain %s (error %s), trying anon\n",
3143 domain->name,
3144 nt_errstr(result) ));
3145 goto anonymous;
3148 TALLOC_FREE(creds);
3149 result = cli_rpc_pipe_open_schannel_with_creds(
3150 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3151 &conn->lsa_pipe);
3153 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3154 && !retry) {
3155 invalidate_cm_connection(domain);
3156 retry = true;
3157 goto retry;
3160 if (!NT_STATUS_IS_OK(result)) {
3161 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3162 "domain %s using schannel. Error was %s\n",
3163 domain->name, nt_errstr(result) ));
3164 goto anonymous;
3166 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3167 "schannel.\n", domain->name ));
3169 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3170 SEC_FLAG_MAXIMUM_ALLOWED,
3171 &conn->lsa_policy);
3173 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3174 invalidate_cm_connection(domain);
3175 TALLOC_FREE(conn->lsa_pipe);
3176 retry = true;
3177 goto retry;
3180 if (NT_STATUS_IS_OK(result)) {
3181 goto done;
3184 if (IS_AD_DC) {
3186 * Make sure we only use schannel as AD DC.
3188 goto done;
3191 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3192 "anonymous\n"));
3194 TALLOC_FREE(conn->lsa_pipe);
3196 anonymous:
3198 if (IS_AD_DC) {
3200 * Make sure we only use schannel as AD DC.
3202 goto done;
3205 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3206 result = NT_STATUS_DOWNGRADE_DETECTED;
3207 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3208 "without connection level security, "
3209 "must set 'winbind sealed pipes = false' and "
3210 "'require strong key = false' to proceed: %s\n",
3211 domain->name, nt_errstr(result)));
3212 goto done;
3215 result = cli_rpc_pipe_open_noauth(conn->cli,
3216 &ndr_table_lsarpc,
3217 &conn->lsa_pipe);
3219 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3220 && !retry) {
3221 invalidate_cm_connection(domain);
3222 retry = true;
3223 goto retry;
3226 if (!NT_STATUS_IS_OK(result)) {
3227 goto done;
3230 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3231 SEC_FLAG_MAXIMUM_ALLOWED,
3232 &conn->lsa_policy);
3234 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3235 invalidate_cm_connection(domain);
3236 TALLOC_FREE(conn->lsa_pipe);
3237 retry = true;
3238 goto retry;
3241 done:
3242 if (!NT_STATUS_IS_OK(result)) {
3243 invalidate_cm_connection(domain);
3244 return result;
3247 *cli = conn->lsa_pipe;
3248 *lsa_policy = conn->lsa_policy;
3249 return result;
3252 /****************************************************************************
3253 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3254 ****************************************************************************/
3256 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3257 TALLOC_CTX *mem_ctx,
3258 struct rpc_pipe_client **cli,
3259 struct policy_handle *lsa_policy)
3261 NTSTATUS status;
3263 if (domain->can_do_ncacn_ip_tcp) {
3264 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3265 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3266 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3267 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3268 invalidate_cm_connection(domain);
3269 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3271 if (NT_STATUS_IS_OK(status)) {
3272 return status;
3276 * we tried twice to connect via ncan_ip_tcp and schannel and
3277 * failed - maybe it is a trusted domain we can't connect to ?
3278 * do not try tcp next time - gd
3280 * This also prevents NETLOGON over TCP
3282 domain->can_do_ncacn_ip_tcp = false;
3285 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3287 return status;
3290 /****************************************************************************
3291 Open the netlogon pipe to this DC.
3292 ****************************************************************************/
3294 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3295 enum dcerpc_transport_t transport,
3296 struct rpc_pipe_client **cli)
3298 struct messaging_context *msg_ctx = global_messaging_context();
3299 struct winbindd_cm_conn *conn;
3300 NTSTATUS result;
3301 enum netr_SchannelType sec_chan_type;
3302 struct cli_credentials *creds = NULL;
3304 *cli = NULL;
3306 if (IS_AD_DC) {
3307 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3309 * Make sure we don't even try to
3310 * connect to a foreign domain
3311 * without a direct outbound trust.
3313 return NT_STATUS_NO_TRUST_LSA_SECRET;
3317 result = init_dc_connection_rpc(domain, domain->rodc);
3318 if (!NT_STATUS_IS_OK(result)) {
3319 return result;
3322 conn = &domain->conn;
3324 if (rpccli_is_connected(conn->netlogon_pipe)) {
3325 *cli = conn->netlogon_pipe;
3326 return NT_STATUS_OK;
3329 TALLOC_FREE(conn->netlogon_pipe);
3330 TALLOC_FREE(conn->netlogon_creds_ctx);
3332 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3333 if (!NT_STATUS_IS_OK(result)) {
3334 DBG_DEBUG("No user available for domain %s when trying "
3335 "schannel\n", domain->name);
3336 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3339 if (cli_credentials_is_anonymous(creds)) {
3340 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3341 "unable to make get NETLOGON credentials\n",
3342 domain->name);
3343 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3346 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3347 if (sec_chan_type == SEC_CHAN_NULL) {
3348 if (transport == NCACN_IP_TCP) {
3349 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3350 "for %s, deny NCACN_IP_TCP and let the "
3351 "caller fallback to NCACN_NP.\n",
3352 domain->name);
3353 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3356 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3357 "fallback to noauth on NCACN_NP.\n",
3358 domain->name);
3360 result = cli_rpc_pipe_open_noauth_transport(
3361 conn->cli,
3362 transport,
3363 &ndr_table_netlogon,
3364 &conn->netlogon_pipe);
3365 if (!NT_STATUS_IS_OK(result)) {
3366 invalidate_cm_connection(domain);
3367 return result;
3370 *cli = conn->netlogon_pipe;
3371 return NT_STATUS_OK;
3374 result = rpccli_create_netlogon_creds_ctx(creds,
3375 domain->dcname,
3376 msg_ctx,
3377 domain,
3378 &conn->netlogon_creds_ctx);
3379 if (!NT_STATUS_IS_OK(result)) {
3380 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3381 "unable to create NETLOGON credentials: %s\n",
3382 domain->name, nt_errstr(result)));
3383 return result;
3386 result = rpccli_connect_netlogon(
3387 conn->cli, transport,
3388 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3389 &conn->netlogon_pipe);
3390 conn->netlogon_force_reauth = false;
3391 if (!NT_STATUS_IS_OK(result)) {
3392 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3393 nt_errstr(result));
3394 return result;
3397 *cli = conn->netlogon_pipe;
3398 return NT_STATUS_OK;
3401 /****************************************************************************
3402 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3403 ****************************************************************************/
3405 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3406 struct rpc_pipe_client **cli)
3408 NTSTATUS status;
3410 status = init_dc_connection_rpc(domain, domain->rodc);
3411 if (!NT_STATUS_IS_OK(status)) {
3412 return status;
3415 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3416 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3417 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3418 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3419 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3420 invalidate_cm_connection(domain);
3421 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3423 if (NT_STATUS_IS_OK(status)) {
3424 return status;
3428 * we tried twice to connect via ncan_ip_tcp and schannel and
3429 * failed - maybe it is a trusted domain we can't connect to ?
3430 * do not try tcp next time - gd
3432 * This also prevents LSA over TCP
3434 domain->can_do_ncacn_ip_tcp = false;
3437 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3438 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3440 * SMB2 session expired, needs reauthentication. Drop
3441 * connection and retry.
3443 invalidate_cm_connection(domain);
3444 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3447 return status;
3450 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3451 struct rpc_pipe_client **cli,
3452 struct netlogon_creds_cli_context **ppdc)
3454 NTSTATUS status;
3456 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3457 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3460 status = cm_connect_netlogon(domain, cli);
3461 if (!NT_STATUS_IS_OK(status)) {
3462 return status;
3465 if (domain->conn.netlogon_creds_ctx == NULL) {
3466 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3469 *ppdc = domain->conn.netlogon_creds_ctx;
3470 return NT_STATUS_OK;
3473 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3474 void *private_data,
3475 uint32_t msg_type,
3476 struct server_id server_id,
3477 DATA_BLOB *data)
3479 struct winbindd_domain *domain;
3480 char *freeit = NULL;
3481 char *addr;
3483 if ((data == NULL)
3484 || (data->data == NULL)
3485 || (data->length == 0)
3486 || (data->data[data->length-1] != '\0')) {
3487 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3488 "string\n"));
3489 return;
3492 addr = (char *)data->data;
3493 DEBUG(10, ("IP %s dropped\n", addr));
3495 if (!is_ipaddress(addr)) {
3496 char *slash;
3498 * Some code sends us ip addresses with the /netmask
3499 * suffix
3501 slash = strchr(addr, '/');
3502 if (slash == NULL) {
3503 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3504 addr));
3505 return;
3507 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3508 if (freeit == NULL) {
3509 DEBUG(1, ("talloc failed\n"));
3510 return;
3512 addr = freeit;
3513 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3516 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3517 char sockaddr[INET6_ADDRSTRLEN];
3519 if (!cli_state_is_connected(domain->conn.cli)) {
3520 continue;
3523 print_sockaddr(sockaddr, sizeof(sockaddr),
3524 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3526 if (strequal(sockaddr, addr)) {
3527 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3530 TALLOC_FREE(freeit);
3533 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3534 void *private_data,
3535 uint32_t msg_type,
3536 struct server_id server_id,
3537 DATA_BLOB *data)
3539 struct winbindd_domain *domain;
3541 for (domain = domain_list(); domain; domain = domain->next) {
3542 if (domain->internal) {
3543 continue;
3545 invalidate_cm_connection(domain);