winbind: make sure we don't contact trusted domains via SAMR as AD DC
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob02a6959f2bd90d717b540550f6d1e6db3280ba8f
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 "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "libsmb/libsmb.h"
73 #include "libsmb/clidgram.h"
74 #include "ads.h"
75 #include "secrets.h"
76 #include "../libcli/security/security.h"
77 #include "passdb.h"
78 #include "messages.h"
79 #include "auth/gensec/gensec.h"
80 #include "../libcli/smb/smbXcli_base.h"
81 #include "libcli/auth/netlogon_creds_cli.h"
82 #include "auth.h"
83 #include "rpc_server/rpc_ncacn_np.h"
84 #include "auth/credentials/credentials.h"
85 #include "lib/param/param.h"
87 #undef DBGC_CLASS
88 #define DBGC_CLASS DBGC_WINBIND
90 struct dc_name_ip {
91 fstring name;
92 struct sockaddr_storage ss;
95 extern struct winbindd_methods reconnect_methods;
96 extern bool override_logfile;
98 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
99 static void set_dc_type_and_flags( struct winbindd_domain *domain );
100 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
101 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
102 struct dc_name_ip **dcs, int *num_dcs,
103 uint32_t request_flags);
105 /****************************************************************
106 Child failed to find DC's. Reschedule check.
107 ****************************************************************/
109 static void msg_failed_to_go_online(struct messaging_context *msg,
110 void *private_data,
111 uint32_t msg_type,
112 struct server_id server_id,
113 DATA_BLOB *data)
115 struct winbindd_domain *domain;
116 const char *domainname = (const char *)data->data;
118 if (data->data == NULL || data->length == 0) {
119 return;
122 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
124 for (domain = domain_list(); domain; domain = domain->next) {
125 if (domain->internal) {
126 continue;
129 if (strequal(domain->name, domainname)) {
130 if (domain->online) {
131 /* We're already online, ignore. */
132 DEBUG(5,("msg_fail_to_go_online: domain %s "
133 "already online.\n", domainname));
134 continue;
137 /* Reschedule the online check. */
138 set_domain_offline(domain);
139 break;
144 /****************************************************************
145 Actually cause a reconnect from a message.
146 ****************************************************************/
148 static void msg_try_to_go_online(struct messaging_context *msg,
149 void *private_data,
150 uint32_t msg_type,
151 struct server_id server_id,
152 DATA_BLOB *data)
154 struct winbindd_domain *domain;
155 const char *domainname = (const char *)data->data;
157 if (data->data == NULL || data->length == 0) {
158 return;
161 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
163 for (domain = domain_list(); domain; domain = domain->next) {
164 if (domain->internal) {
165 continue;
168 if (strequal(domain->name, domainname)) {
170 if (domain->online) {
171 /* We're already online, ignore. */
172 DEBUG(5,("msg_try_to_go_online: domain %s "
173 "already online.\n", domainname));
174 continue;
177 /* This call takes care of setting the online
178 flag to true if we connected, or re-adding
179 the offline handler if false. Bypasses online
180 check so always does network calls. */
182 init_dc_connection_network(domain, true);
183 break;
188 /****************************************************************
189 Fork a child to try and contact a DC. Do this as contacting a
190 DC requires blocking lookups and we don't want to block our
191 parent.
192 ****************************************************************/
194 static bool fork_child_dc_connect(struct winbindd_domain *domain)
196 struct dc_name_ip *dcs = NULL;
197 int num_dcs = 0;
198 TALLOC_CTX *mem_ctx = NULL;
199 pid_t parent_pid = getpid();
200 char *lfile = NULL;
201 NTSTATUS status;
203 if (domain->dc_probe_pid != (pid_t)-1) {
205 * We might already have a DC probe
206 * child working, check.
208 if (process_exists_by_pid(domain->dc_probe_pid)) {
209 DEBUG(10,("fork_child_dc_connect: pid %u already "
210 "checking for DC's.\n",
211 (unsigned int)domain->dc_probe_pid));
212 return true;
214 domain->dc_probe_pid = (pid_t)-1;
217 domain->dc_probe_pid = fork();
219 if (domain->dc_probe_pid == (pid_t)-1) {
220 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
221 return False;
224 if (domain->dc_probe_pid != (pid_t)0) {
225 /* Parent */
226 messaging_register(server_messaging_context(), NULL,
227 MSG_WINBIND_TRY_TO_GO_ONLINE,
228 msg_try_to_go_online);
229 messaging_register(server_messaging_context(), NULL,
230 MSG_WINBIND_FAILED_TO_GO_ONLINE,
231 msg_failed_to_go_online);
232 return True;
235 /* Child. */
237 /* Leave messages blocked - we will never process one. */
239 if (!override_logfile) {
240 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
241 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
242 _exit(1);
246 status = winbindd_reinit_after_fork(NULL, lfile);
247 if (!NT_STATUS_IS_OK(status)) {
248 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
249 nt_errstr(status)));
250 messaging_send_buf(server_messaging_context(),
251 pid_to_procid(parent_pid),
252 MSG_WINBIND_FAILED_TO_GO_ONLINE,
253 (const uint8_t *)domain->name,
254 strlen(domain->name)+1);
255 _exit(1);
257 SAFE_FREE(lfile);
259 setproctitle("dc-connect child");
261 mem_ctx = talloc_init("fork_child_dc_connect");
262 if (!mem_ctx) {
263 DEBUG(0,("talloc_init failed.\n"));
264 messaging_send_buf(server_messaging_context(),
265 pid_to_procid(parent_pid),
266 MSG_WINBIND_FAILED_TO_GO_ONLINE,
267 (const uint8_t *)domain->name,
268 strlen(domain->name)+1);
269 _exit(1);
272 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs, 0)) || (num_dcs == 0)) {
273 /* Still offline ? Can't find DC's. */
274 messaging_send_buf(server_messaging_context(),
275 pid_to_procid(parent_pid),
276 MSG_WINBIND_FAILED_TO_GO_ONLINE,
277 (const uint8_t *)domain->name,
278 strlen(domain->name)+1);
279 _exit(0);
282 /* We got a DC. Send a message to our parent to get it to
283 try and do the same. */
285 messaging_send_buf(server_messaging_context(),
286 pid_to_procid(parent_pid),
287 MSG_WINBIND_TRY_TO_GO_ONLINE,
288 (const uint8_t *)domain->name,
289 strlen(domain->name)+1);
290 _exit(0);
293 /****************************************************************
294 Handler triggered if we're offline to try and detect a DC.
295 ****************************************************************/
297 static void check_domain_online_handler(struct tevent_context *ctx,
298 struct tevent_timer *te,
299 struct timeval now,
300 void *private_data)
302 struct winbindd_domain *domain =
303 (struct winbindd_domain *)private_data;
305 DEBUG(10,("check_domain_online_handler: called for domain "
306 "%s (online = %s)\n", domain->name,
307 domain->online ? "True" : "False" ));
309 TALLOC_FREE(domain->check_online_event);
311 /* Are we still in "startup" mode ? */
313 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
314 /* No longer in "startup" mode. */
315 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
316 domain->name ));
317 domain->startup = False;
320 /* We've been told to stay offline, so stay
321 that way. */
323 if (get_global_winbindd_state_offline()) {
324 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
325 domain->name ));
326 return;
329 /* Fork a child to test if it can contact a DC.
330 If it can then send ourselves a message to
331 cause a reconnect. */
333 fork_child_dc_connect(domain);
336 /****************************************************************
337 If we're still offline setup the timeout check.
338 ****************************************************************/
340 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
342 int wbr = lp_winbind_reconnect_delay();
344 if (domain->startup) {
345 domain->check_online_timeout = 10;
346 } else if (domain->check_online_timeout < wbr) {
347 domain->check_online_timeout = wbr;
351 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
352 void *private_data,
353 uint32_t msg_type,
354 struct server_id server_id,
355 DATA_BLOB *data)
357 const char *domain_name = (const char *)data->data;
358 struct winbindd_domain *domain;
360 domain = find_domain_from_name_noinit(domain_name);
361 if (domain == NULL) {
362 return;
365 domain->online = false;
367 DEBUG(10, ("Domain %s is marked as offline now.\n",
368 domain_name));
371 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
372 void *private_data,
373 uint32_t msg_type,
374 struct server_id server_id,
375 DATA_BLOB *data)
377 const char *domain_name = (const char *)data->data;
378 struct winbindd_domain *domain;
380 domain = find_domain_from_name_noinit(domain_name);
381 if (domain == NULL) {
382 return;
385 domain->online = true;
387 DEBUG(10, ("Domain %s is marked as online now.\n",
388 domain_name));
391 /****************************************************************
392 Set domain offline and also add handler to put us back online
393 if we detect a DC.
394 ****************************************************************/
396 void set_domain_offline(struct winbindd_domain *domain)
398 pid_t parent_pid = getppid();
400 DEBUG(10,("set_domain_offline: called for domain %s\n",
401 domain->name ));
403 TALLOC_FREE(domain->check_online_event);
405 if (domain->internal) {
406 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
407 domain->name ));
408 return;
411 domain->online = False;
413 /* Offline domains are always initialized. They're
414 re-initialized when they go back online. */
416 domain->initialized = True;
418 /* We only add the timeout handler that checks and
419 allows us to go back online when we've not
420 been told to remain offline. */
422 if (get_global_winbindd_state_offline()) {
423 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
424 domain->name ));
425 return;
428 /* If we're in startup mode, check again in 10 seconds, not in
429 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
431 calc_new_online_timeout_check(domain);
433 domain->check_online_event = tevent_add_timer(server_event_context(),
434 NULL,
435 timeval_current_ofs(domain->check_online_timeout,0),
436 check_domain_online_handler,
437 domain);
439 /* The above *has* to succeed for winbindd to work. */
440 if (!domain->check_online_event) {
441 smb_panic("set_domain_offline: failed to add online handler");
444 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
445 domain->name ));
447 /* Send a message to the parent that the domain is offline. */
448 if (parent_pid > 1 && !domain->internal) {
449 messaging_send_buf(server_messaging_context(),
450 pid_to_procid(parent_pid),
451 MSG_WINBIND_DOMAIN_OFFLINE,
452 (uint8_t *)domain->name,
453 strlen(domain->name) + 1);
456 /* Send an offline message to the idmap child when our
457 primary domain goes offline */
459 if ( domain->primary ) {
460 struct winbindd_child *idmap = idmap_child();
462 if ( idmap->pid != 0 ) {
463 messaging_send_buf(server_messaging_context(),
464 pid_to_procid(idmap->pid),
465 MSG_WINBIND_OFFLINE,
466 (const uint8_t *)domain->name,
467 strlen(domain->name)+1);
471 return;
474 /****************************************************************
475 Set domain online - if allowed.
476 ****************************************************************/
478 static void set_domain_online(struct winbindd_domain *domain)
480 pid_t parent_pid = getppid();
482 DEBUG(10,("set_domain_online: called for domain %s\n",
483 domain->name ));
485 if (domain->internal) {
486 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
487 domain->name ));
488 return;
491 if (get_global_winbindd_state_offline()) {
492 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
493 domain->name ));
494 return;
497 winbindd_set_locator_kdc_envs(domain);
499 /* If we are waiting to get a krb5 ticket, trigger immediately. */
500 ccache_regain_all_now();
502 /* Ok, we're out of any startup mode now... */
503 domain->startup = False;
505 if (domain->online == False) {
506 /* We were offline - now we're online. We default to
507 using the MS-RPC backend if we started offline,
508 and if we're going online for the first time we
509 should really re-initialize the backends and the
510 checks to see if we're talking to an AD or NT domain.
513 domain->initialized = False;
515 /* 'reconnect_methods' is the MS-RPC backend. */
516 if (domain->backend == &reconnect_methods) {
517 domain->backend = NULL;
521 /* Ensure we have no online timeout checks. */
522 domain->check_online_timeout = 0;
523 TALLOC_FREE(domain->check_online_event);
525 /* Ensure we ignore any pending child messages. */
526 messaging_deregister(server_messaging_context(),
527 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
528 messaging_deregister(server_messaging_context(),
529 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
531 domain->online = True;
533 /* Send a message to the parent that the domain is online. */
534 if (parent_pid > 1 && !domain->internal) {
535 messaging_send_buf(server_messaging_context(),
536 pid_to_procid(parent_pid),
537 MSG_WINBIND_DOMAIN_ONLINE,
538 (uint8_t *)domain->name,
539 strlen(domain->name) + 1);
542 /* Send an online message to the idmap child when our
543 primary domain comes online */
545 if ( domain->primary ) {
546 struct winbindd_child *idmap = idmap_child();
548 if ( idmap->pid != 0 ) {
549 messaging_send_buf(server_messaging_context(),
550 pid_to_procid(idmap->pid),
551 MSG_WINBIND_ONLINE,
552 (const uint8_t *)domain->name,
553 strlen(domain->name)+1);
557 return;
560 /****************************************************************
561 Requested to set a domain online.
562 ****************************************************************/
564 void set_domain_online_request(struct winbindd_domain *domain)
566 struct timeval tev;
568 DEBUG(10,("set_domain_online_request: called for domain %s\n",
569 domain->name ));
571 if (get_global_winbindd_state_offline()) {
572 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
573 domain->name ));
574 return;
577 if (domain->internal) {
578 DEBUG(10, ("set_domain_online_request: Internal domains are "
579 "always online\n"));
580 return;
583 /* We've been told it's safe to go online and
584 try and connect to a DC. But I don't believe it
585 because network manager seems to lie.
586 Wait at least 5 seconds. Heuristics suck... */
589 GetTimeOfDay(&tev);
591 /* Go into "startup" mode again. */
592 domain->startup_time = time_mono(NULL);
593 domain->startup = True;
595 tev.tv_sec += 5;
597 if (!domain->check_online_event) {
598 /* If we've come from being globally offline we
599 don't have a check online event handler set.
600 We need to add one now we're trying to go
601 back online. */
603 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
604 domain->name ));
607 TALLOC_FREE(domain->check_online_event);
609 domain->check_online_event = tevent_add_timer(server_event_context(),
610 NULL,
611 tev,
612 check_domain_online_handler,
613 domain);
615 /* The above *has* to succeed for winbindd to work. */
616 if (!domain->check_online_event) {
617 smb_panic("set_domain_online_request: failed to add online handler");
621 /****************************************************************
622 Add -ve connection cache entries for domain and realm.
623 ****************************************************************/
625 static void winbind_add_failed_connection_entry(
626 const struct winbindd_domain *domain,
627 const char *server,
628 NTSTATUS result)
630 add_failed_connection_entry(domain->name, server, result);
631 /* If this was the saf name for the last thing we talked to,
632 remove it. */
633 saf_delete(domain->name);
634 if (domain->alt_name != NULL) {
635 add_failed_connection_entry(domain->alt_name, server, result);
636 saf_delete(domain->alt_name);
638 winbindd_unset_locator_kdc_env(domain);
641 /* Choose between anonymous or authenticated connections. We need to use
642 an authenticated connection if DCs have the RestrictAnonymous registry
643 entry set > 0, or the "Additional restrictions for anonymous
644 connections" set in the win2k Local Security Policy.
646 Caller to free() result in domain, username, password
649 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
651 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
652 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
653 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
655 if (*username && **username) {
657 if (!*domain || !**domain)
658 *domain = smb_xstrdup(lp_workgroup());
660 if (!*password || !**password)
661 *password = smb_xstrdup("");
663 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
664 *domain, *username));
666 } else {
667 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
668 *username = smb_xstrdup("");
669 *domain = smb_xstrdup("");
670 *password = smb_xstrdup("");
674 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
675 struct cli_credentials **_creds)
678 TALLOC_CTX *frame = talloc_stackframe();
679 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
680 struct loadparm_context *lp_ctx;
681 char *username = NULL;
682 char *netbios_domain = NULL;
683 char *password = NULL;
684 struct cli_credentials *creds = NULL;
685 bool ok;
687 cm_get_ipc_userpass(&username, &netbios_domain, &password);
689 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
690 if (lp_ctx == NULL) {
691 DEBUG(1, ("loadparm_init_s3 failed\n"));
692 status = NT_STATUS_INTERNAL_ERROR;
693 goto fail;
696 creds = cli_credentials_init(mem_ctx);
697 if (creds == NULL) {
698 status = NT_STATUS_NO_MEMORY;
699 goto fail;
702 cli_credentials_set_conf(creds, lp_ctx);
703 cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
705 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
706 if (!ok) {
707 status = NT_STATUS_NO_MEMORY;
708 goto fail;
711 ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
712 if (!ok) {
713 status = NT_STATUS_NO_MEMORY;
714 goto fail;
717 ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
718 if (!ok) {
719 status = NT_STATUS_NO_MEMORY;
720 goto fail;
723 *_creds = creds;
724 creds = NULL;
725 status = NT_STATUS_OK;
726 fail:
727 TALLOC_FREE(creds);
728 SAFE_FREE(username);
729 SAFE_FREE(netbios_domain);
730 SAFE_FREE(password);
731 TALLOC_FREE(frame);
732 return status;
735 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
737 TALLOC_CTX *frame = talloc_stackframe();
738 char *ipc_account = NULL;
739 char *ipc_domain = NULL;
740 char *ipc_password = NULL;
741 const char *creds_account = NULL;
742 const char *creds_domain = NULL;
743 const char *creds_password = NULL;
744 bool ret = false;
746 cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
748 creds_account = cli_credentials_get_username(creds);
749 creds_domain = cli_credentials_get_domain(creds);
750 creds_password = cli_credentials_get_password(creds);
752 if (!strequal(ipc_domain, creds_domain)) {
753 goto done;
756 if (!strequal(ipc_account, creds_account)) {
757 goto done;
760 if (!strcsequal(ipc_password, creds_password)) {
761 goto done;
764 ret = true;
765 done:
766 SAFE_FREE(ipc_account);
767 SAFE_FREE(ipc_domain);
768 SAFE_FREE(ipc_password);
769 TALLOC_FREE(frame);
770 return ret;
773 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
774 fstring dcname,
775 struct sockaddr_storage *dc_ss,
776 uint32_t request_flags)
778 struct winbindd_domain *our_domain = NULL;
779 struct rpc_pipe_client *netlogon_pipe = NULL;
780 NTSTATUS result;
781 WERROR werr;
782 TALLOC_CTX *mem_ctx;
783 unsigned int orig_timeout;
784 const char *tmp = NULL;
785 const char *p;
786 struct dcerpc_binding_handle *b;
788 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
789 * moment.... */
791 if (IS_DC) {
792 return False;
795 if (domain->primary) {
796 return False;
799 our_domain = find_our_domain();
801 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
802 return False;
805 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
806 if (!NT_STATUS_IS_OK(result)) {
807 talloc_destroy(mem_ctx);
808 return False;
811 b = netlogon_pipe->binding_handle;
813 /* This call can take a long time - allow the server to time out.
814 35 seconds should do it. */
816 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
818 if (our_domain->active_directory) {
819 struct netr_DsRGetDCNameInfo *domain_info = NULL;
822 * TODO request flags are not respected in the server
823 * (and in some cases, like REQUIRE_PDC, causes an error)
825 result = dcerpc_netr_DsRGetDCName(b,
826 mem_ctx,
827 our_domain->dcname,
828 domain->name,
829 NULL,
830 NULL,
831 request_flags|DS_RETURN_DNS_NAME,
832 &domain_info,
833 &werr);
834 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
835 tmp = talloc_strdup(
836 mem_ctx, domain_info->dc_unc);
837 if (tmp == NULL) {
838 DEBUG(0, ("talloc_strdup failed\n"));
839 talloc_destroy(mem_ctx);
840 return false;
842 if (domain->alt_name == NULL) {
843 domain->alt_name = talloc_strdup(domain,
844 domain_info->domain_name);
845 if (domain->alt_name == NULL) {
846 DEBUG(0, ("talloc_strdup failed\n"));
847 talloc_destroy(mem_ctx);
848 return false;
851 if (domain->forest_name == NULL) {
852 domain->forest_name = talloc_strdup(domain,
853 domain_info->forest_name);
854 if (domain->forest_name == NULL) {
855 DEBUG(0, ("talloc_strdup failed\n"));
856 talloc_destroy(mem_ctx);
857 return false;
861 } else {
862 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
863 our_domain->dcname,
864 domain->name,
865 &tmp,
866 &werr);
869 /* And restore our original timeout. */
870 rpccli_set_timeout(netlogon_pipe, orig_timeout);
872 if (!NT_STATUS_IS_OK(result)) {
873 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
874 nt_errstr(result)));
875 talloc_destroy(mem_ctx);
876 return false;
879 if (!W_ERROR_IS_OK(werr)) {
880 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
881 win_errstr(werr)));
882 talloc_destroy(mem_ctx);
883 return false;
886 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
887 p = strip_hostname(tmp);
889 fstrcpy(dcname, p);
891 talloc_destroy(mem_ctx);
893 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
895 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
896 return False;
899 return True;
903 * Helper function to assemble trust password and account name
905 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
906 TALLOC_CTX *mem_ctx,
907 bool netlogon,
908 struct cli_credentials **_creds)
910 const struct winbindd_domain *creds_domain = NULL;
911 struct cli_credentials *creds;
912 NTSTATUS status;
913 bool force_machine_account = false;
915 /* If we are a DC and this is not our own domain */
917 if (!domain->active_directory) {
918 if (!netlogon) {
920 * For non active directory domains
921 * we can only use NTLMSSP for SMB.
923 * But the trust account is not allowed
924 * to use SMB with NTLMSSP.
926 force_machine_account = true;
930 if (IS_DC && !force_machine_account) {
931 creds_domain = domain;
932 } else {
933 creds_domain = find_our_domain();
934 if (creds_domain == NULL) {
935 return NT_STATUS_INVALID_SERVER_STATE;
939 status = pdb_get_trust_credentials(creds_domain->name,
940 creds_domain->alt_name,
941 mem_ctx,
942 &creds);
943 if (!NT_STATUS_IS_OK(status)) {
944 goto ipc_fallback;
947 if (creds_domain != domain) {
949 * We can only use schannel against a direct trust
951 cli_credentials_set_secure_channel_type(creds,
952 SEC_CHAN_NULL);
955 *_creds = creds;
956 return NT_STATUS_OK;
958 ipc_fallback:
959 if (netlogon) {
960 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
963 status = cm_get_ipc_credentials(mem_ctx, &creds);
964 if (!NT_STATUS_IS_OK(status)) {
965 return status;
968 *_creds = creds;
969 return NT_STATUS_OK;
972 /************************************************************************
973 Given a fd with a just-connected TCP connection to a DC, open a connection
974 to the pipe.
975 ************************************************************************/
977 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
978 const int sockfd,
979 const char *controller,
980 struct cli_state **cli,
981 bool *retry)
983 bool try_ipc_auth = false;
984 const char *machine_principal = NULL;
985 const char *machine_realm = NULL;
986 const char *machine_account = NULL;
987 const char *machine_domain = NULL;
988 int flags = 0;
989 struct cli_credentials *creds = NULL;
991 struct named_mutex *mutex;
993 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
994 NTSTATUS tmp_status;
995 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
997 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
999 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
1001 * If we are connecting to our own AD domain, require
1002 * smb signing to disrupt MITM attacks
1004 if (domain->primary && lp_security() == SEC_ADS) {
1005 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1007 * If we are in or are an AD domain and connecting to another
1008 * AD domain in our forest
1009 * then require smb signing to disrupt MITM attacks
1011 } else if ((lp_security() == SEC_ADS ||
1012 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)
1013 && domain->active_directory
1014 && (domain->domain_trust_attribs
1015 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
1016 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1020 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1021 controller, domain->name ));
1023 *retry = True;
1025 mutex = grab_named_mutex(talloc_tos(), controller,
1026 WINBIND_SERVER_MUTEX_WAIT_TIME);
1027 if (mutex == NULL) {
1028 close(sockfd);
1029 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1030 controller));
1031 result = NT_STATUS_POSSIBLE_DEADLOCK;
1032 goto done;
1035 *cli = cli_state_create(NULL, sockfd, controller,
1036 smb_sign_client_connections, flags);
1037 if (*cli == NULL) {
1038 close(sockfd);
1039 DEBUG(1, ("Could not cli_initialize\n"));
1040 result = NT_STATUS_NO_MEMORY;
1041 goto done;
1044 cli_set_timeout(*cli, 10000); /* 10 seconds */
1046 set_socket_options(sockfd, lp_socket_options());
1048 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
1049 lp_client_ipc_min_protocol(),
1050 lp_client_ipc_max_protocol());
1052 if (!NT_STATUS_IS_OK(result)) {
1053 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
1054 goto done;
1057 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
1058 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
1059 try_ipc_auth = true;
1060 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1061 try_ipc_auth = true;
1062 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1064 * If we are forcing on SMB signing, then we must
1065 * require authentication unless this is a one-way
1066 * trust, and we have no stored user/password
1068 try_ipc_auth = true;
1071 if (try_ipc_auth) {
1072 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
1073 if (!NT_STATUS_IS_OK(result)) {
1074 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1075 domain->name, nt_errstr(result)));
1076 goto done;
1078 } else {
1080 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1081 * would try and authentication with our machine
1082 * account password and fail. This is very rare in
1083 * the modern world however
1085 creds = cli_credentials_init_anon(talloc_tos());
1086 if (creds == NULL) {
1087 result = NT_STATUS_NO_MEMORY;
1088 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1089 domain->name, nt_errstr(result)));
1090 goto done;
1094 machine_principal = cli_credentials_get_principal(creds,
1095 talloc_tos());
1096 machine_realm = cli_credentials_get_realm(creds);
1097 machine_account = cli_credentials_get_username(creds);
1098 machine_domain = cli_credentials_get_domain(creds);
1100 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1101 "[%s] and realm [%s]\n",
1102 controller, domain->name, domain->alt_name,
1103 machine_domain, machine_account,
1104 machine_principal, machine_realm));
1106 if (cli_credentials_is_anonymous(creds)) {
1107 goto anon_fallback;
1110 winbindd_set_locator_kdc_envs(domain);
1112 result = cli_session_setup_creds(*cli, creds);
1113 if (NT_STATUS_IS_OK(result)) {
1114 goto session_setup_done;
1117 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1118 controller,
1119 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1120 nt_errstr(result)));
1123 * If we are not going to validiate the conneciton
1124 * with SMB signing, then allow us to fall back to
1125 * anonymous
1127 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1128 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1129 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1130 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1131 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1133 if (!cm_is_ipc_credentials(creds)) {
1134 goto ipc_fallback;
1137 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1138 goto done;
1141 goto anon_fallback;
1144 goto done;
1146 ipc_fallback:
1147 TALLOC_FREE(creds);
1148 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1149 if (!NT_STATUS_IS_OK(tmp_status)) {
1150 result = tmp_status;
1151 goto done;
1154 if (cli_credentials_is_anonymous(creds)) {
1155 goto anon_fallback;
1158 machine_account = cli_credentials_get_username(creds);
1159 machine_domain = cli_credentials_get_domain(creds);
1161 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1162 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1163 machine_domain, machine_account));
1165 result = cli_session_setup_creds(*cli, creds);
1166 if (NT_STATUS_IS_OK(result)) {
1167 goto session_setup_done;
1170 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1171 controller,
1172 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1173 nt_errstr(result)));
1176 * If we are not going to validiate the conneciton
1177 * with SMB signing, then allow us to fall back to
1178 * anonymous
1180 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1181 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1182 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1183 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1184 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1186 goto anon_fallback;
1189 goto done;
1191 anon_fallback:
1192 TALLOC_FREE(creds);
1194 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1195 goto done;
1198 /* Fall back to anonymous connection, this might fail later */
1199 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1200 "connection for DC %s\n",
1201 controller ));
1203 result = cli_session_setup_anon(*cli);
1204 if (NT_STATUS_IS_OK(result)) {
1205 DEBUG(5, ("Connected anonymously\n"));
1206 goto session_setup_done;
1209 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1210 controller, nt_errstr(result)));
1212 /* We can't session setup */
1213 goto done;
1215 session_setup_done:
1216 TALLOC_FREE(creds);
1219 * This should be a short term hack until
1220 * dynamic re-authentication is implemented.
1222 * See Bug 9175 - winbindd doesn't recover from
1223 * NT_STATUS_NETWORK_SESSION_EXPIRED
1225 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1226 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1229 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1230 if (!NT_STATUS_IS_OK(result)) {
1231 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1232 goto done;
1234 tcon_status = result;
1236 /* cache the server name for later connections */
1238 saf_store(domain->name, controller);
1239 if (domain->alt_name) {
1240 saf_store(domain->alt_name, controller);
1243 winbindd_set_locator_kdc_envs(domain);
1245 TALLOC_FREE(mutex);
1246 *retry = False;
1248 result = NT_STATUS_OK;
1250 done:
1251 TALLOC_FREE(mutex);
1252 TALLOC_FREE(creds);
1254 if (NT_STATUS_IS_OK(result)) {
1255 result = tcon_status;
1258 if (!NT_STATUS_IS_OK(result)) {
1259 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1260 controller, nt_errstr(result)));
1261 winbind_add_failed_connection_entry(domain, controller, result);
1262 if ((*cli) != NULL) {
1263 cli_shutdown(*cli);
1264 *cli = NULL;
1268 return result;
1271 /*******************************************************************
1272 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1273 array.
1275 Keeps the list unique by not adding duplicate entries.
1277 @param[in] mem_ctx talloc memory context to allocate from
1278 @param[in] domain_name domain of the DC
1279 @param[in] dcname name of the DC to add to the list
1280 @param[in] pss Internet address and port pair to add to the list
1281 @param[in,out] dcs array of dc_name_ip structures to add to
1282 @param[in,out] num_dcs number of dcs returned in the dcs array
1283 @return true if the list was added to, false otherwise
1284 *******************************************************************/
1286 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1287 const char *dcname, struct sockaddr_storage *pss,
1288 struct dc_name_ip **dcs, int *num)
1290 int i = 0;
1292 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1293 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1294 return False;
1297 /* Make sure there's no duplicates in the list */
1298 for (i=0; i<*num; i++)
1299 if (sockaddr_equal(
1300 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1301 (struct sockaddr *)(void *)pss))
1302 return False;
1304 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1306 if (*dcs == NULL)
1307 return False;
1309 fstrcpy((*dcs)[*num].name, dcname);
1310 (*dcs)[*num].ss = *pss;
1311 *num += 1;
1312 return True;
1315 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1316 struct sockaddr_storage *pss, uint16_t port,
1317 struct sockaddr_storage **addrs, int *num)
1319 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1321 if (*addrs == NULL) {
1322 *num = 0;
1323 return False;
1326 (*addrs)[*num] = *pss;
1327 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1329 *num += 1;
1330 return True;
1333 /*******************************************************************
1334 convert an ip to a name
1335 For an AD Domain, it checks the requirements of the request flags.
1336 *******************************************************************/
1338 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1339 const struct winbindd_domain *domain,
1340 struct sockaddr_storage *pss,
1341 char **name, uint32_t request_flags)
1343 struct ip_service ip_list;
1344 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1345 NTSTATUS status;
1346 const char *dc_name;
1347 fstring nbtname;
1348 #ifdef HAVE_ADS
1349 bool is_ad_domain = false;
1350 #endif
1351 ip_list.ss = *pss;
1352 ip_list.port = 0;
1354 #ifdef HAVE_ADS
1355 /* For active directory servers, try to get the ldap server name.
1356 None of these failures should be considered critical for now */
1358 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1359 is_ad_domain = true;
1360 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1361 is_ad_domain = domain->active_directory;
1364 if (is_ad_domain) {
1365 ADS_STRUCT *ads;
1366 ADS_STATUS ads_status;
1367 char addr[INET6_ADDRSTRLEN];
1369 print_sockaddr(addr, sizeof(addr), pss);
1371 ads = ads_init(domain->alt_name, domain->name, addr);
1372 ads->auth.flags |= ADS_AUTH_NO_BIND;
1373 ads->config.flags |= request_flags;
1374 ads->server.no_fallback = true;
1376 ads_status = ads_connect(ads);
1377 if (ADS_ERR_OK(ads_status)) {
1378 /* We got a cldap packet. */
1379 *name = talloc_strdup(mem_ctx,
1380 ads->config.ldap_server_name);
1381 if (*name == NULL) {
1382 return false;
1384 namecache_store(*name, 0x20, 1, &ip_list);
1386 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1388 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1389 if (ads_closest_dc(ads)) {
1390 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1392 /* We're going to use this KDC for this realm/domain.
1393 If we are using sites, then force the krb5 libs
1394 to use this KDC. */
1396 create_local_private_krb5_conf_for_domain(domain->alt_name,
1397 domain->name,
1398 sitename,
1399 pss);
1401 TALLOC_FREE(sitename);
1402 } else {
1403 /* use an off site KDC */
1404 create_local_private_krb5_conf_for_domain(domain->alt_name,
1405 domain->name,
1406 NULL,
1407 pss);
1409 winbindd_set_locator_kdc_envs(domain);
1411 /* Ensure we contact this DC also. */
1412 saf_store(domain->name, *name);
1413 saf_store(domain->alt_name, *name);
1416 ads_destroy( &ads );
1417 return True;
1420 ads_destroy( &ads );
1421 return false;
1423 #endif
1425 status = nbt_getdc(server_messaging_context(), 10, pss, domain->name,
1426 &domain->sid, nt_version, mem_ctx, &nt_version,
1427 &dc_name, NULL);
1428 if (NT_STATUS_IS_OK(status)) {
1429 *name = talloc_strdup(mem_ctx, dc_name);
1430 if (*name == NULL) {
1431 return false;
1433 namecache_store(*name, 0x20, 1, &ip_list);
1434 return True;
1437 /* try node status request */
1439 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1440 namecache_store(nbtname, 0x20, 1, &ip_list);
1442 if (name != NULL) {
1443 *name = talloc_strdup(mem_ctx, nbtname);
1444 if (*name == NULL) {
1445 return false;
1449 return true;
1451 return False;
1454 /*******************************************************************
1455 Retrieve a list of IP addresses for domain controllers.
1457 The array is sorted in the preferred connection order.
1459 @param[in] mem_ctx talloc memory context to allocate from
1460 @param[in] domain domain to retrieve DCs for
1461 @param[out] dcs array of dcs that will be returned
1462 @param[out] num_dcs number of dcs returned in the dcs array
1463 @return always true
1464 *******************************************************************/
1466 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1467 struct dc_name_ip **dcs, int *num_dcs,
1468 uint32_t request_flags)
1470 fstring dcname;
1471 struct sockaddr_storage ss;
1472 struct ip_service *ip_list = NULL;
1473 int iplist_size = 0;
1474 int i;
1475 bool is_our_domain;
1476 enum security_types sec = (enum security_types)lp_security();
1478 is_our_domain = strequal(domain->name, lp_workgroup());
1480 /* If not our domain, get the preferred DC, by asking our primary DC */
1481 if ( !is_our_domain
1482 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1483 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1484 num_dcs) )
1486 char addr[INET6_ADDRSTRLEN];
1487 print_sockaddr(addr, sizeof(addr), &ss);
1488 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1489 dcname, addr));
1490 return True;
1493 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1494 char *sitename = NULL;
1496 /* We need to make sure we know the local site before
1497 doing any DNS queries, as this will restrict the
1498 get_sorted_dc_list() call below to only fetching
1499 DNS records for the correct site. */
1501 /* Find any DC to get the site record.
1502 We deliberately don't care about the
1503 return here. */
1505 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1507 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1508 if (sitename) {
1510 /* Do the site-specific AD dns lookup first. */
1511 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1512 &iplist_size, True);
1514 /* Add ips to the DC array. We don't look up the name
1515 of the DC in this function, but we fill in the char*
1516 of the ip now to make the failed connection cache
1517 work */
1518 for ( i=0; i<iplist_size; i++ ) {
1519 char addr[INET6_ADDRSTRLEN];
1520 print_sockaddr(addr, sizeof(addr),
1521 &ip_list[i].ss);
1522 add_one_dc_unique(mem_ctx,
1523 domain->name,
1524 addr,
1525 &ip_list[i].ss,
1526 dcs,
1527 num_dcs);
1530 SAFE_FREE(ip_list);
1531 TALLOC_FREE(sitename);
1532 iplist_size = 0;
1535 /* Now we add DCs from the main AD DNS lookup. */
1536 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1537 &iplist_size, True);
1539 for ( i=0; i<iplist_size; i++ ) {
1540 char addr[INET6_ADDRSTRLEN];
1541 print_sockaddr(addr, sizeof(addr),
1542 &ip_list[i].ss);
1543 add_one_dc_unique(mem_ctx,
1544 domain->name,
1545 addr,
1546 &ip_list[i].ss,
1547 dcs,
1548 num_dcs);
1551 SAFE_FREE(ip_list);
1552 iplist_size = 0;
1555 /* Try standard netbios queries if no ADS and fall back to DNS queries
1556 * if alt_name is available */
1557 if (*num_dcs == 0) {
1558 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1559 false);
1560 if (iplist_size == 0) {
1561 if (domain->alt_name != NULL) {
1562 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1563 &iplist_size, true);
1567 for ( i=0; i<iplist_size; i++ ) {
1568 char addr[INET6_ADDRSTRLEN];
1569 print_sockaddr(addr, sizeof(addr),
1570 &ip_list[i].ss);
1571 add_one_dc_unique(mem_ctx,
1572 domain->name,
1573 addr,
1574 &ip_list[i].ss,
1575 dcs,
1576 num_dcs);
1579 SAFE_FREE(ip_list);
1580 iplist_size = 0;
1583 return True;
1586 /*******************************************************************
1587 Find and make a connection to a DC in the given domain.
1589 @param[in] mem_ctx talloc memory context to allocate from
1590 @param[in] domain domain to find a dc in
1591 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1592 @param[out] pss DC Internet address and port
1593 @param[out] fd fd of the open socket connected to the newly found dc
1594 @return true when a DC connection is made, false otherwise
1595 *******************************************************************/
1597 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1598 struct winbindd_domain *domain,
1599 char **dcname, struct sockaddr_storage *pss, int *fd,
1600 uint32_t request_flags)
1602 struct dc_name_ip *dcs = NULL;
1603 int num_dcs = 0;
1605 const char **dcnames = NULL;
1606 size_t num_dcnames = 0;
1608 struct sockaddr_storage *addrs = NULL;
1609 int num_addrs = 0;
1611 int i;
1612 size_t fd_index;
1614 NTSTATUS status;
1616 *fd = -1;
1618 again:
1619 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1620 return False;
1622 for (i=0; i<num_dcs; i++) {
1624 if (!add_string_to_array(mem_ctx, dcs[i].name,
1625 &dcnames, &num_dcnames)) {
1626 return False;
1628 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1629 &addrs, &num_addrs)) {
1630 return False;
1634 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1635 return False;
1637 if ((addrs == NULL) || (dcnames == NULL))
1638 return False;
1640 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1641 num_addrs, 0, 10, fd, &fd_index, NULL);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 for (i=0; i<num_dcs; i++) {
1644 char ab[INET6_ADDRSTRLEN];
1645 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1646 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1647 "domain %s address %s. Error was %s\n",
1648 domain->name, ab, nt_errstr(status) ));
1649 winbind_add_failed_connection_entry(domain,
1650 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1652 return False;
1655 *pss = addrs[fd_index];
1657 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1658 /* Ok, we've got a name for the DC */
1659 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1660 if (*dcname == NULL) {
1661 return false;
1663 return true;
1666 /* Try to figure out the name */
1667 if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1668 return True;
1671 /* We can not continue without the DC's name */
1672 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1673 NT_STATUS_UNSUCCESSFUL);
1675 /* Throw away all arrays as we're doing this again. */
1676 TALLOC_FREE(dcs);
1677 num_dcs = 0;
1679 TALLOC_FREE(dcnames);
1680 num_dcnames = 0;
1682 TALLOC_FREE(addrs);
1683 num_addrs = 0;
1685 close(*fd);
1686 *fd = -1;
1688 goto again;
1691 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1693 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1694 domain_name);
1697 static void store_current_dc_in_gencache(const char *domain_name,
1698 const char *dc_name,
1699 struct cli_state *cli)
1701 char addr[INET6_ADDRSTRLEN];
1702 char *key = NULL;
1703 char *value = NULL;
1705 if (!cli_state_is_connected(cli)) {
1706 return;
1709 print_sockaddr(addr, sizeof(addr),
1710 smbXcli_conn_remote_sockaddr(cli->conn));
1712 key = current_dc_key(talloc_tos(), domain_name);
1713 if (key == NULL) {
1714 goto done;
1717 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1718 if (value == NULL) {
1719 goto done;
1722 gencache_set(key, value, 0x7fffffff);
1723 done:
1724 TALLOC_FREE(value);
1725 TALLOC_FREE(key);
1728 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1729 const char *domain_name,
1730 char **p_dc_name, char **p_dc_ip)
1732 char *key, *p;
1733 char *value = NULL;
1734 bool ret = false;
1735 char *dc_name = NULL;
1736 char *dc_ip = NULL;
1738 key = current_dc_key(talloc_tos(), domain_name);
1739 if (key == NULL) {
1740 goto done;
1742 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1743 goto done;
1745 p = strchr(value, ' ');
1746 if (p == NULL) {
1747 goto done;
1749 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1750 if (dc_ip == NULL) {
1751 goto done;
1753 dc_name = talloc_strdup(mem_ctx, p+1);
1754 if (dc_name == NULL) {
1755 goto done;
1758 if (p_dc_ip != NULL) {
1759 *p_dc_ip = dc_ip;
1760 dc_ip = NULL;
1762 if (p_dc_name != NULL) {
1763 *p_dc_name = dc_name;
1764 dc_name = NULL;
1766 ret = true;
1767 done:
1768 TALLOC_FREE(dc_name);
1769 TALLOC_FREE(dc_ip);
1770 TALLOC_FREE(key);
1771 TALLOC_FREE(value);
1772 return ret;
1775 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1776 const struct ndr_interface_table *table,
1777 struct rpc_pipe_client **ret_pipe)
1779 struct rpc_pipe_client *cli = NULL;
1780 const struct auth_session_info *session_info;
1781 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1784 session_info = get_session_info_system();
1785 SMB_ASSERT(session_info != NULL);
1787 /* create a connection to the specified pipe */
1788 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1789 status = rpc_pipe_open_interface(mem_ctx,
1790 table,
1791 session_info,
1792 NULL,
1793 NULL,
1794 server_messaging_context(),
1795 &cli);
1796 } else {
1797 status = rpc_pipe_open_internal(mem_ctx,
1798 table,
1799 session_info,
1800 NULL,
1801 NULL,
1802 server_messaging_context(),
1803 &cli);
1805 if (!NT_STATUS_IS_OK(status)) {
1806 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1807 table->name, nt_errstr(status)));
1808 return status;
1811 if (ret_pipe) {
1812 *ret_pipe = cli;
1815 return NT_STATUS_OK;
1818 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1819 struct winbindd_cm_conn *new_conn,
1820 bool need_rw_dc)
1822 TALLOC_CTX *mem_ctx;
1823 NTSTATUS result;
1824 char *saf_servername;
1825 int retries;
1826 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1828 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1829 set_domain_offline(domain);
1830 return NT_STATUS_NO_MEMORY;
1833 saf_servername = saf_fetch(mem_ctx, domain->name );
1835 /* we have to check the server affinity cache here since
1836 later we select a DC based on response time and not preference */
1838 /* Check the negative connection cache
1839 before talking to it. It going down may have
1840 triggered the reconnection. */
1842 if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1843 struct sockaddr_storage ss;
1844 char *dcname = NULL;
1845 bool resolved = true;
1847 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1848 saf_servername, domain->name));
1850 /* convert an ip address to a name */
1851 if (is_ipaddress(saf_servername)) {
1852 if (!interpret_string_addr(&ss, saf_servername,
1853 AI_NUMERICHOST)) {
1854 TALLOC_FREE(mem_ctx);
1855 return NT_STATUS_UNSUCCESSFUL;
1857 } else {
1858 if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1859 resolved = false;
1863 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1864 domain->dcname = talloc_strdup(domain,
1865 dcname);
1866 if (domain->dcname == NULL) {
1867 TALLOC_FREE(mem_ctx);
1868 return NT_STATUS_NO_MEMORY;
1871 domain->dcaddr = ss;
1872 } else {
1873 winbind_add_failed_connection_entry(domain, saf_servername,
1874 NT_STATUS_UNSUCCESSFUL);
1878 for (retries = 0; retries < 3; retries++) {
1879 int fd = -1;
1880 bool retry = False;
1881 char *dcname = NULL;
1883 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1885 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1886 domain->dcname ? domain->dcname : "", domain->name));
1888 if (domain->dcname != NULL &&
1889 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1890 domain->dcname)))
1892 NTSTATUS status;
1894 status = smbsock_connect(&domain->dcaddr, 0,
1895 NULL, -1, NULL, -1,
1896 &fd, NULL, 10);
1897 if (!NT_STATUS_IS_OK(status)) {
1898 fd = -1;
1902 if ((fd == -1) &&
1903 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1905 /* This is the one place where we will
1906 set the global winbindd offline state
1907 to true, if a "WINBINDD_OFFLINE" entry
1908 is found in the winbindd cache. */
1909 set_global_winbindd_state_offline();
1910 break;
1912 if (dcname != NULL) {
1913 talloc_free(domain->dcname);
1915 domain->dcname = talloc_move(domain, &dcname);
1916 if (domain->dcname == NULL) {
1917 result = NT_STATUS_NO_MEMORY;
1918 break;
1922 new_conn->cli = NULL;
1924 result = cm_prepare_connection(domain, fd, domain->dcname,
1925 &new_conn->cli, &retry);
1926 if (!NT_STATUS_IS_OK(result)) {
1927 /* Don't leak the smb connection socket */
1928 close(fd);
1931 if (!retry)
1932 break;
1935 if (NT_STATUS_IS_OK(result)) {
1936 bool seal_pipes = true;
1938 winbindd_set_locator_kdc_envs(domain);
1940 if (domain->online == False) {
1941 /* We're changing state from offline to online. */
1942 set_global_winbindd_state_online();
1944 set_domain_online(domain);
1947 * Much as I hate global state, this seems to be the point
1948 * where we can be certain that we have a proper connection to
1949 * a DC. wbinfo --dc-info needs that information, store it in
1950 * gencache with a looong timeout. This will need revisiting
1951 * once we start to connect to multiple DCs, wbcDcInfo is
1952 * already prepared for that.
1954 store_current_dc_in_gencache(domain->name, domain->dcname,
1955 new_conn->cli);
1957 seal_pipes = lp_winbind_sealed_pipes();
1958 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1959 domain->name,
1960 seal_pipes);
1962 if (seal_pipes) {
1963 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1964 } else {
1965 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1967 } else {
1968 /* Ensure we setup the retry handler. */
1969 set_domain_offline(domain);
1972 talloc_destroy(mem_ctx);
1973 return result;
1976 /* Close down all open pipes on a connection. */
1978 void invalidate_cm_connection(struct winbindd_domain *domain)
1980 NTSTATUS result;
1981 struct winbindd_cm_conn *conn = &domain->conn;
1983 /* We're closing down a possibly dead
1984 connection. Don't have impossibly long (10s) timeouts. */
1986 if (conn->cli) {
1987 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1990 if (conn->samr_pipe != NULL) {
1991 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1992 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1993 talloc_tos(),
1994 &conn->sam_connect_handle,
1995 &result);
1997 TALLOC_FREE(conn->samr_pipe);
1998 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1999 if (conn->cli) {
2000 cli_set_timeout(conn->cli, 500);
2004 if (conn->lsa_pipe != NULL) {
2005 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2006 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2007 talloc_tos(),
2008 &conn->lsa_policy,
2009 &result);
2011 TALLOC_FREE(conn->lsa_pipe);
2012 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2013 if (conn->cli) {
2014 cli_set_timeout(conn->cli, 500);
2018 if (conn->lsa_pipe_tcp != NULL) {
2019 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2020 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2021 talloc_tos(),
2022 &conn->lsa_policy,
2023 &result);
2025 TALLOC_FREE(conn->lsa_pipe_tcp);
2026 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2027 if (conn->cli) {
2028 cli_set_timeout(conn->cli, 500);
2032 if (conn->netlogon_pipe != NULL) {
2033 TALLOC_FREE(conn->netlogon_pipe);
2034 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2035 if (conn->cli) {
2036 cli_set_timeout(conn->cli, 500);
2040 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2041 conn->netlogon_force_reauth = false;
2042 TALLOC_FREE(conn->netlogon_creds_ctx);
2044 if (conn->cli) {
2045 cli_shutdown(conn->cli);
2048 conn->cli = NULL;
2051 void close_conns_after_fork(void)
2053 struct winbindd_domain *domain;
2054 struct winbindd_cli_state *cli_state;
2056 for (domain = domain_list(); domain; domain = domain->next) {
2058 * first close the low level SMB TCP connection
2059 * so that we don't generate any SMBclose
2060 * requests in invalidate_cm_connection()
2062 if (cli_state_is_connected(domain->conn.cli)) {
2063 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2066 invalidate_cm_connection(domain);
2069 for (cli_state = winbindd_client_list();
2070 cli_state != NULL;
2071 cli_state = cli_state->next) {
2072 if (cli_state->sock >= 0) {
2073 close(cli_state->sock);
2074 cli_state->sock = -1;
2079 static bool connection_ok(struct winbindd_domain *domain)
2081 bool ok;
2083 ok = cli_state_is_connected(domain->conn.cli);
2084 if (!ok) {
2085 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2086 domain->dcname, domain->name));
2087 return False;
2090 if (domain->online == False) {
2091 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2092 return False;
2095 return True;
2098 /* Initialize a new connection up to the RPC BIND.
2099 Bypass online status check so always does network calls. */
2101 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2103 NTSTATUS result;
2104 bool skip_connection = domain->internal;
2105 if (need_rw_dc && domain->rodc) {
2106 skip_connection = false;
2109 /* Internal connections never use the network. */
2110 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2111 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2114 /* Still ask the internal LSA and SAMR server about the local domain */
2115 if (skip_connection || connection_ok(domain)) {
2116 if (!domain->initialized) {
2117 set_dc_type_and_flags(domain);
2119 return NT_STATUS_OK;
2122 invalidate_cm_connection(domain);
2124 if (!domain->primary && !domain->initialized) {
2126 * Before we connect to a trust, work out if it is an
2127 * AD domain by asking our own domain.
2129 set_dc_type_and_flags_trustinfo(domain);
2132 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2134 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2135 set_dc_type_and_flags(domain);
2138 return result;
2141 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2143 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2144 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2147 if (domain->initialized && !domain->online) {
2148 /* We check for online status elsewhere. */
2149 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2152 return init_dc_connection_network(domain, need_rw_dc);
2155 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2157 NTSTATUS status;
2159 status = init_dc_connection(domain, need_rw_dc);
2160 if (!NT_STATUS_IS_OK(status)) {
2161 return status;
2164 if (!domain->internal && domain->conn.cli == NULL) {
2165 /* happens for trusted domains without inbound trust */
2166 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2169 return NT_STATUS_OK;
2172 /******************************************************************************
2173 Set the trust flags (direction and forest location) for a domain
2174 ******************************************************************************/
2176 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2178 struct winbindd_domain *our_domain;
2179 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2180 WERROR werr;
2181 struct netr_DomainTrustList trusts;
2182 int i;
2183 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2184 NETR_TRUST_FLAG_OUTBOUND |
2185 NETR_TRUST_FLAG_INBOUND);
2186 struct rpc_pipe_client *cli;
2187 TALLOC_CTX *mem_ctx = NULL;
2188 struct dcerpc_binding_handle *b;
2190 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2192 /* Our primary domain doesn't need to worry about trust flags.
2193 Force it to go through the network setup */
2194 if ( domain->primary ) {
2195 return False;
2198 mem_ctx = talloc_stackframe();
2199 our_domain = find_our_domain();
2200 if (our_domain->internal) {
2201 result = init_dc_connection(our_domain, false);
2202 if (!NT_STATUS_IS_OK(result)) {
2203 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2204 "Not able to make a connection to our domain: %s\n",
2205 nt_errstr(result)));
2206 TALLOC_FREE(mem_ctx);
2207 return false;
2211 /* This won't work unless our domain is AD */
2212 if ( !our_domain->active_directory ) {
2213 TALLOC_FREE(mem_ctx);
2214 return False;
2217 if (our_domain->internal) {
2218 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2219 } else if (!connection_ok(our_domain)) {
2220 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2221 "No connection to our domain!\n"));
2222 TALLOC_FREE(mem_ctx);
2223 return False;
2224 } else {
2225 result = cm_connect_netlogon(our_domain, &cli);
2228 if (!NT_STATUS_IS_OK(result)) {
2229 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2230 "a connection to %s for PIPE_NETLOGON (%s)\n",
2231 domain->name, nt_errstr(result)));
2232 TALLOC_FREE(mem_ctx);
2233 return False;
2235 b = cli->binding_handle;
2237 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2238 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2239 cli->desthost,
2240 flags,
2241 &trusts,
2242 &werr);
2243 if (!NT_STATUS_IS_OK(result)) {
2244 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2245 "failed to query trusted domain list: %s\n",
2246 nt_errstr(result)));
2247 TALLOC_FREE(mem_ctx);
2248 return false;
2250 if (!W_ERROR_IS_OK(werr)) {
2251 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2252 "failed to query trusted domain list: %s\n",
2253 win_errstr(werr)));
2254 TALLOC_FREE(mem_ctx);
2255 return false;
2258 /* Now find the domain name and get the flags */
2260 for ( i=0; i<trusts.count; i++ ) {
2261 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2262 domain->domain_flags = trusts.array[i].trust_flags;
2263 domain->domain_type = trusts.array[i].trust_type;
2264 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2266 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2267 domain->active_directory = True;
2269 /* This flag is only set if the domain is *our*
2270 primary domain and the primary domain is in
2271 native mode */
2273 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2275 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2276 "native mode.\n", domain->name,
2277 domain->native_mode ? "" : "NOT "));
2279 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2280 "running active directory.\n", domain->name,
2281 domain->active_directory ? "" : "NOT "));
2283 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2285 domain->initialized = True;
2287 break;
2291 TALLOC_FREE(mem_ctx);
2293 return domain->initialized;
2296 /******************************************************************************
2297 We can 'sense' certain things about the DC by it's replies to certain
2298 questions.
2300 This tells us if this particular remote server is Active Directory, and if it
2301 is native mode.
2302 ******************************************************************************/
2304 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2306 NTSTATUS status, result;
2307 WERROR werr;
2308 TALLOC_CTX *mem_ctx = NULL;
2309 struct rpc_pipe_client *cli = NULL;
2310 struct policy_handle pol;
2311 union dssetup_DsRoleInfo info;
2312 union lsa_PolicyInformation *lsa_info = NULL;
2314 if (!domain->internal && !connection_ok(domain)) {
2315 return;
2318 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2319 domain->name);
2320 if (!mem_ctx) {
2321 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2322 return;
2325 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2327 if (domain->internal) {
2328 status = wb_open_internal_pipe(mem_ctx,
2329 &ndr_table_dssetup,
2330 &cli);
2331 } else {
2332 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2333 &ndr_table_dssetup,
2334 &cli);
2337 if (!NT_STATUS_IS_OK(status)) {
2338 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2339 "PI_DSSETUP on domain %s: (%s)\n",
2340 domain->name, nt_errstr(status)));
2342 /* if this is just a non-AD domain we need to continue
2343 * identifying so that we can in the end return with
2344 * domain->initialized = True - gd */
2346 goto no_dssetup;
2349 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2350 DS_ROLE_BASIC_INFORMATION,
2351 &info,
2352 &werr);
2353 TALLOC_FREE(cli);
2355 if (NT_STATUS_IS_OK(status)) {
2356 result = werror_to_ntstatus(werr);
2358 if (!NT_STATUS_IS_OK(status)) {
2359 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2360 "on domain %s failed: (%s)\n",
2361 domain->name, nt_errstr(status)));
2363 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2364 * every opcode on the DSSETUP pipe, continue with
2365 * no_dssetup mode here as well to get domain->initialized
2366 * set - gd */
2368 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2369 goto no_dssetup;
2372 TALLOC_FREE(mem_ctx);
2373 return;
2376 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2377 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2378 domain->native_mode = True;
2379 } else {
2380 domain->native_mode = False;
2383 no_dssetup:
2384 if (domain->internal) {
2385 status = wb_open_internal_pipe(mem_ctx,
2386 &ndr_table_lsarpc,
2387 &cli);
2388 } else {
2389 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2390 &ndr_table_lsarpc, &cli);
2392 if (!NT_STATUS_IS_OK(status)) {
2393 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2394 "PI_LSARPC on domain %s: (%s)\n",
2395 domain->name, nt_errstr(status)));
2396 TALLOC_FREE(cli);
2397 TALLOC_FREE(mem_ctx);
2398 return;
2401 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2402 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2404 if (NT_STATUS_IS_OK(status)) {
2405 /* This particular query is exactly what Win2k clients use
2406 to determine that the DC is active directory */
2407 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2408 &pol,
2409 LSA_POLICY_INFO_DNS,
2410 &lsa_info,
2411 &result);
2414 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2415 domain->active_directory = True;
2417 if (lsa_info->dns.name.string) {
2418 if (!strequal(domain->name, lsa_info->dns.name.string))
2420 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2421 "for domain %s claimed it was a DC "
2422 "for domain %s, refusing to "
2423 "initialize\n",
2424 domain->name,
2425 lsa_info->dns.name.string));
2426 TALLOC_FREE(cli);
2427 TALLOC_FREE(mem_ctx);
2428 return;
2430 talloc_free(domain->name);
2431 domain->name = talloc_strdup(domain,
2432 lsa_info->dns.name.string);
2433 if (domain->name == NULL) {
2434 goto done;
2438 if (lsa_info->dns.dns_domain.string) {
2439 if (domain->alt_name != NULL &&
2440 !strequal(domain->alt_name,
2441 lsa_info->dns.dns_domain.string))
2443 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2444 "for domain %s (%s) claimed it was "
2445 "a DC for domain %s, refusing to "
2446 "initialize\n",
2447 domain->alt_name, domain->name,
2448 lsa_info->dns.dns_domain.string));
2449 TALLOC_FREE(cli);
2450 TALLOC_FREE(mem_ctx);
2451 return;
2453 talloc_free(domain->alt_name);
2454 domain->alt_name =
2455 talloc_strdup(domain,
2456 lsa_info->dns.dns_domain.string);
2457 if (domain->alt_name == NULL) {
2458 goto done;
2462 /* See if we can set some domain trust flags about
2463 ourself */
2465 if (lsa_info->dns.dns_forest.string) {
2466 talloc_free(domain->forest_name);
2467 domain->forest_name =
2468 talloc_strdup(domain,
2469 lsa_info->dns.dns_forest.string);
2470 if (domain->forest_name == NULL) {
2471 goto done;
2474 if (strequal(domain->forest_name, domain->alt_name)) {
2475 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2479 if (lsa_info->dns.sid) {
2480 if (!is_null_sid(&domain->sid) &&
2481 !dom_sid_equal(&domain->sid,
2482 lsa_info->dns.sid))
2484 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2485 "for domain %s (%s) claimed it was "
2486 "a DC for domain %s, refusing to "
2487 "initialize\n",
2488 dom_sid_string(talloc_tos(),
2489 &domain->sid),
2490 domain->name,
2491 dom_sid_string(talloc_tos(),
2492 lsa_info->dns.sid)));
2493 TALLOC_FREE(cli);
2494 TALLOC_FREE(mem_ctx);
2495 return;
2497 sid_copy(&domain->sid, lsa_info->dns.sid);
2499 } else {
2500 domain->active_directory = False;
2502 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2503 SEC_FLAG_MAXIMUM_ALLOWED,
2504 &pol);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 goto done;
2510 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2511 &pol,
2512 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2513 &lsa_info,
2514 &result);
2515 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2517 if (lsa_info->account_domain.name.string) {
2518 if (!strequal(domain->name,
2519 lsa_info->account_domain.name.string))
2521 DEBUG(1,
2522 ("set_dc_type_and_flags_connect: "
2523 "DC for domain %s claimed it was"
2524 " a DC for domain %s, refusing "
2525 "to initialize\n", domain->name,
2526 lsa_info->
2527 account_domain.name.string));
2528 TALLOC_FREE(cli);
2529 TALLOC_FREE(mem_ctx);
2530 return;
2532 talloc_free(domain->name);
2533 domain->name =
2534 talloc_strdup(domain,
2535 lsa_info->account_domain.name.string);
2538 if (lsa_info->account_domain.sid) {
2539 if (!is_null_sid(&domain->sid) &&
2540 !dom_sid_equal(&domain->sid,
2541 lsa_info->account_domain.sid))
2543 DEBUG(1,
2544 ("set_dc_type_and_flags_connect: "
2545 "DC for domain %s (%s) claimed "
2546 "it was a DC for domain %s, "
2547 "refusing to initialize\n",
2548 dom_sid_string(talloc_tos(),
2549 &domain->sid),
2550 domain->name,
2551 dom_sid_string(talloc_tos(),
2552 lsa_info->account_domain.sid)));
2553 TALLOC_FREE(cli);
2554 TALLOC_FREE(mem_ctx);
2555 return;
2557 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2561 done:
2563 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2564 domain->name, domain->native_mode ? "" : "NOT "));
2566 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2567 domain->name, domain->active_directory ? "" : "NOT "));
2569 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2571 TALLOC_FREE(cli);
2573 TALLOC_FREE(mem_ctx);
2575 domain->initialized = True;
2578 /**********************************************************************
2579 Set the domain_flags (trust attributes, domain operating modes, etc...
2580 ***********************************************************************/
2582 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2584 /* we always have to contact our primary domain */
2586 if ( domain->primary || domain->internal) {
2587 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2588 "primary or internal domain\n"));
2589 set_dc_type_and_flags_connect( domain );
2590 return;
2593 /* Use our DC to get the information if possible */
2595 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2596 /* Otherwise, fallback to contacting the
2597 domain directly */
2598 set_dc_type_and_flags_connect( domain );
2601 return;
2606 /**********************************************************************
2607 ***********************************************************************/
2609 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2610 struct netlogon_creds_cli_context **ppdc)
2612 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2613 struct rpc_pipe_client *netlogon_pipe;
2615 *ppdc = NULL;
2617 if ((!IS_DC) && (!domain->primary)) {
2618 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2621 if (domain->conn.netlogon_creds_ctx != NULL) {
2622 *ppdc = domain->conn.netlogon_creds_ctx;
2623 return NT_STATUS_OK;
2626 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2627 if (!NT_STATUS_IS_OK(result)) {
2628 return result;
2631 return NT_STATUS_OK;
2634 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2635 bool need_rw_dc,
2636 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2638 struct winbindd_cm_conn *conn;
2639 NTSTATUS status, result;
2640 struct netlogon_creds_cli_context *p_creds;
2641 struct cli_credentials *creds = NULL;
2642 bool retry = false; /* allow one retry attempt for expired session */
2644 if (sid_check_is_our_sam(&domain->sid)) {
2645 if (domain->rodc == false || need_rw_dc == false) {
2646 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2650 if (IS_AD_DC) {
2652 * In theory we should not use SAMR within
2653 * winbindd at all, but that's a larger task to
2654 * remove this and avoid breaking existing
2655 * setups.
2657 * At least as AD DC we have the restriction
2658 * to avoid SAMR against trusted domains,
2659 * as there're no existing setups.
2661 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2664 retry:
2665 status = init_dc_connection_rpc(domain, need_rw_dc);
2666 if (!NT_STATUS_IS_OK(status)) {
2667 return status;
2670 conn = &domain->conn;
2672 if (rpccli_is_connected(conn->samr_pipe)) {
2673 goto done;
2676 TALLOC_FREE(conn->samr_pipe);
2679 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2680 * sign and sealed pipe using the machine account password by
2681 * preference. If we can't - try schannel, if that fails, try
2682 * anonymous.
2685 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2686 if (!NT_STATUS_IS_OK(result)) {
2687 DEBUG(10, ("cm_connect_sam: No user available for "
2688 "domain %s, trying schannel\n", domain->name));
2689 goto schannel;
2692 if (cli_credentials_is_anonymous(creds)) {
2693 goto anonymous;
2697 * We have an authenticated connection. Use a SPNEGO
2698 * authenticated SAMR pipe with sign & seal.
2700 status = cli_rpc_pipe_open_with_creds(conn->cli,
2701 &ndr_table_samr,
2702 NCACN_NP,
2703 DCERPC_AUTH_TYPE_SPNEGO,
2704 conn->auth_level,
2705 smbXcli_conn_remote_name(conn->cli->conn),
2706 creds,
2707 &conn->samr_pipe);
2709 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2710 && !retry) {
2711 invalidate_cm_connection(domain);
2712 retry = true;
2713 goto retry;
2716 if (!NT_STATUS_IS_OK(status)) {
2717 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2718 "pipe for domain %s using NTLMSSP "
2719 "authenticated pipe: user %s. Error was "
2720 "%s\n", domain->name,
2721 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2722 nt_errstr(status)));
2723 goto schannel;
2726 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2727 "domain %s using NTLMSSP authenticated "
2728 "pipe: user %s\n", domain->name,
2729 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2731 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2732 conn->samr_pipe->desthost,
2733 SEC_FLAG_MAXIMUM_ALLOWED,
2734 &conn->sam_connect_handle,
2735 &result);
2737 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2738 invalidate_cm_connection(domain);
2739 TALLOC_FREE(conn->samr_pipe);
2740 retry = true;
2741 goto retry;
2744 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2745 goto open_domain;
2747 if (NT_STATUS_IS_OK(status)) {
2748 status = result;
2751 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2752 "failed for domain %s, error was %s. Trying schannel\n",
2753 domain->name, nt_errstr(status) ));
2754 TALLOC_FREE(conn->samr_pipe);
2756 schannel:
2758 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2760 status = cm_get_schannel_creds(domain, &p_creds);
2761 if (!NT_STATUS_IS_OK(status)) {
2762 /* If this call fails - conn->cli can now be NULL ! */
2763 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2764 "for domain %s (error %s), trying anon\n",
2765 domain->name,
2766 nt_errstr(status) ));
2767 goto anonymous;
2769 TALLOC_FREE(creds);
2770 status = cli_rpc_pipe_open_schannel_with_creds(
2771 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2772 &conn->samr_pipe);
2774 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2775 && !retry) {
2776 invalidate_cm_connection(domain);
2777 retry = true;
2778 goto retry;
2781 if (!NT_STATUS_IS_OK(status)) {
2782 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2783 "domain %s using schannel. Error was %s\n",
2784 domain->name, nt_errstr(status) ));
2785 goto anonymous;
2787 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2788 "schannel.\n", domain->name ));
2790 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2791 conn->samr_pipe->desthost,
2792 SEC_FLAG_MAXIMUM_ALLOWED,
2793 &conn->sam_connect_handle,
2794 &result);
2796 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2797 invalidate_cm_connection(domain);
2798 TALLOC_FREE(conn->samr_pipe);
2799 retry = true;
2800 goto retry;
2803 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2804 goto open_domain;
2806 if (NT_STATUS_IS_OK(status)) {
2807 status = result;
2809 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2810 "for domain %s, error was %s. Trying anonymous\n",
2811 domain->name, nt_errstr(status) ));
2812 TALLOC_FREE(conn->samr_pipe);
2814 anonymous:
2816 /* Finally fall back to anonymous. */
2817 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2818 status = NT_STATUS_DOWNGRADE_DETECTED;
2819 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2820 "without connection level security, "
2821 "must set 'winbind sealed pipes = false' and "
2822 "'require strong key = false' to proceed: %s\n",
2823 domain->name, nt_errstr(status)));
2824 goto done;
2826 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2827 &conn->samr_pipe);
2829 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2830 && !retry) {
2831 invalidate_cm_connection(domain);
2832 retry = true;
2833 goto retry;
2836 if (!NT_STATUS_IS_OK(status)) {
2837 goto done;
2840 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2841 conn->samr_pipe->desthost,
2842 SEC_FLAG_MAXIMUM_ALLOWED,
2843 &conn->sam_connect_handle,
2844 &result);
2846 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2847 invalidate_cm_connection(domain);
2848 TALLOC_FREE(conn->samr_pipe);
2849 retry = true;
2850 goto retry;
2853 if (!NT_STATUS_IS_OK(status)) {
2854 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2855 "for domain %s Error was %s\n",
2856 domain->name, nt_errstr(status) ));
2857 goto done;
2859 if (!NT_STATUS_IS_OK(result)) {
2860 status = result;
2861 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2862 "for domain %s Error was %s\n",
2863 domain->name, nt_errstr(result)));
2864 goto done;
2867 open_domain:
2868 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2869 mem_ctx,
2870 &conn->sam_connect_handle,
2871 SEC_FLAG_MAXIMUM_ALLOWED,
2872 &domain->sid,
2873 &conn->sam_domain_handle,
2874 &result);
2875 if (!NT_STATUS_IS_OK(status)) {
2876 goto done;
2879 status = result;
2880 done:
2882 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2884 * if we got access denied, we might just have no access rights
2885 * to talk to the remote samr server server (e.g. when we are a
2886 * PDC and we are connecting a w2k8 pdc via an interdomain
2887 * trust). In that case do not invalidate the whole connection
2888 * stack
2890 TALLOC_FREE(conn->samr_pipe);
2891 ZERO_STRUCT(conn->sam_domain_handle);
2892 return status;
2893 } else if (!NT_STATUS_IS_OK(status)) {
2894 invalidate_cm_connection(domain);
2895 return status;
2898 *cli = conn->samr_pipe;
2899 *sam_handle = conn->sam_domain_handle;
2900 return status;
2903 /**********************************************************************
2904 open an schanneld ncacn_ip_tcp connection to LSA
2905 ***********************************************************************/
2907 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2908 TALLOC_CTX *mem_ctx,
2909 struct rpc_pipe_client **cli)
2911 struct winbindd_cm_conn *conn;
2912 struct netlogon_creds_cli_context *p_creds = NULL;
2913 NTSTATUS status;
2915 DEBUG(10,("cm_connect_lsa_tcp\n"));
2917 status = init_dc_connection_rpc(domain, false);
2918 if (!NT_STATUS_IS_OK(status)) {
2919 return status;
2922 conn = &domain->conn;
2925 * rpccli_is_connected handles more error cases
2927 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2928 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2929 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2930 goto done;
2933 TALLOC_FREE(conn->lsa_pipe_tcp);
2935 status = cm_get_schannel_creds(domain, &p_creds);
2936 if (!NT_STATUS_IS_OK(status)) {
2937 goto done;
2940 status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
2941 &ndr_table_lsarpc,
2942 NCACN_IP_TCP,
2943 p_creds,
2944 &conn->lsa_pipe_tcp);
2945 if (!NT_STATUS_IS_OK(status)) {
2946 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2947 nt_errstr(status)));
2948 goto done;
2951 done:
2952 if (!NT_STATUS_IS_OK(status)) {
2953 TALLOC_FREE(conn->lsa_pipe_tcp);
2954 return status;
2957 *cli = conn->lsa_pipe_tcp;
2959 return status;
2962 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2963 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2965 struct winbindd_cm_conn *conn;
2966 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2967 struct netlogon_creds_cli_context *p_creds;
2968 struct cli_credentials *creds = NULL;
2969 bool retry = false; /* allow one retry attempt for expired session */
2971 retry:
2972 result = init_dc_connection_rpc(domain, false);
2973 if (!NT_STATUS_IS_OK(result))
2974 return result;
2976 conn = &domain->conn;
2978 if (rpccli_is_connected(conn->lsa_pipe)) {
2979 goto done;
2982 TALLOC_FREE(conn->lsa_pipe);
2984 if (IS_AD_DC) {
2986 * Make sure we only use schannel as AD DC.
2988 goto schannel;
2991 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2992 if (!NT_STATUS_IS_OK(result)) {
2993 DEBUG(10, ("cm_connect_lsa: No user available for "
2994 "domain %s, trying schannel\n", domain->name));
2995 goto schannel;
2998 if (cli_credentials_is_anonymous(creds)) {
2999 goto anonymous;
3003 * We have an authenticated connection. Use a SPNEGO
3004 * authenticated LSA pipe with sign & seal.
3006 result = cli_rpc_pipe_open_with_creds
3007 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
3008 DCERPC_AUTH_TYPE_SPNEGO,
3009 conn->auth_level,
3010 smbXcli_conn_remote_name(conn->cli->conn),
3011 creds,
3012 &conn->lsa_pipe);
3014 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3015 && !retry) {
3016 invalidate_cm_connection(domain);
3017 retry = true;
3018 goto retry;
3021 if (!NT_STATUS_IS_OK(result)) {
3022 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3023 "domain %s using NTLMSSP authenticated pipe: user "
3024 "%s. Error was %s. Trying schannel.\n",
3025 domain->name,
3026 cli_credentials_get_unparsed_name(creds, talloc_tos()),
3027 nt_errstr(result)));
3028 goto schannel;
3031 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3032 "NTLMSSP authenticated pipe: user %s\n",
3033 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3035 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3036 SEC_FLAG_MAXIMUM_ALLOWED,
3037 &conn->lsa_policy);
3038 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3039 invalidate_cm_connection(domain);
3040 TALLOC_FREE(conn->lsa_pipe);
3041 retry = true;
3042 goto retry;
3045 if (NT_STATUS_IS_OK(result)) {
3046 goto done;
3049 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3050 "schannel\n"));
3052 TALLOC_FREE(conn->lsa_pipe);
3054 schannel:
3056 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3058 result = cm_get_schannel_creds(domain, &p_creds);
3059 if (!NT_STATUS_IS_OK(result)) {
3060 /* If this call fails - conn->cli can now be NULL ! */
3061 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3062 "for domain %s (error %s), trying anon\n",
3063 domain->name,
3064 nt_errstr(result) ));
3065 goto anonymous;
3068 TALLOC_FREE(creds);
3069 result = cli_rpc_pipe_open_schannel_with_creds(
3070 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3071 &conn->lsa_pipe);
3073 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3074 && !retry) {
3075 invalidate_cm_connection(domain);
3076 retry = true;
3077 goto retry;
3080 if (!NT_STATUS_IS_OK(result)) {
3081 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3082 "domain %s using schannel. Error was %s\n",
3083 domain->name, nt_errstr(result) ));
3084 goto anonymous;
3086 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3087 "schannel.\n", domain->name ));
3089 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3090 SEC_FLAG_MAXIMUM_ALLOWED,
3091 &conn->lsa_policy);
3093 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3094 invalidate_cm_connection(domain);
3095 TALLOC_FREE(conn->lsa_pipe);
3096 retry = true;
3097 goto retry;
3100 if (NT_STATUS_IS_OK(result)) {
3101 goto done;
3104 if (IS_AD_DC) {
3106 * Make sure we only use schannel as AD DC.
3108 goto done;
3111 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3112 "anonymous\n"));
3114 TALLOC_FREE(conn->lsa_pipe);
3116 anonymous:
3118 if (IS_AD_DC) {
3120 * Make sure we only use schannel as AD DC.
3122 goto done;
3125 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3126 result = NT_STATUS_DOWNGRADE_DETECTED;
3127 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3128 "without connection level security, "
3129 "must set 'winbind sealed pipes = false' and "
3130 "'require strong key = false' to proceed: %s\n",
3131 domain->name, nt_errstr(result)));
3132 goto done;
3135 result = cli_rpc_pipe_open_noauth(conn->cli,
3136 &ndr_table_lsarpc,
3137 &conn->lsa_pipe);
3139 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3140 && !retry) {
3141 invalidate_cm_connection(domain);
3142 retry = true;
3143 goto retry;
3146 if (!NT_STATUS_IS_OK(result)) {
3147 goto done;
3150 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3151 SEC_FLAG_MAXIMUM_ALLOWED,
3152 &conn->lsa_policy);
3154 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3155 invalidate_cm_connection(domain);
3156 TALLOC_FREE(conn->lsa_pipe);
3157 retry = true;
3158 goto retry;
3161 done:
3162 if (!NT_STATUS_IS_OK(result)) {
3163 invalidate_cm_connection(domain);
3164 return result;
3167 *cli = conn->lsa_pipe;
3168 *lsa_policy = conn->lsa_policy;
3169 return result;
3172 /****************************************************************************
3173 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3174 ****************************************************************************/
3176 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3177 TALLOC_CTX *mem_ctx,
3178 struct rpc_pipe_client **cli,
3179 struct policy_handle *lsa_policy)
3181 NTSTATUS status;
3183 if (domain->can_do_ncacn_ip_tcp) {
3184 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3185 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3186 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3187 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3188 invalidate_cm_connection(domain);
3189 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3191 if (NT_STATUS_IS_OK(status)) {
3192 return status;
3196 * we tried twice to connect via ncan_ip_tcp and schannel and
3197 * failed - maybe it is a trusted domain we can't connect to ?
3198 * do not try tcp next time - gd
3200 * This also prevents NETLOGON over TCP
3202 domain->can_do_ncacn_ip_tcp = false;
3205 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3207 return status;
3210 /****************************************************************************
3211 Open the netlogon pipe to this DC.
3212 ****************************************************************************/
3214 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3215 enum dcerpc_transport_t transport,
3216 struct rpc_pipe_client **cli)
3218 struct messaging_context *msg_ctx = server_messaging_context();
3219 struct winbindd_cm_conn *conn;
3220 NTSTATUS result;
3221 enum netr_SchannelType sec_chan_type;
3222 struct cli_credentials *creds = NULL;
3224 *cli = NULL;
3226 if (IS_AD_DC) {
3227 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3229 * Make sure we don't even try to
3230 * connect to a foreign domain
3231 * without a direct outbound trust.
3233 return NT_STATUS_NO_TRUST_LSA_SECRET;
3237 result = init_dc_connection_rpc(domain, domain->rodc);
3238 if (!NT_STATUS_IS_OK(result)) {
3239 return result;
3242 conn = &domain->conn;
3244 if (rpccli_is_connected(conn->netlogon_pipe)) {
3245 *cli = conn->netlogon_pipe;
3246 return NT_STATUS_OK;
3249 TALLOC_FREE(conn->netlogon_pipe);
3250 TALLOC_FREE(conn->netlogon_creds_ctx);
3252 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3253 if (!NT_STATUS_IS_OK(result)) {
3254 DBG_DEBUG("No user available for domain %s when trying "
3255 "schannel\n", domain->name);
3256 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3259 if (cli_credentials_is_anonymous(creds)) {
3260 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3261 "unable to make get NETLOGON credentials\n",
3262 domain->name);
3263 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3266 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3267 if (sec_chan_type == SEC_CHAN_NULL) {
3268 if (transport == NCACN_IP_TCP) {
3269 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3270 "for %s, deny NCACN_IP_TCP and let the "
3271 "caller fallback to NCACN_NP.\n",
3272 domain->name);
3273 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3276 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3277 "fallback to noauth on NCACN_NP.\n",
3278 domain->name);
3280 result = cli_rpc_pipe_open_noauth_transport(
3281 conn->cli,
3282 transport,
3283 &ndr_table_netlogon,
3284 &conn->netlogon_pipe);
3285 if (!NT_STATUS_IS_OK(result)) {
3286 invalidate_cm_connection(domain);
3287 return result;
3290 *cli = conn->netlogon_pipe;
3291 return NT_STATUS_OK;
3294 result = rpccli_create_netlogon_creds_ctx(creds,
3295 domain->dcname,
3296 msg_ctx,
3297 domain,
3298 &conn->netlogon_creds_ctx);
3299 if (!NT_STATUS_IS_OK(result)) {
3300 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3301 "unable to create NETLOGON credentials: %s\n",
3302 domain->name, nt_errstr(result)));
3303 return result;
3306 result = rpccli_connect_netlogon(
3307 conn->cli, transport,
3308 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3309 &conn->netlogon_pipe);
3310 if (!NT_STATUS_IS_OK(result)) {
3311 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3312 nt_errstr(result));
3313 return result;
3316 *cli = conn->netlogon_pipe;
3317 return NT_STATUS_OK;
3320 /****************************************************************************
3321 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3322 ****************************************************************************/
3324 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3325 struct rpc_pipe_client **cli)
3327 NTSTATUS status;
3329 status = init_dc_connection_rpc(domain, domain->rodc);
3330 if (!NT_STATUS_IS_OK(status)) {
3331 return status;
3334 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3335 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3336 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3337 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3338 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3339 invalidate_cm_connection(domain);
3340 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3342 if (NT_STATUS_IS_OK(status)) {
3343 return status;
3347 * we tried twice to connect via ncan_ip_tcp and schannel and
3348 * failed - maybe it is a trusted domain we can't connect to ?
3349 * do not try tcp next time - gd
3351 * This also prevents LSA over TCP
3353 domain->can_do_ncacn_ip_tcp = false;
3356 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3357 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3359 * SMB2 session expired, needs reauthentication. Drop
3360 * connection and retry.
3362 invalidate_cm_connection(domain);
3363 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3366 return status;
3369 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3370 struct rpc_pipe_client **cli,
3371 struct netlogon_creds_cli_context **ppdc)
3373 NTSTATUS status;
3375 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3376 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3379 status = cm_connect_netlogon(domain, cli);
3380 if (!NT_STATUS_IS_OK(status)) {
3381 return status;
3384 if (domain->conn.netlogon_creds_ctx == NULL) {
3385 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3388 *ppdc = domain->conn.netlogon_creds_ctx;
3389 return NT_STATUS_OK;
3392 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3393 void *private_data,
3394 uint32_t msg_type,
3395 struct server_id server_id,
3396 DATA_BLOB *data)
3398 struct winbindd_domain *domain;
3399 char *freeit = NULL;
3400 char *addr;
3402 if ((data == NULL)
3403 || (data->data == NULL)
3404 || (data->length == 0)
3405 || (data->data[data->length-1] != '\0')) {
3406 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3407 "string\n"));
3408 return;
3411 addr = (char *)data->data;
3412 DEBUG(10, ("IP %s dropped\n", addr));
3414 if (!is_ipaddress(addr)) {
3415 char *slash;
3417 * Some code sends us ip addresses with the /netmask
3418 * suffix
3420 slash = strchr(addr, '/');
3421 if (slash == NULL) {
3422 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3423 addr));
3424 return;
3426 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3427 if (freeit == NULL) {
3428 DEBUG(1, ("talloc failed\n"));
3429 return;
3431 addr = freeit;
3432 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3435 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3436 char sockaddr[INET6_ADDRSTRLEN];
3438 if (!cli_state_is_connected(domain->conn.cli)) {
3439 continue;
3442 print_sockaddr(sockaddr, sizeof(sockaddr),
3443 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3445 if (strequal(sockaddr, addr)) {
3446 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3449 TALLOC_FREE(freeit);