tests/krb5: Fix method for creating invalid length zeroed checksum
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob5fb22d7e9c8a6faf71db1f64123d0229905a36f3
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 validate the connection
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_INVALID_COMPUTER_NAME)
1177 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
1178 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1179 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1181 if (!cm_is_ipc_credentials(creds)) {
1182 goto ipc_fallback;
1185 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1186 goto done;
1189 goto anon_fallback;
1192 goto done;
1194 ipc_fallback:
1195 TALLOC_FREE(creds);
1196 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1197 if (!NT_STATUS_IS_OK(tmp_status)) {
1198 result = tmp_status;
1199 goto done;
1202 if (cli_credentials_is_anonymous(creds)) {
1203 goto anon_fallback;
1206 machine_account = cli_credentials_get_username(creds);
1207 machine_domain = cli_credentials_get_domain(creds);
1209 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1210 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1211 machine_domain, machine_account));
1213 result = cli_session_setup_creds(*cli, creds);
1214 if (NT_STATUS_IS_OK(result)) {
1215 goto session_setup_done;
1218 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1219 controller,
1220 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1221 nt_errstr(result)));
1224 * If we are not going to validate the connection
1225 * with SMB signing, then allow us to fall back to
1226 * anonymous
1228 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1229 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1230 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1231 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
1232 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
1233 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1234 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1236 goto anon_fallback;
1239 goto done;
1241 anon_fallback:
1242 TALLOC_FREE(creds);
1244 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1245 goto done;
1248 /* Fall back to anonymous connection, this might fail later */
1249 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1250 "connection for DC %s\n",
1251 controller ));
1253 result = cli_session_setup_anon(*cli);
1254 if (NT_STATUS_IS_OK(result)) {
1255 DEBUG(5, ("Connected anonymously\n"));
1256 goto session_setup_done;
1259 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1260 controller, nt_errstr(result)));
1262 /* We can't session setup */
1263 goto done;
1265 session_setup_done:
1266 TALLOC_FREE(creds);
1269 * This should be a short term hack until
1270 * dynamic re-authentication is implemented.
1272 * See Bug 9175 - winbindd doesn't recover from
1273 * NT_STATUS_NETWORK_SESSION_EXPIRED
1275 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1276 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1279 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1280 if (!NT_STATUS_IS_OK(result)) {
1281 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1282 goto done;
1284 tcon_status = result;
1286 /* cache the server name for later connections */
1288 saf_store(domain->name, controller);
1289 if (domain->alt_name) {
1290 saf_store(domain->alt_name, controller);
1293 winbindd_set_locator_kdc_envs(domain);
1295 TALLOC_FREE(mutex);
1296 *retry = False;
1298 result = NT_STATUS_OK;
1300 done:
1301 TALLOC_FREE(mutex);
1302 TALLOC_FREE(creds);
1304 if (NT_STATUS_IS_OK(result)) {
1305 result = tcon_status;
1308 if (!NT_STATUS_IS_OK(result)) {
1309 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1310 controller, nt_errstr(result)));
1311 winbind_add_failed_connection_entry(domain, controller, result);
1312 if ((*cli) != NULL) {
1313 cli_shutdown(*cli);
1314 *cli = NULL;
1318 return result;
1321 /*******************************************************************
1322 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1323 array.
1325 Keeps the list unique by not adding duplicate entries.
1327 @param[in] mem_ctx talloc memory context to allocate from
1328 @param[in] domain_name domain of the DC
1329 @param[in] dcname name of the DC to add to the list
1330 @param[in] pss Internet address and port pair to add to the list
1331 @param[in,out] dcs array of dc_name_ip structures to add to
1332 @param[in,out] num_dcs number of dcs returned in the dcs array
1333 @return true if the list was added to, false otherwise
1334 *******************************************************************/
1336 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1337 const char *dcname, struct sockaddr_storage *pss,
1338 struct dc_name_ip **dcs, int *num)
1340 int i = 0;
1342 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1343 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1344 return False;
1347 /* Make sure there's no duplicates in the list */
1348 for (i=0; i<*num; i++)
1349 if (sockaddr_equal(
1350 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1351 (struct sockaddr *)(void *)pss))
1352 return False;
1354 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1356 if (*dcs == NULL)
1357 return False;
1359 fstrcpy((*dcs)[*num].name, dcname);
1360 (*dcs)[*num].ss = *pss;
1361 *num += 1;
1362 return True;
1365 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1366 struct sockaddr_storage *pss, uint16_t port,
1367 struct sockaddr_storage **addrs, int *num)
1369 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1371 if (*addrs == NULL) {
1372 *num = 0;
1373 return False;
1376 (*addrs)[*num] = *pss;
1377 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1379 *num += 1;
1380 return True;
1383 /*******************************************************************
1384 convert an ip to a name
1385 For an AD Domain, it checks the requirements of the request flags.
1386 *******************************************************************/
1388 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1389 const struct winbindd_domain *domain,
1390 struct sockaddr_storage *pss,
1391 char **name, uint32_t request_flags)
1393 struct ip_service ip_list;
1394 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1395 NTSTATUS status;
1396 const char *dc_name;
1397 fstring nbtname;
1398 #ifdef HAVE_ADS
1399 bool is_ad_domain = false;
1400 #endif
1401 ip_list.ss = *pss;
1402 ip_list.port = 0;
1404 #ifdef HAVE_ADS
1405 /* For active directory servers, try to get the ldap server name.
1406 None of these failures should be considered critical for now */
1408 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1409 is_ad_domain = true;
1410 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1411 is_ad_domain = domain->active_directory;
1414 if (is_ad_domain) {
1415 ADS_STRUCT *ads;
1416 ADS_STATUS ads_status;
1417 char addr[INET6_ADDRSTRLEN];
1419 print_sockaddr(addr, sizeof(addr), pss);
1421 ads = ads_init(domain->alt_name,
1422 domain->name,
1423 addr,
1424 ADS_SASL_PLAIN);
1425 ads->auth.flags |= ADS_AUTH_NO_BIND;
1426 ads->config.flags |= request_flags;
1427 ads->server.no_fallback = true;
1429 ads_status = ads_connect(ads);
1430 if (ADS_ERR_OK(ads_status)) {
1431 /* We got a cldap packet. */
1432 *name = talloc_strdup(mem_ctx,
1433 ads->config.ldap_server_name);
1434 if (*name == NULL) {
1435 return false;
1437 namecache_store(*name, 0x20, 1, &ip_list);
1439 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1441 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1442 if (ads_closest_dc(ads)) {
1443 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1445 /* We're going to use this KDC for this realm/domain.
1446 If we are using sites, then force the krb5 libs
1447 to use this KDC. */
1449 create_local_private_krb5_conf_for_domain(domain->alt_name,
1450 domain->name,
1451 sitename,
1452 pss);
1454 TALLOC_FREE(sitename);
1455 } else {
1456 /* use an off site KDC */
1457 create_local_private_krb5_conf_for_domain(domain->alt_name,
1458 domain->name,
1459 NULL,
1460 pss);
1462 winbindd_set_locator_kdc_envs(domain);
1464 /* Ensure we contact this DC also. */
1465 saf_store(domain->name, *name);
1466 saf_store(domain->alt_name, *name);
1469 ads_destroy( &ads );
1470 return True;
1473 ads_destroy( &ads );
1474 return false;
1476 #endif
1479 size_t len = strlen(lp_netbios_name());
1480 char my_acct_name[len+2];
1482 snprintf(my_acct_name,
1483 sizeof(my_acct_name),
1484 "%s$",
1485 lp_netbios_name());
1487 status = nbt_getdc(global_messaging_context(), 10, pss,
1488 domain->name, &domain->sid,
1489 my_acct_name, ACB_WSTRUST,
1490 nt_version, mem_ctx, &nt_version,
1491 &dc_name, NULL);
1493 if (NT_STATUS_IS_OK(status)) {
1494 *name = talloc_strdup(mem_ctx, dc_name);
1495 if (*name == NULL) {
1496 return false;
1498 namecache_store(*name, 0x20, 1, &ip_list);
1499 return True;
1502 /* try node status request */
1504 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1505 namecache_store(nbtname, 0x20, 1, &ip_list);
1507 if (name != NULL) {
1508 *name = talloc_strdup(mem_ctx, nbtname);
1509 if (*name == NULL) {
1510 return false;
1514 return true;
1516 return False;
1519 /*******************************************************************
1520 Retrieve a list of IP addresses for domain controllers.
1522 The array is sorted in the preferred connection order.
1524 @param[in] mem_ctx talloc memory context to allocate from
1525 @param[in] domain domain to retrieve DCs for
1526 @param[out] dcs array of dcs that will be returned
1527 @param[out] num_dcs number of dcs returned in the dcs array
1528 @return always true
1529 *******************************************************************/
1531 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1532 struct dc_name_ip **dcs, int *num_dcs,
1533 uint32_t request_flags)
1535 fstring dcname;
1536 struct sockaddr_storage ss;
1537 struct ip_service *ip_list = NULL;
1538 int iplist_size = 0;
1539 int i;
1540 bool is_our_domain;
1541 enum security_types sec = (enum security_types)lp_security();
1543 is_our_domain = strequal(domain->name, lp_workgroup());
1545 /* If not our domain, get the preferred DC, by asking our primary DC */
1546 if ( !is_our_domain
1547 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1548 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1549 num_dcs) )
1551 char addr[INET6_ADDRSTRLEN];
1552 print_sockaddr(addr, sizeof(addr), &ss);
1553 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1554 dcname, addr));
1555 return True;
1558 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1559 char *sitename = NULL;
1561 /* We need to make sure we know the local site before
1562 doing any DNS queries, as this will restrict the
1563 get_sorted_dc_list() call below to only fetching
1564 DNS records for the correct site. */
1566 /* Find any DC to get the site record.
1567 We deliberately don't care about the
1568 return here. */
1570 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1572 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1573 if (sitename) {
1575 /* Do the site-specific AD dns lookup first. */
1576 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1577 &iplist_size, True);
1579 /* Add ips to the DC array. We don't look up the name
1580 of the DC in this function, but we fill in the char*
1581 of the ip now to make the failed connection cache
1582 work */
1583 for ( i=0; i<iplist_size; i++ ) {
1584 char addr[INET6_ADDRSTRLEN];
1585 print_sockaddr(addr, sizeof(addr),
1586 &ip_list[i].ss);
1587 add_one_dc_unique(mem_ctx,
1588 domain->name,
1589 addr,
1590 &ip_list[i].ss,
1591 dcs,
1592 num_dcs);
1595 SAFE_FREE(ip_list);
1596 TALLOC_FREE(sitename);
1597 iplist_size = 0;
1600 /* Now we add DCs from the main AD DNS lookup. */
1601 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1602 &iplist_size, True);
1604 for ( i=0; i<iplist_size; i++ ) {
1605 char addr[INET6_ADDRSTRLEN];
1606 print_sockaddr(addr, sizeof(addr),
1607 &ip_list[i].ss);
1608 add_one_dc_unique(mem_ctx,
1609 domain->name,
1610 addr,
1611 &ip_list[i].ss,
1612 dcs,
1613 num_dcs);
1616 SAFE_FREE(ip_list);
1617 iplist_size = 0;
1620 /* Try standard netbios queries if no ADS and fall back to DNS queries
1621 * if alt_name is available */
1622 if (*num_dcs == 0) {
1623 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1624 false);
1625 if (iplist_size == 0) {
1626 if (domain->alt_name != NULL) {
1627 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1628 &iplist_size, true);
1632 for ( i=0; i<iplist_size; i++ ) {
1633 char addr[INET6_ADDRSTRLEN];
1634 print_sockaddr(addr, sizeof(addr),
1635 &ip_list[i].ss);
1636 add_one_dc_unique(mem_ctx,
1637 domain->name,
1638 addr,
1639 &ip_list[i].ss,
1640 dcs,
1641 num_dcs);
1644 SAFE_FREE(ip_list);
1645 iplist_size = 0;
1648 return True;
1651 /*******************************************************************
1652 Find and make a connection to a DC in the given domain.
1654 @param[in] mem_ctx talloc memory context to allocate from
1655 @param[in] domain domain to find a dc in
1656 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1657 @param[out] pss DC Internet address and port
1658 @param[out] fd fd of the open socket connected to the newly found dc
1659 @return true when a DC connection is made, false otherwise
1660 *******************************************************************/
1662 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1663 struct winbindd_domain *domain,
1664 char **dcname, struct sockaddr_storage *pss, int *fd,
1665 uint32_t request_flags)
1667 struct dc_name_ip *dcs = NULL;
1668 int num_dcs = 0;
1670 const char **dcnames = NULL;
1671 size_t num_dcnames = 0;
1673 struct sockaddr_storage *addrs = NULL;
1674 int num_addrs = 0;
1676 int i;
1677 size_t fd_index;
1679 NTSTATUS status;
1681 *fd = -1;
1683 again:
1684 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1685 return False;
1687 for (i=0; i<num_dcs; i++) {
1689 if (!add_string_to_array(mem_ctx, dcs[i].name,
1690 &dcnames, &num_dcnames)) {
1691 return False;
1693 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1694 &addrs, &num_addrs)) {
1695 return False;
1699 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1700 return False;
1702 if ((addrs == NULL) || (dcnames == NULL))
1703 return False;
1705 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1706 num_addrs, 0, 10, fd, &fd_index, NULL);
1707 if (!NT_STATUS_IS_OK(status)) {
1708 for (i=0; i<num_dcs; i++) {
1709 char ab[INET6_ADDRSTRLEN];
1710 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1711 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1712 "domain %s address %s. Error was %s\n",
1713 domain->name, ab, nt_errstr(status) ));
1714 winbind_add_failed_connection_entry(domain,
1715 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1717 return False;
1720 *pss = addrs[fd_index];
1722 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1723 /* Ok, we've got a name for the DC */
1724 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1725 if (*dcname == NULL) {
1726 return false;
1728 return true;
1731 /* Try to figure out the name */
1732 if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1733 return True;
1736 /* We can not continue without the DC's name */
1737 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1738 NT_STATUS_UNSUCCESSFUL);
1740 /* Throw away all arrays as we're doing this again. */
1741 TALLOC_FREE(dcs);
1742 num_dcs = 0;
1744 TALLOC_FREE(dcnames);
1745 num_dcnames = 0;
1747 TALLOC_FREE(addrs);
1748 num_addrs = 0;
1750 if (*fd != -1) {
1751 close(*fd);
1752 *fd = -1;
1755 goto again;
1758 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1760 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1761 domain_name);
1764 static void store_current_dc_in_gencache(const char *domain_name,
1765 const char *dc_name,
1766 struct cli_state *cli)
1768 char addr[INET6_ADDRSTRLEN];
1769 char *key = NULL;
1770 char *value = NULL;
1772 if (!cli_state_is_connected(cli)) {
1773 return;
1776 print_sockaddr(addr, sizeof(addr),
1777 smbXcli_conn_remote_sockaddr(cli->conn));
1779 key = current_dc_key(talloc_tos(), domain_name);
1780 if (key == NULL) {
1781 goto done;
1784 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1785 if (value == NULL) {
1786 goto done;
1789 gencache_set(key, value, 0x7fffffff);
1790 done:
1791 TALLOC_FREE(value);
1792 TALLOC_FREE(key);
1795 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1796 const char *domain_name,
1797 char **p_dc_name, char **p_dc_ip)
1799 char *key, *p;
1800 char *value = NULL;
1801 bool ret = false;
1802 char *dc_name = NULL;
1803 char *dc_ip = NULL;
1805 key = current_dc_key(talloc_tos(), domain_name);
1806 if (key == NULL) {
1807 goto done;
1809 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1810 goto done;
1812 p = strchr(value, ' ');
1813 if (p == NULL) {
1814 goto done;
1816 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1817 if (dc_ip == NULL) {
1818 goto done;
1820 dc_name = talloc_strdup(mem_ctx, p+1);
1821 if (dc_name == NULL) {
1822 goto done;
1825 if (p_dc_ip != NULL) {
1826 *p_dc_ip = dc_ip;
1827 dc_ip = NULL;
1829 if (p_dc_name != NULL) {
1830 *p_dc_name = dc_name;
1831 dc_name = NULL;
1833 ret = true;
1834 done:
1835 TALLOC_FREE(dc_name);
1836 TALLOC_FREE(dc_ip);
1837 TALLOC_FREE(key);
1838 TALLOC_FREE(value);
1839 return ret;
1842 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1843 const struct ndr_interface_table *table,
1844 struct rpc_pipe_client **ret_pipe)
1846 struct rpc_pipe_client *cli = NULL;
1847 const struct auth_session_info *session_info;
1848 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1851 session_info = get_session_info_system();
1852 SMB_ASSERT(session_info != NULL);
1854 /* create a connection to the specified pipe */
1855 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1856 status = rpc_pipe_open_interface(mem_ctx,
1857 table,
1858 session_info,
1859 NULL,
1860 NULL,
1861 global_messaging_context(),
1862 &cli);
1863 } else {
1864 status = rpc_pipe_open_internal(mem_ctx,
1865 table,
1866 session_info,
1867 NULL,
1868 NULL,
1869 global_messaging_context(),
1870 &cli);
1872 if (!NT_STATUS_IS_OK(status)) {
1873 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1874 table->name, nt_errstr(status)));
1875 return status;
1878 if (ret_pipe) {
1879 *ret_pipe = cli;
1882 return NT_STATUS_OK;
1885 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1886 struct winbindd_cm_conn *new_conn,
1887 bool need_rw_dc)
1889 TALLOC_CTX *mem_ctx;
1890 NTSTATUS result;
1891 char *saf_servername;
1892 int retries;
1893 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1895 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1896 set_domain_offline(domain);
1897 return NT_STATUS_NO_MEMORY;
1900 saf_servername = saf_fetch(mem_ctx, domain->name );
1902 /* we have to check the server affinity cache here since
1903 later we select a DC based on response time and not preference */
1905 /* Check the negative connection cache
1906 before talking to it. It going down may have
1907 triggered the reconnection. */
1909 if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1910 struct sockaddr_storage ss;
1911 char *dcname = NULL;
1912 bool resolved = true;
1914 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1915 saf_servername, domain->name));
1917 /* convert an ip address to a name */
1918 if (is_ipaddress(saf_servername)) {
1919 if (!interpret_string_addr(&ss, saf_servername,
1920 AI_NUMERICHOST)) {
1921 TALLOC_FREE(mem_ctx);
1922 return NT_STATUS_UNSUCCESSFUL;
1924 } else {
1925 if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1926 resolved = false;
1930 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1931 domain->dcname = talloc_strdup(domain,
1932 dcname);
1933 if (domain->dcname == NULL) {
1934 TALLOC_FREE(mem_ctx);
1935 return NT_STATUS_NO_MEMORY;
1938 domain->dcaddr = ss;
1939 } else {
1940 winbind_add_failed_connection_entry(domain, saf_servername,
1941 NT_STATUS_UNSUCCESSFUL);
1945 for (retries = 0; retries < 3; retries++) {
1946 int fd = -1;
1947 bool retry = False;
1948 char *dcname = NULL;
1950 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1952 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1953 domain->dcname ? domain->dcname : "", domain->name));
1955 if (domain->dcname != NULL &&
1956 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1957 domain->dcname)))
1959 NTSTATUS status;
1961 status = smbsock_connect(&domain->dcaddr, 0,
1962 NULL, -1, NULL, -1,
1963 &fd, NULL, 10);
1964 if (!NT_STATUS_IS_OK(status)) {
1965 fd = -1;
1969 if ((fd == -1) &&
1970 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1972 /* This is the one place where we will
1973 set the global winbindd offline state
1974 to true, if a "WINBINDD_OFFLINE" entry
1975 is found in the winbindd cache. */
1976 set_global_winbindd_state_offline();
1977 break;
1979 if (dcname != NULL) {
1980 talloc_free(domain->dcname);
1982 domain->dcname = talloc_move(domain, &dcname);
1983 if (domain->dcname == NULL) {
1984 result = NT_STATUS_NO_MEMORY;
1985 break;
1989 new_conn->cli = NULL;
1991 result = cm_prepare_connection(domain, fd, domain->dcname,
1992 &new_conn->cli, &retry);
1993 if (!NT_STATUS_IS_OK(result)) {
1994 /* Don't leak the smb connection socket */
1995 if (fd != -1) {
1996 close(fd);
1997 fd = -1;
2001 if (!retry)
2002 break;
2005 if (NT_STATUS_IS_OK(result)) {
2006 bool seal_pipes = true;
2008 winbindd_set_locator_kdc_envs(domain);
2010 if (domain->online == False) {
2011 /* We're changing state from offline to online. */
2012 set_global_winbindd_state_online();
2014 set_domain_online(domain);
2017 * Much as I hate global state, this seems to be the point
2018 * where we can be certain that we have a proper connection to
2019 * a DC. wbinfo --dc-info needs that information, store it in
2020 * gencache with a looong timeout. This will need revisiting
2021 * once we start to connect to multiple DCs, wbcDcInfo is
2022 * already prepared for that.
2024 store_current_dc_in_gencache(domain->name, domain->dcname,
2025 new_conn->cli);
2027 seal_pipes = lp_winbind_sealed_pipes();
2028 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2029 domain->name,
2030 seal_pipes);
2032 if (seal_pipes) {
2033 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2034 } else {
2035 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2037 } else {
2038 /* Ensure we setup the retry handler. */
2039 set_domain_offline(domain);
2042 talloc_destroy(mem_ctx);
2043 return result;
2046 /* Close down all open pipes on a connection. */
2048 void invalidate_cm_connection(struct winbindd_domain *domain)
2050 NTSTATUS result;
2051 struct winbindd_cm_conn *conn = &domain->conn;
2053 /* We're closing down a possibly dead
2054 connection. Don't have impossibly long (10s) timeouts. */
2056 if (conn->cli) {
2057 cli_set_timeout(conn->cli, 1000); /* 1 second. */
2060 if (conn->samr_pipe != NULL) {
2061 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
2062 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
2063 talloc_tos(),
2064 &conn->sam_connect_handle,
2065 &result);
2067 TALLOC_FREE(conn->samr_pipe);
2068 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2069 if (conn->cli) {
2070 cli_set_timeout(conn->cli, 500);
2074 if (conn->lsa_pipe != NULL) {
2075 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2076 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2077 talloc_tos(),
2078 &conn->lsa_policy,
2079 &result);
2081 TALLOC_FREE(conn->lsa_pipe);
2082 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2083 if (conn->cli) {
2084 cli_set_timeout(conn->cli, 500);
2088 if (conn->lsa_pipe_tcp != NULL) {
2089 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2090 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2091 talloc_tos(),
2092 &conn->lsa_policy,
2093 &result);
2095 TALLOC_FREE(conn->lsa_pipe_tcp);
2096 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2097 if (conn->cli) {
2098 cli_set_timeout(conn->cli, 500);
2102 if (conn->netlogon_pipe != NULL) {
2103 TALLOC_FREE(conn->netlogon_pipe);
2104 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2105 if (conn->cli) {
2106 cli_set_timeout(conn->cli, 500);
2110 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2111 TALLOC_FREE(conn->netlogon_creds_ctx);
2113 if (conn->cli) {
2114 cli_shutdown(conn->cli);
2117 conn->cli = NULL;
2120 void close_conns_after_fork(void)
2122 struct winbindd_domain *domain;
2123 struct winbindd_cli_state *cli_state;
2125 for (domain = domain_list(); domain; domain = domain->next) {
2127 * first close the low level SMB TCP connection
2128 * so that we don't generate any SMBclose
2129 * requests in invalidate_cm_connection()
2131 if (cli_state_is_connected(domain->conn.cli)) {
2132 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2135 invalidate_cm_connection(domain);
2138 for (cli_state = winbindd_client_list();
2139 cli_state != NULL;
2140 cli_state = cli_state->next) {
2141 if (cli_state->sock >= 0) {
2142 close(cli_state->sock);
2143 cli_state->sock = -1;
2148 static bool connection_ok(struct winbindd_domain *domain)
2150 bool ok;
2152 ok = cli_state_is_connected(domain->conn.cli);
2153 if (!ok) {
2154 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2155 domain->dcname, domain->name));
2156 return False;
2159 if (!domain->online) {
2160 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2161 return False;
2164 return True;
2167 /* Initialize a new connection up to the RPC BIND.
2168 Bypass online status check so always does network calls. */
2170 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2172 NTSTATUS result;
2173 bool skip_connection = domain->internal;
2174 if (need_rw_dc && domain->rodc) {
2175 skip_connection = false;
2178 /* Internal connections never use the network. */
2179 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2180 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2183 /* Still ask the internal LSA and SAMR server about the local domain */
2184 if (skip_connection || connection_ok(domain)) {
2185 if (!domain->initialized) {
2186 set_dc_type_and_flags(domain);
2188 return NT_STATUS_OK;
2191 invalidate_cm_connection(domain);
2193 if (!domain->primary && !domain->initialized) {
2195 * Before we connect to a trust, work out if it is an
2196 * AD domain by asking our own domain.
2198 set_dc_type_and_flags_trustinfo(domain);
2201 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2203 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2204 set_dc_type_and_flags(domain);
2207 return result;
2210 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2212 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2213 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2216 if (domain->initialized && !domain->online) {
2217 /* We check for online status elsewhere. */
2218 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2221 return init_dc_connection_network(domain, need_rw_dc);
2224 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2226 NTSTATUS status;
2228 status = init_dc_connection(domain, need_rw_dc);
2229 if (!NT_STATUS_IS_OK(status)) {
2230 return status;
2233 if (!domain->internal && domain->conn.cli == NULL) {
2234 /* happens for trusted domains without inbound trust */
2235 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2238 return NT_STATUS_OK;
2241 /******************************************************************************
2242 Set the trust flags (direction and forest location) for a domain
2243 ******************************************************************************/
2245 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2247 struct winbindd_domain *our_domain;
2248 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2249 WERROR werr;
2250 struct netr_DomainTrustList trusts;
2251 int i;
2252 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2253 NETR_TRUST_FLAG_OUTBOUND |
2254 NETR_TRUST_FLAG_INBOUND);
2255 struct rpc_pipe_client *cli;
2256 TALLOC_CTX *mem_ctx = NULL;
2257 struct dcerpc_binding_handle *b;
2259 if (IS_DC) {
2261 * On a DC we loaded all trusts
2262 * from configuration and never learn
2263 * new domains.
2265 return true;
2268 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2270 /* Our primary domain doesn't need to worry about trust flags.
2271 Force it to go through the network setup */
2272 if ( domain->primary ) {
2273 return False;
2276 mem_ctx = talloc_stackframe();
2277 our_domain = find_our_domain();
2278 if (our_domain->internal) {
2279 result = init_dc_connection(our_domain, false);
2280 if (!NT_STATUS_IS_OK(result)) {
2281 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2282 "Not able to make a connection to our domain: %s\n",
2283 nt_errstr(result)));
2284 TALLOC_FREE(mem_ctx);
2285 return false;
2289 /* This won't work unless our domain is AD */
2290 if ( !our_domain->active_directory ) {
2291 TALLOC_FREE(mem_ctx);
2292 return False;
2295 if (our_domain->internal) {
2296 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2297 } else if (!connection_ok(our_domain)) {
2298 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2299 "No connection to our domain!\n"));
2300 TALLOC_FREE(mem_ctx);
2301 return False;
2302 } else {
2303 result = cm_connect_netlogon(our_domain, &cli);
2306 if (!NT_STATUS_IS_OK(result)) {
2307 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2308 "a connection to %s for PIPE_NETLOGON (%s)\n",
2309 domain->name, nt_errstr(result)));
2310 TALLOC_FREE(mem_ctx);
2311 return False;
2313 b = cli->binding_handle;
2315 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2316 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2317 cli->desthost,
2318 flags,
2319 &trusts,
2320 &werr);
2321 if (!NT_STATUS_IS_OK(result)) {
2322 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2323 "failed to query trusted domain list: %s\n",
2324 nt_errstr(result)));
2325 TALLOC_FREE(mem_ctx);
2326 return false;
2328 if (!W_ERROR_IS_OK(werr)) {
2329 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2330 "failed to query trusted domain list: %s\n",
2331 win_errstr(werr)));
2332 TALLOC_FREE(mem_ctx);
2333 return false;
2336 /* Now find the domain name and get the flags */
2338 for ( i=0; i<trusts.count; i++ ) {
2339 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2340 domain->domain_flags = trusts.array[i].trust_flags;
2341 domain->domain_type = trusts.array[i].trust_type;
2342 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2344 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2345 domain->active_directory = True;
2347 /* This flag is only set if the domain is *our*
2348 primary domain and the primary domain is in
2349 native mode */
2351 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2353 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2354 "native mode.\n", domain->name,
2355 domain->native_mode ? "" : "NOT "));
2357 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2358 "running active directory.\n", domain->name,
2359 domain->active_directory ? "" : "NOT "));
2361 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2363 domain->initialized = True;
2365 break;
2369 TALLOC_FREE(mem_ctx);
2371 return domain->initialized;
2374 /******************************************************************************
2375 We can 'sense' certain things about the DC by it's replies to certain
2376 questions.
2378 This tells us if this particular remote server is Active Directory, and if it
2379 is native mode.
2380 ******************************************************************************/
2382 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2384 NTSTATUS status, result;
2385 WERROR werr;
2386 TALLOC_CTX *mem_ctx = NULL;
2387 struct rpc_pipe_client *cli = NULL;
2388 struct policy_handle pol;
2389 union dssetup_DsRoleInfo info;
2390 union lsa_PolicyInformation *lsa_info = NULL;
2392 if (!domain->internal && !connection_ok(domain)) {
2393 return;
2396 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2397 domain->name);
2398 if (!mem_ctx) {
2399 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2400 return;
2403 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2405 if (domain->internal) {
2406 status = wb_open_internal_pipe(mem_ctx,
2407 &ndr_table_dssetup,
2408 &cli);
2409 } else {
2410 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2411 &ndr_table_dssetup,
2412 &cli);
2415 if (!NT_STATUS_IS_OK(status)) {
2416 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2417 "PI_DSSETUP on domain %s: (%s)\n",
2418 domain->name, nt_errstr(status)));
2420 /* if this is just a non-AD domain we need to continue
2421 * identifying so that we can in the end return with
2422 * domain->initialized = True - gd */
2424 goto no_dssetup;
2427 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2428 DS_ROLE_BASIC_INFORMATION,
2429 &info,
2430 &werr);
2431 TALLOC_FREE(cli);
2433 if (NT_STATUS_IS_OK(status)) {
2434 result = werror_to_ntstatus(werr);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2438 "on domain %s failed: (%s)\n",
2439 domain->name, nt_errstr(status)));
2441 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2442 * every opcode on the DSSETUP pipe, continue with
2443 * no_dssetup mode here as well to get domain->initialized
2444 * set - gd */
2446 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2447 goto no_dssetup;
2450 TALLOC_FREE(mem_ctx);
2451 return;
2454 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2455 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2456 domain->native_mode = True;
2457 } else {
2458 domain->native_mode = False;
2461 no_dssetup:
2462 if (domain->internal) {
2463 status = wb_open_internal_pipe(mem_ctx,
2464 &ndr_table_lsarpc,
2465 &cli);
2466 } else {
2467 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2468 &ndr_table_lsarpc, &cli);
2470 if (!NT_STATUS_IS_OK(status)) {
2471 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2472 "PI_LSARPC on domain %s: (%s)\n",
2473 domain->name, nt_errstr(status)));
2474 TALLOC_FREE(cli);
2475 TALLOC_FREE(mem_ctx);
2476 return;
2479 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2480 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2482 if (NT_STATUS_IS_OK(status)) {
2483 /* This particular query is exactly what Win2k clients use
2484 to determine that the DC is active directory */
2485 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2486 &pol,
2487 LSA_POLICY_INFO_DNS,
2488 &lsa_info,
2489 &result);
2492 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2493 domain->active_directory = True;
2495 if (lsa_info->dns.name.string) {
2496 if (!strequal(domain->name, lsa_info->dns.name.string))
2498 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2499 "for domain %s claimed it was a DC "
2500 "for domain %s, refusing to "
2501 "initialize\n",
2502 domain->name,
2503 lsa_info->dns.name.string));
2504 TALLOC_FREE(cli);
2505 TALLOC_FREE(mem_ctx);
2506 return;
2508 talloc_free(domain->name);
2509 domain->name = talloc_strdup(domain,
2510 lsa_info->dns.name.string);
2511 if (domain->name == NULL) {
2512 goto done;
2516 if (lsa_info->dns.dns_domain.string) {
2517 if (domain->alt_name != NULL &&
2518 !strequal(domain->alt_name,
2519 lsa_info->dns.dns_domain.string))
2521 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2522 "for domain %s (%s) claimed it was "
2523 "a DC for domain %s, refusing to "
2524 "initialize\n",
2525 domain->alt_name, domain->name,
2526 lsa_info->dns.dns_domain.string));
2527 TALLOC_FREE(cli);
2528 TALLOC_FREE(mem_ctx);
2529 return;
2531 talloc_free(domain->alt_name);
2532 domain->alt_name =
2533 talloc_strdup(domain,
2534 lsa_info->dns.dns_domain.string);
2535 if (domain->alt_name == NULL) {
2536 goto done;
2540 /* See if we can set some domain trust flags about
2541 ourself */
2543 if (lsa_info->dns.dns_forest.string) {
2544 talloc_free(domain->forest_name);
2545 domain->forest_name =
2546 talloc_strdup(domain,
2547 lsa_info->dns.dns_forest.string);
2548 if (domain->forest_name == NULL) {
2549 goto done;
2552 if (strequal(domain->forest_name, domain->alt_name)) {
2553 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2557 if (lsa_info->dns.sid) {
2558 if (!is_null_sid(&domain->sid) &&
2559 !dom_sid_equal(&domain->sid,
2560 lsa_info->dns.sid))
2562 struct dom_sid_buf buf1, buf2;
2563 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2564 "for domain %s (%s) claimed it was "
2565 "a DC for domain %s, refusing to "
2566 "initialize\n",
2567 dom_sid_str_buf(&domain->sid, &buf1),
2568 domain->name,
2569 dom_sid_str_buf(lsa_info->dns.sid,
2570 &buf2)));
2571 TALLOC_FREE(cli);
2572 TALLOC_FREE(mem_ctx);
2573 return;
2575 sid_copy(&domain->sid, lsa_info->dns.sid);
2577 } else {
2578 domain->active_directory = False;
2580 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2581 SEC_FLAG_MAXIMUM_ALLOWED,
2582 &pol);
2584 if (!NT_STATUS_IS_OK(status)) {
2585 goto done;
2588 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2589 &pol,
2590 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2591 &lsa_info,
2592 &result);
2593 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2595 if (lsa_info->account_domain.name.string) {
2596 if (!strequal(domain->name,
2597 lsa_info->account_domain.name.string))
2599 DEBUG(1,
2600 ("set_dc_type_and_flags_connect: "
2601 "DC for domain %s claimed it was"
2602 " a DC for domain %s, refusing "
2603 "to initialize\n", domain->name,
2604 lsa_info->
2605 account_domain.name.string));
2606 TALLOC_FREE(cli);
2607 TALLOC_FREE(mem_ctx);
2608 return;
2610 talloc_free(domain->name);
2611 domain->name =
2612 talloc_strdup(domain,
2613 lsa_info->account_domain.name.string);
2616 if (lsa_info->account_domain.sid) {
2617 if (!is_null_sid(&domain->sid) &&
2618 !dom_sid_equal(&domain->sid,
2619 lsa_info->account_domain.sid))
2621 struct dom_sid_buf buf1, buf2;
2622 DEBUG(1,
2623 ("set_dc_type_and_flags_connect: "
2624 "DC for domain %s (%s) claimed "
2625 "it was a DC for domain %s, "
2626 "refusing to initialize\n",
2627 dom_sid_str_buf(
2628 &domain->sid, &buf1),
2629 domain->name,
2630 dom_sid_str_buf(
2631 lsa_info->account_domain.sid,
2632 &buf2)));
2633 TALLOC_FREE(cli);
2634 TALLOC_FREE(mem_ctx);
2635 return;
2637 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2641 done:
2643 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2644 domain->name, domain->native_mode ? "" : "NOT "));
2646 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2647 domain->name, domain->active_directory ? "" : "NOT "));
2649 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2651 TALLOC_FREE(cli);
2653 TALLOC_FREE(mem_ctx);
2655 domain->initialized = True;
2658 /**********************************************************************
2659 Set the domain_flags (trust attributes, domain operating modes, etc...
2660 ***********************************************************************/
2662 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2664 if (IS_DC) {
2666 * On a DC we loaded all trusts
2667 * from configuration and never learn
2668 * new domains.
2670 return;
2673 /* we always have to contact our primary domain */
2675 if ( domain->primary || domain->internal) {
2676 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2677 "primary or internal domain\n"));
2678 set_dc_type_and_flags_connect( domain );
2679 return;
2682 /* Use our DC to get the information if possible */
2684 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2685 /* Otherwise, fallback to contacting the
2686 domain directly */
2687 set_dc_type_and_flags_connect( domain );
2690 return;
2695 /**********************************************************************
2696 ***********************************************************************/
2698 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2699 struct netlogon_creds_cli_context **ppdc)
2701 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2702 struct rpc_pipe_client *netlogon_pipe;
2704 *ppdc = NULL;
2706 if ((!IS_DC) && (!domain->primary)) {
2707 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2710 if (domain->conn.netlogon_creds_ctx != NULL) {
2711 *ppdc = domain->conn.netlogon_creds_ctx;
2712 return NT_STATUS_OK;
2715 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2716 if (!NT_STATUS_IS_OK(result)) {
2717 return result;
2720 return NT_STATUS_OK;
2723 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2724 bool need_rw_dc,
2725 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2727 struct winbindd_cm_conn *conn;
2728 NTSTATUS status, result;
2729 struct netlogon_creds_cli_context *p_creds;
2730 struct cli_credentials *creds = NULL;
2731 bool retry = false; /* allow one retry attempt for expired session */
2733 if (sid_check_is_our_sam(&domain->sid)) {
2734 if (domain->rodc == false || need_rw_dc == false) {
2735 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2739 if (IS_AD_DC) {
2741 * In theory we should not use SAMR within
2742 * winbindd at all, but that's a larger task to
2743 * remove this and avoid breaking existing
2744 * setups.
2746 * At least as AD DC we have the restriction
2747 * to avoid SAMR against trusted domains,
2748 * as there're no existing setups.
2750 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2753 retry:
2754 status = init_dc_connection_rpc(domain, need_rw_dc);
2755 if (!NT_STATUS_IS_OK(status)) {
2756 return status;
2759 conn = &domain->conn;
2761 if (rpccli_is_connected(conn->samr_pipe)) {
2762 goto done;
2765 TALLOC_FREE(conn->samr_pipe);
2768 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2769 * sign and sealed pipe using the machine account password by
2770 * preference. If we can't - try schannel, if that fails, try
2771 * anonymous.
2774 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2775 if (!NT_STATUS_IS_OK(result)) {
2776 DEBUG(10, ("cm_connect_sam: No user available for "
2777 "domain %s, trying schannel\n", domain->name));
2778 goto schannel;
2781 if (cli_credentials_is_anonymous(creds)) {
2782 goto anonymous;
2786 * We have an authenticated connection. Use a SPNEGO
2787 * authenticated SAMR pipe with sign & seal.
2789 status = cli_rpc_pipe_open_with_creds(conn->cli,
2790 &ndr_table_samr,
2791 NCACN_NP,
2792 DCERPC_AUTH_TYPE_SPNEGO,
2793 conn->auth_level,
2794 smbXcli_conn_remote_name(conn->cli->conn),
2795 creds,
2796 &conn->samr_pipe);
2798 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2799 && !retry) {
2800 invalidate_cm_connection(domain);
2801 retry = true;
2802 goto retry;
2805 if (!NT_STATUS_IS_OK(status)) {
2806 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2807 "pipe for domain %s using NTLMSSP "
2808 "authenticated pipe: user %s. Error was "
2809 "%s\n", domain->name,
2810 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2811 nt_errstr(status)));
2812 goto schannel;
2815 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2816 "domain %s using NTLMSSP authenticated "
2817 "pipe: user %s\n", domain->name,
2818 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2820 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2821 conn->samr_pipe->desthost,
2822 SEC_FLAG_MAXIMUM_ALLOWED,
2823 &conn->sam_connect_handle,
2824 &result);
2826 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2827 invalidate_cm_connection(domain);
2828 TALLOC_FREE(conn->samr_pipe);
2829 retry = true;
2830 goto retry;
2833 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2834 goto open_domain;
2836 if (NT_STATUS_IS_OK(status)) {
2837 status = result;
2840 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2841 "failed for domain %s, error was %s. Trying schannel\n",
2842 domain->name, nt_errstr(status) ));
2843 TALLOC_FREE(conn->samr_pipe);
2845 schannel:
2847 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2849 status = cm_get_schannel_creds(domain, &p_creds);
2850 if (!NT_STATUS_IS_OK(status)) {
2851 /* If this call fails - conn->cli can now be NULL ! */
2852 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2853 "for domain %s (error %s), trying anon\n",
2854 domain->name,
2855 nt_errstr(status) ));
2856 goto anonymous;
2858 TALLOC_FREE(creds);
2859 status = cli_rpc_pipe_open_schannel_with_creds(
2860 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2861 &conn->samr_pipe);
2863 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2864 && !retry) {
2865 invalidate_cm_connection(domain);
2866 retry = true;
2867 goto retry;
2870 if (!NT_STATUS_IS_OK(status)) {
2871 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2872 "domain %s using schannel. Error was %s\n",
2873 domain->name, nt_errstr(status) ));
2874 goto anonymous;
2876 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2877 "schannel.\n", domain->name ));
2879 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2880 conn->samr_pipe->desthost,
2881 SEC_FLAG_MAXIMUM_ALLOWED,
2882 &conn->sam_connect_handle,
2883 &result);
2885 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2886 invalidate_cm_connection(domain);
2887 TALLOC_FREE(conn->samr_pipe);
2888 retry = true;
2889 goto retry;
2892 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2893 goto open_domain;
2895 if (NT_STATUS_IS_OK(status)) {
2896 status = result;
2898 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2899 "for domain %s, error was %s. Trying anonymous\n",
2900 domain->name, nt_errstr(status) ));
2901 TALLOC_FREE(conn->samr_pipe);
2903 anonymous:
2905 /* Finally fall back to anonymous. */
2906 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2907 status = NT_STATUS_DOWNGRADE_DETECTED;
2908 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2909 "without connection level security, "
2910 "must set 'winbind sealed pipes = false' and "
2911 "'require strong key = false' to proceed: %s\n",
2912 domain->name, nt_errstr(status)));
2913 goto done;
2915 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2916 &conn->samr_pipe);
2918 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2919 && !retry) {
2920 invalidate_cm_connection(domain);
2921 retry = true;
2922 goto retry;
2925 if (!NT_STATUS_IS_OK(status)) {
2926 goto done;
2929 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2930 conn->samr_pipe->desthost,
2931 SEC_FLAG_MAXIMUM_ALLOWED,
2932 &conn->sam_connect_handle,
2933 &result);
2935 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2936 invalidate_cm_connection(domain);
2937 TALLOC_FREE(conn->samr_pipe);
2938 retry = true;
2939 goto retry;
2942 if (!NT_STATUS_IS_OK(status)) {
2943 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2944 "for domain %s Error was %s\n",
2945 domain->name, nt_errstr(status) ));
2946 goto done;
2948 if (!NT_STATUS_IS_OK(result)) {
2949 status = result;
2950 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2951 "for domain %s Error was %s\n",
2952 domain->name, nt_errstr(result)));
2953 goto done;
2956 open_domain:
2957 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2958 mem_ctx,
2959 &conn->sam_connect_handle,
2960 SEC_FLAG_MAXIMUM_ALLOWED,
2961 &domain->sid,
2962 &conn->sam_domain_handle,
2963 &result);
2964 if (!NT_STATUS_IS_OK(status)) {
2965 goto done;
2968 status = result;
2969 done:
2971 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2973 * if we got access denied, we might just have no access rights
2974 * to talk to the remote samr server server (e.g. when we are a
2975 * PDC and we are connecting a w2k8 pdc via an interdomain
2976 * trust). In that case do not invalidate the whole connection
2977 * stack
2979 TALLOC_FREE(conn->samr_pipe);
2980 ZERO_STRUCT(conn->sam_domain_handle);
2981 return status;
2982 } else if (!NT_STATUS_IS_OK(status)) {
2983 invalidate_cm_connection(domain);
2984 return status;
2987 *cli = conn->samr_pipe;
2988 *sam_handle = conn->sam_domain_handle;
2989 return status;
2992 /**********************************************************************
2993 open an schanneld ncacn_ip_tcp connection to LSA
2994 ***********************************************************************/
2996 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2997 TALLOC_CTX *mem_ctx,
2998 struct rpc_pipe_client **cli)
3000 struct winbindd_cm_conn *conn;
3001 struct netlogon_creds_cli_context *p_creds = NULL;
3002 NTSTATUS status;
3004 DEBUG(10,("cm_connect_lsa_tcp\n"));
3006 status = init_dc_connection_rpc(domain, false);
3007 if (!NT_STATUS_IS_OK(status)) {
3008 return status;
3011 conn = &domain->conn;
3014 * rpccli_is_connected handles more error cases
3016 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
3017 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
3018 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
3019 goto done;
3022 TALLOC_FREE(conn->lsa_pipe_tcp);
3024 status = cm_get_schannel_creds(domain, &p_creds);
3025 if (!NT_STATUS_IS_OK(status)) {
3026 goto done;
3029 status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
3030 &ndr_table_lsarpc,
3031 NCACN_IP_TCP,
3032 p_creds,
3033 &conn->lsa_pipe_tcp);
3034 if (!NT_STATUS_IS_OK(status)) {
3035 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
3036 nt_errstr(status)));
3037 goto done;
3040 done:
3041 if (!NT_STATUS_IS_OK(status)) {
3042 TALLOC_FREE(conn->lsa_pipe_tcp);
3043 return status;
3046 *cli = conn->lsa_pipe_tcp;
3048 return status;
3051 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
3052 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
3054 struct winbindd_cm_conn *conn;
3055 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
3056 struct netlogon_creds_cli_context *p_creds;
3057 struct cli_credentials *creds = NULL;
3058 bool retry = false; /* allow one retry attempt for expired session */
3060 retry:
3061 result = init_dc_connection_rpc(domain, false);
3062 if (!NT_STATUS_IS_OK(result))
3063 return result;
3065 conn = &domain->conn;
3067 if (rpccli_is_connected(conn->lsa_pipe)) {
3068 goto done;
3071 TALLOC_FREE(conn->lsa_pipe);
3073 if (IS_AD_DC) {
3075 * Make sure we only use schannel as AD DC.
3077 goto schannel;
3080 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
3081 if (!NT_STATUS_IS_OK(result)) {
3082 DEBUG(10, ("cm_connect_lsa: No user available for "
3083 "domain %s, trying schannel\n", domain->name));
3084 goto schannel;
3087 if (cli_credentials_is_anonymous(creds)) {
3088 goto anonymous;
3092 * We have an authenticated connection. Use a SPNEGO
3093 * authenticated LSA pipe with sign & seal.
3095 result = cli_rpc_pipe_open_with_creds
3096 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
3097 DCERPC_AUTH_TYPE_SPNEGO,
3098 conn->auth_level,
3099 smbXcli_conn_remote_name(conn->cli->conn),
3100 creds,
3101 &conn->lsa_pipe);
3103 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3104 && !retry) {
3105 invalidate_cm_connection(domain);
3106 retry = true;
3107 goto retry;
3110 if (!NT_STATUS_IS_OK(result)) {
3111 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3112 "domain %s using NTLMSSP authenticated pipe: user "
3113 "%s. Error was %s. Trying schannel.\n",
3114 domain->name,
3115 cli_credentials_get_unparsed_name(creds, talloc_tos()),
3116 nt_errstr(result)));
3117 goto schannel;
3120 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3121 "NTLMSSP authenticated pipe: user %s\n",
3122 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3124 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3125 SEC_FLAG_MAXIMUM_ALLOWED,
3126 &conn->lsa_policy);
3127 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3128 invalidate_cm_connection(domain);
3129 TALLOC_FREE(conn->lsa_pipe);
3130 retry = true;
3131 goto retry;
3134 if (NT_STATUS_IS_OK(result)) {
3135 goto done;
3138 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3139 "schannel\n"));
3141 TALLOC_FREE(conn->lsa_pipe);
3143 schannel:
3145 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3147 result = cm_get_schannel_creds(domain, &p_creds);
3148 if (!NT_STATUS_IS_OK(result)) {
3149 /* If this call fails - conn->cli can now be NULL ! */
3150 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3151 "for domain %s (error %s), trying anon\n",
3152 domain->name,
3153 nt_errstr(result) ));
3154 goto anonymous;
3157 TALLOC_FREE(creds);
3158 result = cli_rpc_pipe_open_schannel_with_creds(
3159 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3160 &conn->lsa_pipe);
3162 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3163 && !retry) {
3164 invalidate_cm_connection(domain);
3165 retry = true;
3166 goto retry;
3169 if (!NT_STATUS_IS_OK(result)) {
3170 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3171 "domain %s using schannel. Error was %s\n",
3172 domain->name, nt_errstr(result) ));
3173 goto anonymous;
3175 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3176 "schannel.\n", domain->name ));
3178 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3179 SEC_FLAG_MAXIMUM_ALLOWED,
3180 &conn->lsa_policy);
3182 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3183 invalidate_cm_connection(domain);
3184 TALLOC_FREE(conn->lsa_pipe);
3185 retry = true;
3186 goto retry;
3189 if (NT_STATUS_IS_OK(result)) {
3190 goto done;
3193 if (IS_AD_DC) {
3195 * Make sure we only use schannel as AD DC.
3197 goto done;
3200 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3201 "anonymous\n"));
3203 TALLOC_FREE(conn->lsa_pipe);
3205 anonymous:
3207 if (IS_AD_DC) {
3209 * Make sure we only use schannel as AD DC.
3211 goto done;
3214 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3215 result = NT_STATUS_DOWNGRADE_DETECTED;
3216 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3217 "without connection level security, "
3218 "must set 'winbind sealed pipes = false' and "
3219 "'require strong key = false' to proceed: %s\n",
3220 domain->name, nt_errstr(result)));
3221 goto done;
3224 result = cli_rpc_pipe_open_noauth(conn->cli,
3225 &ndr_table_lsarpc,
3226 &conn->lsa_pipe);
3228 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3229 && !retry) {
3230 invalidate_cm_connection(domain);
3231 retry = true;
3232 goto retry;
3235 if (!NT_STATUS_IS_OK(result)) {
3236 goto done;
3239 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3240 SEC_FLAG_MAXIMUM_ALLOWED,
3241 &conn->lsa_policy);
3243 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3244 invalidate_cm_connection(domain);
3245 TALLOC_FREE(conn->lsa_pipe);
3246 retry = true;
3247 goto retry;
3250 done:
3251 if (!NT_STATUS_IS_OK(result)) {
3252 invalidate_cm_connection(domain);
3253 return result;
3256 *cli = conn->lsa_pipe;
3257 *lsa_policy = conn->lsa_policy;
3258 return result;
3261 /****************************************************************************
3262 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3263 ****************************************************************************/
3265 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3266 TALLOC_CTX *mem_ctx,
3267 struct rpc_pipe_client **cli,
3268 struct policy_handle *lsa_policy)
3270 NTSTATUS status;
3272 if (domain->can_do_ncacn_ip_tcp) {
3273 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3274 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3275 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3276 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3277 invalidate_cm_connection(domain);
3278 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3280 if (NT_STATUS_IS_OK(status)) {
3281 return status;
3285 * we tried twice to connect via ncan_ip_tcp and schannel and
3286 * failed - maybe it is a trusted domain we can't connect to ?
3287 * do not try tcp next time - gd
3289 * This also prevents NETLOGON over TCP
3291 domain->can_do_ncacn_ip_tcp = false;
3294 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3296 return status;
3299 /****************************************************************************
3300 Open the netlogon pipe to this DC.
3301 ****************************************************************************/
3303 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3304 enum dcerpc_transport_t transport,
3305 struct rpc_pipe_client **cli)
3307 struct messaging_context *msg_ctx = global_messaging_context();
3308 struct winbindd_cm_conn *conn;
3309 NTSTATUS result;
3310 enum netr_SchannelType sec_chan_type;
3311 struct cli_credentials *creds = NULL;
3313 *cli = NULL;
3315 if (IS_AD_DC) {
3316 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3318 * Make sure we don't even try to
3319 * connect to a foreign domain
3320 * without a direct outbound trust.
3322 return NT_STATUS_NO_TRUST_LSA_SECRET;
3326 result = init_dc_connection_rpc(domain, domain->rodc);
3327 if (!NT_STATUS_IS_OK(result)) {
3328 return result;
3331 conn = &domain->conn;
3333 if (rpccli_is_connected(conn->netlogon_pipe)) {
3334 *cli = conn->netlogon_pipe;
3335 return NT_STATUS_OK;
3338 TALLOC_FREE(conn->netlogon_pipe);
3339 TALLOC_FREE(conn->netlogon_creds_ctx);
3341 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3342 if (!NT_STATUS_IS_OK(result)) {
3343 DBG_DEBUG("No user available for domain %s when trying "
3344 "schannel\n", domain->name);
3345 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3348 if (cli_credentials_is_anonymous(creds)) {
3349 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3350 "unable to make get NETLOGON credentials\n",
3351 domain->name);
3352 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3355 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3356 if (sec_chan_type == SEC_CHAN_NULL) {
3357 if (transport == NCACN_IP_TCP) {
3358 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3359 "for %s, deny NCACN_IP_TCP and let the "
3360 "caller fallback to NCACN_NP.\n",
3361 domain->name);
3362 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3365 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3366 "fallback to noauth on NCACN_NP.\n",
3367 domain->name);
3369 result = cli_rpc_pipe_open_noauth_transport(
3370 conn->cli,
3371 transport,
3372 &ndr_table_netlogon,
3373 &conn->netlogon_pipe);
3374 if (!NT_STATUS_IS_OK(result)) {
3375 invalidate_cm_connection(domain);
3376 return result;
3379 *cli = conn->netlogon_pipe;
3380 return NT_STATUS_OK;
3383 result = rpccli_create_netlogon_creds_ctx(creds,
3384 domain->dcname,
3385 msg_ctx,
3386 domain,
3387 &conn->netlogon_creds_ctx);
3388 if (!NT_STATUS_IS_OK(result)) {
3389 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3390 "unable to create NETLOGON credentials: %s\n",
3391 domain->name, nt_errstr(result)));
3392 return result;
3395 result = rpccli_connect_netlogon(
3396 conn->cli, transport,
3397 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3398 &conn->netlogon_pipe);
3399 conn->netlogon_force_reauth = false;
3400 if (!NT_STATUS_IS_OK(result)) {
3401 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3402 nt_errstr(result));
3403 return result;
3406 *cli = conn->netlogon_pipe;
3407 return NT_STATUS_OK;
3410 /****************************************************************************
3411 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3412 ****************************************************************************/
3414 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3415 struct rpc_pipe_client **cli)
3417 NTSTATUS status;
3419 status = init_dc_connection_rpc(domain, domain->rodc);
3420 if (!NT_STATUS_IS_OK(status)) {
3421 return status;
3424 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3425 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3426 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3427 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3428 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3429 invalidate_cm_connection(domain);
3430 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3432 if (NT_STATUS_IS_OK(status)) {
3433 return status;
3437 * we tried twice to connect via ncan_ip_tcp and schannel and
3438 * failed - maybe it is a trusted domain we can't connect to ?
3439 * do not try tcp next time - gd
3441 * This also prevents LSA over TCP
3443 domain->can_do_ncacn_ip_tcp = false;
3446 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3447 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3449 * SMB2 session expired, needs reauthentication. Drop
3450 * connection and retry.
3452 invalidate_cm_connection(domain);
3453 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3456 return status;
3459 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3460 struct rpc_pipe_client **cli,
3461 struct netlogon_creds_cli_context **ppdc)
3463 NTSTATUS status;
3465 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3466 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3469 status = cm_connect_netlogon(domain, cli);
3470 if (!NT_STATUS_IS_OK(status)) {
3471 return status;
3474 if (domain->conn.netlogon_creds_ctx == NULL) {
3475 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3478 *ppdc = domain->conn.netlogon_creds_ctx;
3479 return NT_STATUS_OK;
3482 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3483 void *private_data,
3484 uint32_t msg_type,
3485 struct server_id server_id,
3486 DATA_BLOB *data)
3488 struct winbindd_domain *domain;
3489 char *freeit = NULL;
3490 char *addr;
3492 if ((data == NULL)
3493 || (data->data == NULL)
3494 || (data->length == 0)
3495 || (data->data[data->length-1] != '\0')) {
3496 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3497 "string\n"));
3498 return;
3501 addr = (char *)data->data;
3502 DEBUG(10, ("IP %s dropped\n", addr));
3504 if (!is_ipaddress(addr)) {
3505 char *slash;
3507 * Some code sends us ip addresses with the /netmask
3508 * suffix
3510 slash = strchr(addr, '/');
3511 if (slash == NULL) {
3512 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3513 addr));
3514 return;
3516 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3517 if (freeit == NULL) {
3518 DEBUG(1, ("talloc failed\n"));
3519 return;
3521 addr = freeit;
3522 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3525 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3526 char sockaddr[INET6_ADDRSTRLEN];
3528 if (!cli_state_is_connected(domain->conn.cli)) {
3529 continue;
3532 print_sockaddr(sockaddr, sizeof(sockaddr),
3533 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3535 if (strequal(sockaddr, addr)) {
3536 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3539 TALLOC_FREE(freeit);
3542 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3543 void *private_data,
3544 uint32_t msg_type,
3545 struct server_id server_id,
3546 DATA_BLOB *data)
3548 struct winbindd_domain *domain;
3550 for (domain = domain_list(); domain; domain = domain->next) {
3551 if (domain->internal) {
3552 continue;
3554 invalidate_cm_connection(domain);