winbind: let cm_connect_netlogon_transport() only work against direct trust as AD DC
[Samba.git] / source3 / winbindd / winbindd_cm.c
bloba88e05cac232d7780c9c2a0fea5899524194e190
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;
202 bool ok;
204 if (domain->dc_probe_pid != (pid_t)-1) {
206 * We might already have a DC probe
207 * child working, check.
209 if (process_exists_by_pid(domain->dc_probe_pid)) {
210 DEBUG(10,("fork_child_dc_connect: pid %u already "
211 "checking for DC's.\n",
212 (unsigned int)domain->dc_probe_pid));
213 return true;
215 domain->dc_probe_pid = (pid_t)-1;
218 domain->dc_probe_pid = fork();
220 if (domain->dc_probe_pid == (pid_t)-1) {
221 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
222 return False;
225 if (domain->dc_probe_pid != (pid_t)0) {
226 /* Parent */
227 messaging_register(server_messaging_context(), NULL,
228 MSG_WINBIND_TRY_TO_GO_ONLINE,
229 msg_try_to_go_online);
230 messaging_register(server_messaging_context(), NULL,
231 MSG_WINBIND_FAILED_TO_GO_ONLINE,
232 msg_failed_to_go_online);
233 return True;
236 /* Child. */
238 /* Leave messages blocked - we will never process one. */
240 if (!override_logfile) {
241 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
242 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
243 _exit(1);
247 status = winbindd_reinit_after_fork(NULL, lfile);
248 if (!NT_STATUS_IS_OK(status)) {
249 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
250 nt_errstr(status)));
251 messaging_send_buf(server_messaging_context(),
252 pid_to_procid(parent_pid),
253 MSG_WINBIND_FAILED_TO_GO_ONLINE,
254 (const uint8_t *)domain->name,
255 strlen(domain->name)+1);
256 _exit(1);
258 SAFE_FREE(lfile);
260 setproctitle("dc-connect child");
262 mem_ctx = talloc_init("fork_child_dc_connect");
263 if (!mem_ctx) {
264 DEBUG(0,("talloc_init failed.\n"));
265 messaging_send_buf(server_messaging_context(),
266 pid_to_procid(parent_pid),
267 MSG_WINBIND_FAILED_TO_GO_ONLINE,
268 (const uint8_t *)domain->name,
269 strlen(domain->name)+1);
270 _exit(1);
273 ok = get_dcs(mem_ctx, domain, &dcs, &num_dcs, 0);
274 TALLOC_FREE(mem_ctx);
275 if (!ok || (num_dcs == 0)) {
276 /* Still offline ? Can't find DC's. */
277 messaging_send_buf(server_messaging_context(),
278 pid_to_procid(parent_pid),
279 MSG_WINBIND_FAILED_TO_GO_ONLINE,
280 (const uint8_t *)domain->name,
281 strlen(domain->name)+1);
282 _exit(0);
285 /* We got a DC. Send a message to our parent to get it to
286 try and do the same. */
288 messaging_send_buf(server_messaging_context(),
289 pid_to_procid(parent_pid),
290 MSG_WINBIND_TRY_TO_GO_ONLINE,
291 (const uint8_t *)domain->name,
292 strlen(domain->name)+1);
293 _exit(0);
296 /****************************************************************
297 Handler triggered if we're offline to try and detect a DC.
298 ****************************************************************/
300 static void check_domain_online_handler(struct tevent_context *ctx,
301 struct tevent_timer *te,
302 struct timeval now,
303 void *private_data)
305 struct winbindd_domain *domain =
306 (struct winbindd_domain *)private_data;
308 DEBUG(10,("check_domain_online_handler: called for domain "
309 "%s (online = %s)\n", domain->name,
310 domain->online ? "True" : "False" ));
312 TALLOC_FREE(domain->check_online_event);
314 /* Are we still in "startup" mode ? */
316 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
317 /* No longer in "startup" mode. */
318 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
319 domain->name ));
320 domain->startup = False;
323 /* We've been told to stay offline, so stay
324 that way. */
326 if (get_global_winbindd_state_offline()) {
327 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
328 domain->name ));
329 return;
332 /* Fork a child to test if it can contact a DC.
333 If it can then send ourselves a message to
334 cause a reconnect. */
336 fork_child_dc_connect(domain);
339 /****************************************************************
340 If we're still offline setup the timeout check.
341 ****************************************************************/
343 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
345 int wbr = lp_winbind_reconnect_delay();
347 if (domain->startup) {
348 domain->check_online_timeout = 10;
349 } else if (domain->check_online_timeout < wbr) {
350 domain->check_online_timeout = wbr;
354 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
355 void *private_data,
356 uint32_t msg_type,
357 struct server_id server_id,
358 DATA_BLOB *data)
360 const char *domain_name = (const char *)data->data;
361 struct winbindd_domain *domain;
363 domain = find_domain_from_name_noinit(domain_name);
364 if (domain == NULL) {
365 return;
368 domain->online = false;
370 DEBUG(10, ("Domain %s is marked as offline now.\n",
371 domain_name));
374 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
375 void *private_data,
376 uint32_t msg_type,
377 struct server_id server_id,
378 DATA_BLOB *data)
380 const char *domain_name = (const char *)data->data;
381 struct winbindd_domain *domain;
383 domain = find_domain_from_name_noinit(domain_name);
384 if (domain == NULL) {
385 return;
388 domain->online = true;
390 DEBUG(10, ("Domain %s is marked as online now.\n",
391 domain_name));
394 /****************************************************************
395 Set domain offline and also add handler to put us back online
396 if we detect a DC.
397 ****************************************************************/
399 void set_domain_offline(struct winbindd_domain *domain)
401 pid_t parent_pid = getppid();
403 DEBUG(10,("set_domain_offline: called for domain %s\n",
404 domain->name ));
406 TALLOC_FREE(domain->check_online_event);
408 if (domain->internal) {
409 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
410 domain->name ));
411 return;
414 domain->online = False;
416 /* Offline domains are always initialized. They're
417 re-initialized when they go back online. */
419 domain->initialized = True;
421 /* We only add the timeout handler that checks and
422 allows us to go back online when we've not
423 been told to remain offline. */
425 if (get_global_winbindd_state_offline()) {
426 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
427 domain->name ));
428 return;
431 /* If we're in startup mode, check again in 10 seconds, not in
432 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
434 calc_new_online_timeout_check(domain);
436 domain->check_online_event = tevent_add_timer(server_event_context(),
437 NULL,
438 timeval_current_ofs(domain->check_online_timeout,0),
439 check_domain_online_handler,
440 domain);
442 /* The above *has* to succeed for winbindd to work. */
443 if (!domain->check_online_event) {
444 smb_panic("set_domain_offline: failed to add online handler");
447 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
448 domain->name ));
450 /* Send a message to the parent that the domain is offline. */
451 if (parent_pid > 1 && !domain->internal) {
452 messaging_send_buf(server_messaging_context(),
453 pid_to_procid(parent_pid),
454 MSG_WINBIND_DOMAIN_OFFLINE,
455 (uint8_t *)domain->name,
456 strlen(domain->name) + 1);
459 /* Send an offline message to the idmap child when our
460 primary domain goes offline */
462 if ( domain->primary ) {
463 struct winbindd_child *idmap = idmap_child();
465 if ( idmap->pid != 0 ) {
466 messaging_send_buf(server_messaging_context(),
467 pid_to_procid(idmap->pid),
468 MSG_WINBIND_OFFLINE,
469 (const uint8_t *)domain->name,
470 strlen(domain->name)+1);
474 return;
477 /****************************************************************
478 Set domain online - if allowed.
479 ****************************************************************/
481 static void set_domain_online(struct winbindd_domain *domain)
483 pid_t parent_pid = getppid();
485 DEBUG(10,("set_domain_online: called for domain %s\n",
486 domain->name ));
488 if (domain->internal) {
489 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
490 domain->name ));
491 return;
494 if (get_global_winbindd_state_offline()) {
495 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
496 domain->name ));
497 return;
500 winbindd_set_locator_kdc_envs(domain);
502 /* If we are waiting to get a krb5 ticket, trigger immediately. */
503 ccache_regain_all_now();
505 /* Ok, we're out of any startup mode now... */
506 domain->startup = False;
508 if (domain->online == False) {
509 /* We were offline - now we're online. We default to
510 using the MS-RPC backend if we started offline,
511 and if we're going online for the first time we
512 should really re-initialize the backends and the
513 checks to see if we're talking to an AD or NT domain.
516 domain->initialized = False;
518 /* 'reconnect_methods' is the MS-RPC backend. */
519 if (domain->backend == &reconnect_methods) {
520 domain->backend = NULL;
524 /* Ensure we have no online timeout checks. */
525 domain->check_online_timeout = 0;
526 TALLOC_FREE(domain->check_online_event);
528 /* Ensure we ignore any pending child messages. */
529 messaging_deregister(server_messaging_context(),
530 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
531 messaging_deregister(server_messaging_context(),
532 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
534 domain->online = True;
536 /* Send a message to the parent that the domain is online. */
537 if (parent_pid > 1 && !domain->internal) {
538 messaging_send_buf(server_messaging_context(),
539 pid_to_procid(parent_pid),
540 MSG_WINBIND_DOMAIN_ONLINE,
541 (uint8_t *)domain->name,
542 strlen(domain->name) + 1);
545 /* Send an online message to the idmap child when our
546 primary domain comes online */
548 if ( domain->primary ) {
549 struct winbindd_child *idmap = idmap_child();
551 if ( idmap->pid != 0 ) {
552 messaging_send_buf(server_messaging_context(),
553 pid_to_procid(idmap->pid),
554 MSG_WINBIND_ONLINE,
555 (const uint8_t *)domain->name,
556 strlen(domain->name)+1);
560 return;
563 /****************************************************************
564 Requested to set a domain online.
565 ****************************************************************/
567 void set_domain_online_request(struct winbindd_domain *domain)
569 struct timeval tev;
571 DEBUG(10,("set_domain_online_request: called for domain %s\n",
572 domain->name ));
574 if (get_global_winbindd_state_offline()) {
575 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
576 domain->name ));
577 return;
580 if (domain->internal) {
581 DEBUG(10, ("set_domain_online_request: Internal domains are "
582 "always online\n"));
583 return;
586 /* We've been told it's safe to go online and
587 try and connect to a DC. But I don't believe it
588 because network manager seems to lie.
589 Wait at least 5 seconds. Heuristics suck... */
592 GetTimeOfDay(&tev);
594 /* Go into "startup" mode again. */
595 domain->startup_time = time_mono(NULL);
596 domain->startup = True;
598 tev.tv_sec += 5;
600 if (!domain->check_online_event) {
601 /* If we've come from being globally offline we
602 don't have a check online event handler set.
603 We need to add one now we're trying to go
604 back online. */
606 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
607 domain->name ));
610 TALLOC_FREE(domain->check_online_event);
612 domain->check_online_event = tevent_add_timer(server_event_context(),
613 NULL,
614 tev,
615 check_domain_online_handler,
616 domain);
618 /* The above *has* to succeed for winbindd to work. */
619 if (!domain->check_online_event) {
620 smb_panic("set_domain_online_request: failed to add online handler");
624 /****************************************************************
625 Add -ve connection cache entries for domain and realm.
626 ****************************************************************/
628 static void winbind_add_failed_connection_entry(
629 const struct winbindd_domain *domain,
630 const char *server,
631 NTSTATUS result)
633 add_failed_connection_entry(domain->name, server, result);
634 /* If this was the saf name for the last thing we talked to,
635 remove it. */
636 saf_delete(domain->name);
637 if (domain->alt_name != NULL) {
638 add_failed_connection_entry(domain->alt_name, server, result);
639 saf_delete(domain->alt_name);
641 winbindd_unset_locator_kdc_env(domain);
644 /* Choose between anonymous or authenticated connections. We need to use
645 an authenticated connection if DCs have the RestrictAnonymous registry
646 entry set > 0, or the "Additional restrictions for anonymous
647 connections" set in the win2k Local Security Policy.
649 Caller to free() result in domain, username, password
652 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
654 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
655 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
656 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
658 if (*username && **username) {
660 if (!*domain || !**domain)
661 *domain = smb_xstrdup(lp_workgroup());
663 if (!*password || !**password)
664 *password = smb_xstrdup("");
666 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
667 *domain, *username));
669 } else {
670 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
671 *username = smb_xstrdup("");
672 *domain = smb_xstrdup("");
673 *password = smb_xstrdup("");
677 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
678 struct cli_credentials **_creds)
681 TALLOC_CTX *frame = talloc_stackframe();
682 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
683 struct loadparm_context *lp_ctx;
684 char *username = NULL;
685 char *netbios_domain = NULL;
686 char *password = NULL;
687 struct cli_credentials *creds = NULL;
688 bool ok;
690 cm_get_ipc_userpass(&username, &netbios_domain, &password);
692 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
693 if (lp_ctx == NULL) {
694 DEBUG(1, ("loadparm_init_s3 failed\n"));
695 status = NT_STATUS_INTERNAL_ERROR;
696 goto fail;
699 creds = cli_credentials_init(mem_ctx);
700 if (creds == NULL) {
701 status = NT_STATUS_NO_MEMORY;
702 goto fail;
705 cli_credentials_set_conf(creds, lp_ctx);
706 cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
708 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
709 if (!ok) {
710 status = NT_STATUS_NO_MEMORY;
711 goto fail;
714 ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
715 if (!ok) {
716 status = NT_STATUS_NO_MEMORY;
717 goto fail;
720 ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
721 if (!ok) {
722 status = NT_STATUS_NO_MEMORY;
723 goto fail;
726 *_creds = creds;
727 creds = NULL;
728 status = NT_STATUS_OK;
729 fail:
730 TALLOC_FREE(creds);
731 SAFE_FREE(username);
732 SAFE_FREE(netbios_domain);
733 SAFE_FREE(password);
734 TALLOC_FREE(frame);
735 return status;
738 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
740 TALLOC_CTX *frame = talloc_stackframe();
741 char *ipc_account = NULL;
742 char *ipc_domain = NULL;
743 char *ipc_password = NULL;
744 const char *creds_account = NULL;
745 const char *creds_domain = NULL;
746 const char *creds_password = NULL;
747 bool ret = false;
749 cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
751 creds_account = cli_credentials_get_username(creds);
752 creds_domain = cli_credentials_get_domain(creds);
753 creds_password = cli_credentials_get_password(creds);
755 if (!strequal(ipc_domain, creds_domain)) {
756 goto done;
759 if (!strequal(ipc_account, creds_account)) {
760 goto done;
763 if (!strcsequal(ipc_password, creds_password)) {
764 goto done;
767 ret = true;
768 done:
769 SAFE_FREE(ipc_account);
770 SAFE_FREE(ipc_domain);
771 SAFE_FREE(ipc_password);
772 TALLOC_FREE(frame);
773 return ret;
776 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
777 fstring dcname,
778 struct sockaddr_storage *dc_ss,
779 uint32_t request_flags)
781 struct winbindd_domain *our_domain = NULL;
782 struct rpc_pipe_client *netlogon_pipe = NULL;
783 NTSTATUS result;
784 WERROR werr;
785 TALLOC_CTX *mem_ctx;
786 unsigned int orig_timeout;
787 const char *tmp = NULL;
788 const char *p;
789 struct dcerpc_binding_handle *b;
791 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
792 * moment.... */
794 if (IS_DC) {
795 return False;
798 if (domain->primary) {
799 return False;
802 our_domain = find_our_domain();
804 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
805 return False;
808 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
809 if (!NT_STATUS_IS_OK(result)) {
810 talloc_destroy(mem_ctx);
811 return False;
814 b = netlogon_pipe->binding_handle;
816 /* This call can take a long time - allow the server to time out.
817 35 seconds should do it. */
819 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
821 if (our_domain->active_directory) {
822 struct netr_DsRGetDCNameInfo *domain_info = NULL;
825 * TODO request flags are not respected in the server
826 * (and in some cases, like REQUIRE_PDC, causes an error)
828 result = dcerpc_netr_DsRGetDCName(b,
829 mem_ctx,
830 our_domain->dcname,
831 domain->name,
832 NULL,
833 NULL,
834 request_flags|DS_RETURN_DNS_NAME,
835 &domain_info,
836 &werr);
837 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
838 tmp = talloc_strdup(
839 mem_ctx, domain_info->dc_unc);
840 if (tmp == NULL) {
841 DEBUG(0, ("talloc_strdup failed\n"));
842 talloc_destroy(mem_ctx);
843 return false;
845 if (domain->alt_name == NULL) {
846 domain->alt_name = talloc_strdup(domain,
847 domain_info->domain_name);
848 if (domain->alt_name == NULL) {
849 DEBUG(0, ("talloc_strdup failed\n"));
850 talloc_destroy(mem_ctx);
851 return false;
854 if (domain->forest_name == NULL) {
855 domain->forest_name = talloc_strdup(domain,
856 domain_info->forest_name);
857 if (domain->forest_name == NULL) {
858 DEBUG(0, ("talloc_strdup failed\n"));
859 talloc_destroy(mem_ctx);
860 return false;
864 } else {
865 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
866 our_domain->dcname,
867 domain->name,
868 &tmp,
869 &werr);
872 /* And restore our original timeout. */
873 rpccli_set_timeout(netlogon_pipe, orig_timeout);
875 if (!NT_STATUS_IS_OK(result)) {
876 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
877 nt_errstr(result)));
878 talloc_destroy(mem_ctx);
879 return false;
882 if (!W_ERROR_IS_OK(werr)) {
883 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
884 win_errstr(werr)));
885 talloc_destroy(mem_ctx);
886 return false;
889 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
890 p = strip_hostname(tmp);
892 fstrcpy(dcname, p);
894 talloc_destroy(mem_ctx);
896 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
898 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
899 return False;
902 return True;
906 * Helper function to assemble trust password and account name
908 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
909 TALLOC_CTX *mem_ctx,
910 bool netlogon,
911 struct cli_credentials **_creds)
913 const struct winbindd_domain *creds_domain = NULL;
914 struct cli_credentials *creds;
915 NTSTATUS status;
916 bool force_machine_account = false;
918 /* If we are a DC and this is not our own domain */
920 if (!domain->active_directory) {
921 if (!netlogon) {
923 * For non active directory domains
924 * we can only use NTLMSSP for SMB.
926 * But the trust account is not allowed
927 * to use SMB with NTLMSSP.
929 force_machine_account = true;
933 if (IS_DC && !force_machine_account) {
934 creds_domain = domain;
935 } else {
936 creds_domain = find_our_domain();
937 if (creds_domain == NULL) {
938 return NT_STATUS_INVALID_SERVER_STATE;
942 status = pdb_get_trust_credentials(creds_domain->name,
943 creds_domain->alt_name,
944 mem_ctx,
945 &creds);
946 if (!NT_STATUS_IS_OK(status)) {
947 goto ipc_fallback;
950 if (creds_domain != domain) {
952 * We can only use schannel against a direct trust
954 cli_credentials_set_secure_channel_type(creds,
955 SEC_CHAN_NULL);
958 *_creds = creds;
959 return NT_STATUS_OK;
961 ipc_fallback:
962 if (netlogon) {
963 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
966 status = cm_get_ipc_credentials(mem_ctx, &creds);
967 if (!NT_STATUS_IS_OK(status)) {
968 return status;
971 *_creds = creds;
972 return NT_STATUS_OK;
975 /************************************************************************
976 Given a fd with a just-connected TCP connection to a DC, open a connection
977 to the pipe.
978 ************************************************************************/
980 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
981 const int sockfd,
982 const char *controller,
983 struct cli_state **cli,
984 bool *retry)
986 bool try_ipc_auth = false;
987 const char *machine_principal = NULL;
988 const char *machine_realm = NULL;
989 const char *machine_account = NULL;
990 const char *machine_domain = NULL;
991 int flags = 0;
992 struct cli_credentials *creds = NULL;
994 struct named_mutex *mutex;
996 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
997 NTSTATUS tmp_status;
998 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
1000 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
1002 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
1004 * If we are connecting to our own AD domain, require
1005 * smb signing to disrupt MITM attacks
1007 if (domain->primary && lp_security() == SEC_ADS) {
1008 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1010 * If we are in or are an AD domain and connecting to another
1011 * AD domain in our forest
1012 * then require smb signing to disrupt MITM attacks
1014 } else if ((lp_security() == SEC_ADS ||
1015 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)
1016 && domain->active_directory
1017 && (domain->domain_trust_attribs
1018 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
1019 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1023 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1024 controller, domain->name ));
1026 *retry = True;
1028 mutex = grab_named_mutex(talloc_tos(), controller,
1029 WINBIND_SERVER_MUTEX_WAIT_TIME);
1030 if (mutex == NULL) {
1031 close(sockfd);
1032 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1033 controller));
1034 result = NT_STATUS_POSSIBLE_DEADLOCK;
1035 goto done;
1038 *cli = cli_state_create(NULL, sockfd, controller,
1039 smb_sign_client_connections, flags);
1040 if (*cli == NULL) {
1041 close(sockfd);
1042 DEBUG(1, ("Could not cli_initialize\n"));
1043 result = NT_STATUS_NO_MEMORY;
1044 goto done;
1047 cli_set_timeout(*cli, 10000); /* 10 seconds */
1049 set_socket_options(sockfd, lp_socket_options());
1051 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
1052 lp_client_ipc_min_protocol(),
1053 lp_client_ipc_max_protocol());
1055 if (!NT_STATUS_IS_OK(result)) {
1056 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
1057 goto done;
1060 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
1061 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
1062 try_ipc_auth = true;
1063 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1064 try_ipc_auth = true;
1065 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1067 * If we are forcing on SMB signing, then we must
1068 * require authentication unless this is a one-way
1069 * trust, and we have no stored user/password
1071 try_ipc_auth = true;
1074 if (try_ipc_auth) {
1075 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
1076 if (!NT_STATUS_IS_OK(result)) {
1077 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1078 domain->name, nt_errstr(result)));
1079 goto done;
1081 } else {
1083 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1084 * would try and authentication with our machine
1085 * account password and fail. This is very rare in
1086 * the modern world however
1088 creds = cli_credentials_init_anon(talloc_tos());
1089 if (creds == NULL) {
1090 result = NT_STATUS_NO_MEMORY;
1091 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1092 domain->name, nt_errstr(result)));
1093 goto done;
1097 machine_principal = cli_credentials_get_principal(creds,
1098 talloc_tos());
1099 machine_realm = cli_credentials_get_realm(creds);
1100 machine_account = cli_credentials_get_username(creds);
1101 machine_domain = cli_credentials_get_domain(creds);
1103 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1104 "[%s] and realm [%s]\n",
1105 controller, domain->name, domain->alt_name,
1106 machine_domain, machine_account,
1107 machine_principal, machine_realm));
1109 if (cli_credentials_is_anonymous(creds)) {
1110 goto anon_fallback;
1113 winbindd_set_locator_kdc_envs(domain);
1115 result = cli_session_setup_creds(*cli, creds);
1116 if (NT_STATUS_IS_OK(result)) {
1117 goto session_setup_done;
1120 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1121 controller,
1122 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1123 nt_errstr(result)));
1126 * If we are not going to validiate the conneciton
1127 * with SMB signing, then allow us to fall back to
1128 * anonymous
1130 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1131 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1132 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1133 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1134 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1136 if (!cm_is_ipc_credentials(creds)) {
1137 goto ipc_fallback;
1140 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1141 goto done;
1144 goto anon_fallback;
1147 goto done;
1149 ipc_fallback:
1150 TALLOC_FREE(creds);
1151 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1152 if (!NT_STATUS_IS_OK(tmp_status)) {
1153 result = tmp_status;
1154 goto done;
1157 if (cli_credentials_is_anonymous(creds)) {
1158 goto anon_fallback;
1161 machine_account = cli_credentials_get_username(creds);
1162 machine_domain = cli_credentials_get_domain(creds);
1164 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1165 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1166 machine_domain, machine_account));
1168 result = cli_session_setup_creds(*cli, creds);
1169 if (NT_STATUS_IS_OK(result)) {
1170 goto session_setup_done;
1173 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1174 controller,
1175 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1176 nt_errstr(result)));
1179 * If we are not going to validiate the conneciton
1180 * with SMB signing, then allow us to fall back to
1181 * anonymous
1183 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1184 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1185 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1186 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1187 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1189 goto anon_fallback;
1192 goto done;
1194 anon_fallback:
1195 TALLOC_FREE(creds);
1197 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1198 goto done;
1201 /* Fall back to anonymous connection, this might fail later */
1202 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1203 "connection for DC %s\n",
1204 controller ));
1206 result = cli_session_setup_anon(*cli);
1207 if (NT_STATUS_IS_OK(result)) {
1208 DEBUG(5, ("Connected anonymously\n"));
1209 goto session_setup_done;
1212 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1213 controller, nt_errstr(result)));
1215 /* We can't session setup */
1216 goto done;
1218 session_setup_done:
1219 TALLOC_FREE(creds);
1222 * This should be a short term hack until
1223 * dynamic re-authentication is implemented.
1225 * See Bug 9175 - winbindd doesn't recover from
1226 * NT_STATUS_NETWORK_SESSION_EXPIRED
1228 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1229 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1232 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1233 if (!NT_STATUS_IS_OK(result)) {
1234 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1235 goto done;
1237 tcon_status = result;
1239 /* cache the server name for later connections */
1241 saf_store(domain->name, controller);
1242 if (domain->alt_name) {
1243 saf_store(domain->alt_name, controller);
1246 winbindd_set_locator_kdc_envs(domain);
1248 TALLOC_FREE(mutex);
1249 *retry = False;
1251 result = NT_STATUS_OK;
1253 done:
1254 TALLOC_FREE(mutex);
1255 TALLOC_FREE(creds);
1257 if (NT_STATUS_IS_OK(result)) {
1258 result = tcon_status;
1261 if (!NT_STATUS_IS_OK(result)) {
1262 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1263 controller, nt_errstr(result)));
1264 winbind_add_failed_connection_entry(domain, controller, result);
1265 if ((*cli) != NULL) {
1266 cli_shutdown(*cli);
1267 *cli = NULL;
1271 return result;
1274 /*******************************************************************
1275 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1276 array.
1278 Keeps the list unique by not adding duplicate entries.
1280 @param[in] mem_ctx talloc memory context to allocate from
1281 @param[in] domain_name domain of the DC
1282 @param[in] dcname name of the DC to add to the list
1283 @param[in] pss Internet address and port pair to add to the list
1284 @param[in,out] dcs array of dc_name_ip structures to add to
1285 @param[in,out] num_dcs number of dcs returned in the dcs array
1286 @return true if the list was added to, false otherwise
1287 *******************************************************************/
1289 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1290 const char *dcname, struct sockaddr_storage *pss,
1291 struct dc_name_ip **dcs, int *num)
1293 int i = 0;
1295 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1296 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1297 return False;
1300 /* Make sure there's no duplicates in the list */
1301 for (i=0; i<*num; i++)
1302 if (sockaddr_equal(
1303 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1304 (struct sockaddr *)(void *)pss))
1305 return False;
1307 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1309 if (*dcs == NULL)
1310 return False;
1312 fstrcpy((*dcs)[*num].name, dcname);
1313 (*dcs)[*num].ss = *pss;
1314 *num += 1;
1315 return True;
1318 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1319 struct sockaddr_storage *pss, uint16_t port,
1320 struct sockaddr_storage **addrs, int *num)
1322 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1324 if (*addrs == NULL) {
1325 *num = 0;
1326 return False;
1329 (*addrs)[*num] = *pss;
1330 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1332 *num += 1;
1333 return True;
1336 /*******************************************************************
1337 convert an ip to a name
1338 For an AD Domain, it checks the requirements of the request flags.
1339 *******************************************************************/
1341 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1342 const struct winbindd_domain *domain,
1343 struct sockaddr_storage *pss,
1344 char **name, uint32_t request_flags)
1346 struct ip_service ip_list;
1347 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1348 NTSTATUS status;
1349 const char *dc_name;
1350 fstring nbtname;
1351 #ifdef HAVE_ADS
1352 bool is_ad_domain = false;
1353 #endif
1354 ip_list.ss = *pss;
1355 ip_list.port = 0;
1357 #ifdef HAVE_ADS
1358 /* For active directory servers, try to get the ldap server name.
1359 None of these failures should be considered critical for now */
1361 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1362 is_ad_domain = true;
1363 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1364 is_ad_domain = domain->active_directory;
1367 if (is_ad_domain) {
1368 ADS_STRUCT *ads;
1369 ADS_STATUS ads_status;
1370 char addr[INET6_ADDRSTRLEN];
1372 print_sockaddr(addr, sizeof(addr), pss);
1374 ads = ads_init(domain->alt_name, domain->name, addr);
1375 ads->auth.flags |= ADS_AUTH_NO_BIND;
1376 ads->config.flags |= request_flags;
1377 ads->server.no_fallback = true;
1379 ads_status = ads_connect(ads);
1380 if (ADS_ERR_OK(ads_status)) {
1381 /* We got a cldap packet. */
1382 *name = talloc_strdup(mem_ctx,
1383 ads->config.ldap_server_name);
1384 if (*name == NULL) {
1385 return false;
1387 namecache_store(*name, 0x20, 1, &ip_list);
1389 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1391 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1392 if (ads_closest_dc(ads)) {
1393 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1395 /* We're going to use this KDC for this realm/domain.
1396 If we are using sites, then force the krb5 libs
1397 to use this KDC. */
1399 create_local_private_krb5_conf_for_domain(domain->alt_name,
1400 domain->name,
1401 sitename,
1402 pss);
1404 TALLOC_FREE(sitename);
1405 } else {
1406 /* use an off site KDC */
1407 create_local_private_krb5_conf_for_domain(domain->alt_name,
1408 domain->name,
1409 NULL,
1410 pss);
1412 winbindd_set_locator_kdc_envs(domain);
1414 /* Ensure we contact this DC also. */
1415 saf_store(domain->name, *name);
1416 saf_store(domain->alt_name, *name);
1419 ads_destroy( &ads );
1420 return True;
1423 ads_destroy( &ads );
1424 return false;
1426 #endif
1428 status = nbt_getdc(server_messaging_context(), 10, pss, domain->name,
1429 &domain->sid, nt_version, mem_ctx, &nt_version,
1430 &dc_name, NULL);
1431 if (NT_STATUS_IS_OK(status)) {
1432 *name = talloc_strdup(mem_ctx, dc_name);
1433 if (*name == NULL) {
1434 return false;
1436 namecache_store(*name, 0x20, 1, &ip_list);
1437 return True;
1440 /* try node status request */
1442 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1443 namecache_store(nbtname, 0x20, 1, &ip_list);
1445 if (name != NULL) {
1446 *name = talloc_strdup(mem_ctx, nbtname);
1447 if (*name == NULL) {
1448 return false;
1452 return true;
1454 return False;
1457 /*******************************************************************
1458 Retrieve a list of IP addresses for domain controllers.
1460 The array is sorted in the preferred connection order.
1462 @param[in] mem_ctx talloc memory context to allocate from
1463 @param[in] domain domain to retrieve DCs for
1464 @param[out] dcs array of dcs that will be returned
1465 @param[out] num_dcs number of dcs returned in the dcs array
1466 @return always true
1467 *******************************************************************/
1469 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1470 struct dc_name_ip **dcs, int *num_dcs,
1471 uint32_t request_flags)
1473 fstring dcname;
1474 struct sockaddr_storage ss;
1475 struct ip_service *ip_list = NULL;
1476 int iplist_size = 0;
1477 int i;
1478 bool is_our_domain;
1479 enum security_types sec = (enum security_types)lp_security();
1481 is_our_domain = strequal(domain->name, lp_workgroup());
1483 /* If not our domain, get the preferred DC, by asking our primary DC */
1484 if ( !is_our_domain
1485 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1486 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1487 num_dcs) )
1489 char addr[INET6_ADDRSTRLEN];
1490 print_sockaddr(addr, sizeof(addr), &ss);
1491 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1492 dcname, addr));
1493 return True;
1496 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1497 char *sitename = NULL;
1499 /* We need to make sure we know the local site before
1500 doing any DNS queries, as this will restrict the
1501 get_sorted_dc_list() call below to only fetching
1502 DNS records for the correct site. */
1504 /* Find any DC to get the site record.
1505 We deliberately don't care about the
1506 return here. */
1508 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1510 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1511 if (sitename) {
1513 /* Do the site-specific AD dns lookup first. */
1514 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1515 &iplist_size, True);
1517 /* Add ips to the DC array. We don't look up the name
1518 of the DC in this function, but we fill in the char*
1519 of the ip now to make the failed connection cache
1520 work */
1521 for ( i=0; i<iplist_size; i++ ) {
1522 char addr[INET6_ADDRSTRLEN];
1523 print_sockaddr(addr, sizeof(addr),
1524 &ip_list[i].ss);
1525 add_one_dc_unique(mem_ctx,
1526 domain->name,
1527 addr,
1528 &ip_list[i].ss,
1529 dcs,
1530 num_dcs);
1533 SAFE_FREE(ip_list);
1534 TALLOC_FREE(sitename);
1535 iplist_size = 0;
1538 /* Now we add DCs from the main AD DNS lookup. */
1539 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1540 &iplist_size, True);
1542 for ( i=0; i<iplist_size; i++ ) {
1543 char addr[INET6_ADDRSTRLEN];
1544 print_sockaddr(addr, sizeof(addr),
1545 &ip_list[i].ss);
1546 add_one_dc_unique(mem_ctx,
1547 domain->name,
1548 addr,
1549 &ip_list[i].ss,
1550 dcs,
1551 num_dcs);
1554 SAFE_FREE(ip_list);
1555 iplist_size = 0;
1558 /* Try standard netbios queries if no ADS and fall back to DNS queries
1559 * if alt_name is available */
1560 if (*num_dcs == 0) {
1561 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1562 false);
1563 if (iplist_size == 0) {
1564 if (domain->alt_name != NULL) {
1565 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1566 &iplist_size, true);
1570 for ( i=0; i<iplist_size; i++ ) {
1571 char addr[INET6_ADDRSTRLEN];
1572 print_sockaddr(addr, sizeof(addr),
1573 &ip_list[i].ss);
1574 add_one_dc_unique(mem_ctx,
1575 domain->name,
1576 addr,
1577 &ip_list[i].ss,
1578 dcs,
1579 num_dcs);
1582 SAFE_FREE(ip_list);
1583 iplist_size = 0;
1586 return True;
1589 /*******************************************************************
1590 Find and make a connection to a DC in the given domain.
1592 @param[in] mem_ctx talloc memory context to allocate from
1593 @param[in] domain domain to find a dc in
1594 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1595 @param[out] pss DC Internet address and port
1596 @param[out] fd fd of the open socket connected to the newly found dc
1597 @return true when a DC connection is made, false otherwise
1598 *******************************************************************/
1600 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1601 struct winbindd_domain *domain,
1602 char **dcname, struct sockaddr_storage *pss, int *fd,
1603 uint32_t request_flags)
1605 struct dc_name_ip *dcs = NULL;
1606 int num_dcs = 0;
1608 const char **dcnames = NULL;
1609 size_t num_dcnames = 0;
1611 struct sockaddr_storage *addrs = NULL;
1612 int num_addrs = 0;
1614 int i;
1615 size_t fd_index;
1617 NTSTATUS status;
1619 *fd = -1;
1621 again:
1622 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1623 return False;
1625 for (i=0; i<num_dcs; i++) {
1627 if (!add_string_to_array(mem_ctx, dcs[i].name,
1628 &dcnames, &num_dcnames)) {
1629 return False;
1631 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1632 &addrs, &num_addrs)) {
1633 return False;
1637 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1638 return False;
1640 if ((addrs == NULL) || (dcnames == NULL))
1641 return False;
1643 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1644 num_addrs, 0, 10, fd, &fd_index, NULL);
1645 if (!NT_STATUS_IS_OK(status)) {
1646 for (i=0; i<num_dcs; i++) {
1647 char ab[INET6_ADDRSTRLEN];
1648 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1649 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1650 "domain %s address %s. Error was %s\n",
1651 domain->name, ab, nt_errstr(status) ));
1652 winbind_add_failed_connection_entry(domain,
1653 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1655 return False;
1658 *pss = addrs[fd_index];
1660 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1661 /* Ok, we've got a name for the DC */
1662 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1663 if (*dcname == NULL) {
1664 return false;
1666 return true;
1669 /* Try to figure out the name */
1670 if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1671 return True;
1674 /* We can not continue without the DC's name */
1675 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1676 NT_STATUS_UNSUCCESSFUL);
1678 /* Throw away all arrays as we're doing this again. */
1679 TALLOC_FREE(dcs);
1680 num_dcs = 0;
1682 TALLOC_FREE(dcnames);
1683 num_dcnames = 0;
1685 TALLOC_FREE(addrs);
1686 num_addrs = 0;
1688 close(*fd);
1689 *fd = -1;
1691 goto again;
1694 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1696 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1697 domain_name);
1700 static void store_current_dc_in_gencache(const char *domain_name,
1701 const char *dc_name,
1702 struct cli_state *cli)
1704 char addr[INET6_ADDRSTRLEN];
1705 char *key = NULL;
1706 char *value = NULL;
1708 if (!cli_state_is_connected(cli)) {
1709 return;
1712 print_sockaddr(addr, sizeof(addr),
1713 smbXcli_conn_remote_sockaddr(cli->conn));
1715 key = current_dc_key(talloc_tos(), domain_name);
1716 if (key == NULL) {
1717 goto done;
1720 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1721 if (value == NULL) {
1722 goto done;
1725 gencache_set(key, value, 0x7fffffff);
1726 done:
1727 TALLOC_FREE(value);
1728 TALLOC_FREE(key);
1731 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1732 const char *domain_name,
1733 char **p_dc_name, char **p_dc_ip)
1735 char *key, *p;
1736 char *value = NULL;
1737 bool ret = false;
1738 char *dc_name = NULL;
1739 char *dc_ip = NULL;
1741 key = current_dc_key(talloc_tos(), domain_name);
1742 if (key == NULL) {
1743 goto done;
1745 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1746 goto done;
1748 p = strchr(value, ' ');
1749 if (p == NULL) {
1750 goto done;
1752 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1753 if (dc_ip == NULL) {
1754 goto done;
1756 dc_name = talloc_strdup(mem_ctx, p+1);
1757 if (dc_name == NULL) {
1758 goto done;
1761 if (p_dc_ip != NULL) {
1762 *p_dc_ip = dc_ip;
1763 dc_ip = NULL;
1765 if (p_dc_name != NULL) {
1766 *p_dc_name = dc_name;
1767 dc_name = NULL;
1769 ret = true;
1770 done:
1771 TALLOC_FREE(dc_name);
1772 TALLOC_FREE(dc_ip);
1773 TALLOC_FREE(key);
1774 TALLOC_FREE(value);
1775 return ret;
1778 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1779 const struct ndr_interface_table *table,
1780 struct rpc_pipe_client **ret_pipe)
1782 struct rpc_pipe_client *cli = NULL;
1783 const struct auth_session_info *session_info;
1784 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1787 session_info = get_session_info_system();
1788 SMB_ASSERT(session_info != NULL);
1790 /* create a connection to the specified pipe */
1791 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1792 status = rpc_pipe_open_interface(mem_ctx,
1793 table,
1794 session_info,
1795 NULL,
1796 NULL,
1797 server_messaging_context(),
1798 &cli);
1799 } else {
1800 status = rpc_pipe_open_internal(mem_ctx,
1801 table,
1802 session_info,
1803 NULL,
1804 NULL,
1805 server_messaging_context(),
1806 &cli);
1808 if (!NT_STATUS_IS_OK(status)) {
1809 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1810 table->name, nt_errstr(status)));
1811 return status;
1814 if (ret_pipe) {
1815 *ret_pipe = cli;
1818 return NT_STATUS_OK;
1821 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1822 struct winbindd_cm_conn *new_conn,
1823 bool need_rw_dc)
1825 TALLOC_CTX *mem_ctx;
1826 NTSTATUS result;
1827 char *saf_servername;
1828 int retries;
1829 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1831 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1832 set_domain_offline(domain);
1833 return NT_STATUS_NO_MEMORY;
1836 saf_servername = saf_fetch(mem_ctx, domain->name );
1838 /* we have to check the server affinity cache here since
1839 later we select a DC based on response time and not preference */
1841 /* Check the negative connection cache
1842 before talking to it. It going down may have
1843 triggered the reconnection. */
1845 if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1846 struct sockaddr_storage ss;
1847 char *dcname = NULL;
1848 bool resolved = true;
1850 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1851 saf_servername, domain->name));
1853 /* convert an ip address to a name */
1854 if (is_ipaddress(saf_servername)) {
1855 if (!interpret_string_addr(&ss, saf_servername,
1856 AI_NUMERICHOST)) {
1857 TALLOC_FREE(mem_ctx);
1858 return NT_STATUS_UNSUCCESSFUL;
1860 } else {
1861 if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1862 resolved = false;
1866 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1867 domain->dcname = talloc_strdup(domain,
1868 dcname);
1869 if (domain->dcname == NULL) {
1870 TALLOC_FREE(mem_ctx);
1871 return NT_STATUS_NO_MEMORY;
1874 domain->dcaddr = ss;
1875 } else {
1876 winbind_add_failed_connection_entry(domain, saf_servername,
1877 NT_STATUS_UNSUCCESSFUL);
1881 for (retries = 0; retries < 3; retries++) {
1882 int fd = -1;
1883 bool retry = False;
1884 char *dcname = NULL;
1886 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1888 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1889 domain->dcname ? domain->dcname : "", domain->name));
1891 if (domain->dcname != NULL &&
1892 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1893 domain->dcname)))
1895 NTSTATUS status;
1897 status = smbsock_connect(&domain->dcaddr, 0,
1898 NULL, -1, NULL, -1,
1899 &fd, NULL, 10);
1900 if (!NT_STATUS_IS_OK(status)) {
1901 fd = -1;
1905 if ((fd == -1) &&
1906 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1908 /* This is the one place where we will
1909 set the global winbindd offline state
1910 to true, if a "WINBINDD_OFFLINE" entry
1911 is found in the winbindd cache. */
1912 set_global_winbindd_state_offline();
1913 break;
1915 if (dcname != NULL) {
1916 talloc_free(domain->dcname);
1918 domain->dcname = talloc_move(domain, &dcname);
1919 if (domain->dcname == NULL) {
1920 result = NT_STATUS_NO_MEMORY;
1921 break;
1925 new_conn->cli = NULL;
1927 result = cm_prepare_connection(domain, fd, domain->dcname,
1928 &new_conn->cli, &retry);
1929 if (!NT_STATUS_IS_OK(result)) {
1930 /* Don't leak the smb connection socket */
1931 close(fd);
1934 if (!retry)
1935 break;
1938 if (NT_STATUS_IS_OK(result)) {
1939 bool seal_pipes = true;
1941 winbindd_set_locator_kdc_envs(domain);
1943 if (domain->online == False) {
1944 /* We're changing state from offline to online. */
1945 set_global_winbindd_state_online();
1947 set_domain_online(domain);
1950 * Much as I hate global state, this seems to be the point
1951 * where we can be certain that we have a proper connection to
1952 * a DC. wbinfo --dc-info needs that information, store it in
1953 * gencache with a looong timeout. This will need revisiting
1954 * once we start to connect to multiple DCs, wbcDcInfo is
1955 * already prepared for that.
1957 store_current_dc_in_gencache(domain->name, domain->dcname,
1958 new_conn->cli);
1960 seal_pipes = lp_winbind_sealed_pipes();
1961 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1962 domain->name,
1963 seal_pipes);
1965 if (seal_pipes) {
1966 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1967 } else {
1968 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1970 } else {
1971 /* Ensure we setup the retry handler. */
1972 set_domain_offline(domain);
1975 talloc_destroy(mem_ctx);
1976 return result;
1979 /* Close down all open pipes on a connection. */
1981 void invalidate_cm_connection(struct winbindd_domain *domain)
1983 NTSTATUS result;
1984 struct winbindd_cm_conn *conn = &domain->conn;
1986 /* We're closing down a possibly dead
1987 connection. Don't have impossibly long (10s) timeouts. */
1989 if (conn->cli) {
1990 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1993 if (conn->samr_pipe != NULL) {
1994 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1995 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1996 talloc_tos(),
1997 &conn->sam_connect_handle,
1998 &result);
2000 TALLOC_FREE(conn->samr_pipe);
2001 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2002 if (conn->cli) {
2003 cli_set_timeout(conn->cli, 500);
2007 if (conn->lsa_pipe != NULL) {
2008 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2009 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2010 talloc_tos(),
2011 &conn->lsa_policy,
2012 &result);
2014 TALLOC_FREE(conn->lsa_pipe);
2015 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2016 if (conn->cli) {
2017 cli_set_timeout(conn->cli, 500);
2021 if (conn->lsa_pipe_tcp != NULL) {
2022 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2023 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2024 talloc_tos(),
2025 &conn->lsa_policy,
2026 &result);
2028 TALLOC_FREE(conn->lsa_pipe_tcp);
2029 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2030 if (conn->cli) {
2031 cli_set_timeout(conn->cli, 500);
2035 if (conn->netlogon_pipe != NULL) {
2036 TALLOC_FREE(conn->netlogon_pipe);
2037 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2038 if (conn->cli) {
2039 cli_set_timeout(conn->cli, 500);
2043 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2044 conn->netlogon_force_reauth = false;
2045 TALLOC_FREE(conn->netlogon_creds_ctx);
2047 if (conn->cli) {
2048 cli_shutdown(conn->cli);
2051 conn->cli = NULL;
2054 void close_conns_after_fork(void)
2056 struct winbindd_domain *domain;
2057 struct winbindd_cli_state *cli_state;
2059 for (domain = domain_list(); domain; domain = domain->next) {
2061 * first close the low level SMB TCP connection
2062 * so that we don't generate any SMBclose
2063 * requests in invalidate_cm_connection()
2065 if (cli_state_is_connected(domain->conn.cli)) {
2066 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2069 invalidate_cm_connection(domain);
2072 for (cli_state = winbindd_client_list();
2073 cli_state != NULL;
2074 cli_state = cli_state->next) {
2075 if (cli_state->sock >= 0) {
2076 close(cli_state->sock);
2077 cli_state->sock = -1;
2082 static bool connection_ok(struct winbindd_domain *domain)
2084 bool ok;
2086 ok = cli_state_is_connected(domain->conn.cli);
2087 if (!ok) {
2088 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2089 domain->dcname, domain->name));
2090 return False;
2093 if (domain->online == False) {
2094 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2095 return False;
2098 return True;
2101 /* Initialize a new connection up to the RPC BIND.
2102 Bypass online status check so always does network calls. */
2104 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2106 NTSTATUS result;
2107 bool skip_connection = domain->internal;
2108 if (need_rw_dc && domain->rodc) {
2109 skip_connection = false;
2112 /* Internal connections never use the network. */
2113 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2114 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2117 /* Still ask the internal LSA and SAMR server about the local domain */
2118 if (skip_connection || connection_ok(domain)) {
2119 if (!domain->initialized) {
2120 set_dc_type_and_flags(domain);
2122 return NT_STATUS_OK;
2125 invalidate_cm_connection(domain);
2127 if (!domain->primary && !domain->initialized) {
2129 * Before we connect to a trust, work out if it is an
2130 * AD domain by asking our own domain.
2132 set_dc_type_and_flags_trustinfo(domain);
2135 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2137 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2138 set_dc_type_and_flags(domain);
2141 return result;
2144 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2146 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2147 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2150 if (domain->initialized && !domain->online) {
2151 /* We check for online status elsewhere. */
2152 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2155 return init_dc_connection_network(domain, need_rw_dc);
2158 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2160 NTSTATUS status;
2162 status = init_dc_connection(domain, need_rw_dc);
2163 if (!NT_STATUS_IS_OK(status)) {
2164 return status;
2167 if (!domain->internal && domain->conn.cli == NULL) {
2168 /* happens for trusted domains without inbound trust */
2169 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2172 return NT_STATUS_OK;
2175 /******************************************************************************
2176 Set the trust flags (direction and forest location) for a domain
2177 ******************************************************************************/
2179 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2181 struct winbindd_domain *our_domain;
2182 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2183 WERROR werr;
2184 struct netr_DomainTrustList trusts;
2185 int i;
2186 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2187 NETR_TRUST_FLAG_OUTBOUND |
2188 NETR_TRUST_FLAG_INBOUND);
2189 struct rpc_pipe_client *cli;
2190 TALLOC_CTX *mem_ctx = NULL;
2191 struct dcerpc_binding_handle *b;
2193 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2195 /* Our primary domain doesn't need to worry about trust flags.
2196 Force it to go through the network setup */
2197 if ( domain->primary ) {
2198 return False;
2201 mem_ctx = talloc_stackframe();
2202 our_domain = find_our_domain();
2203 if (our_domain->internal) {
2204 result = init_dc_connection(our_domain, false);
2205 if (!NT_STATUS_IS_OK(result)) {
2206 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2207 "Not able to make a connection to our domain: %s\n",
2208 nt_errstr(result)));
2209 TALLOC_FREE(mem_ctx);
2210 return false;
2214 /* This won't work unless our domain is AD */
2215 if ( !our_domain->active_directory ) {
2216 TALLOC_FREE(mem_ctx);
2217 return False;
2220 if (our_domain->internal) {
2221 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2222 } else if (!connection_ok(our_domain)) {
2223 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2224 "No connection to our domain!\n"));
2225 TALLOC_FREE(mem_ctx);
2226 return False;
2227 } else {
2228 result = cm_connect_netlogon(our_domain, &cli);
2231 if (!NT_STATUS_IS_OK(result)) {
2232 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2233 "a connection to %s for PIPE_NETLOGON (%s)\n",
2234 domain->name, nt_errstr(result)));
2235 TALLOC_FREE(mem_ctx);
2236 return False;
2238 b = cli->binding_handle;
2240 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2241 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2242 cli->desthost,
2243 flags,
2244 &trusts,
2245 &werr);
2246 if (!NT_STATUS_IS_OK(result)) {
2247 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2248 "failed to query trusted domain list: %s\n",
2249 nt_errstr(result)));
2250 TALLOC_FREE(mem_ctx);
2251 return false;
2253 if (!W_ERROR_IS_OK(werr)) {
2254 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2255 "failed to query trusted domain list: %s\n",
2256 win_errstr(werr)));
2257 TALLOC_FREE(mem_ctx);
2258 return false;
2261 /* Now find the domain name and get the flags */
2263 for ( i=0; i<trusts.count; i++ ) {
2264 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2265 domain->domain_flags = trusts.array[i].trust_flags;
2266 domain->domain_type = trusts.array[i].trust_type;
2267 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2269 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2270 domain->active_directory = True;
2272 /* This flag is only set if the domain is *our*
2273 primary domain and the primary domain is in
2274 native mode */
2276 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2278 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2279 "native mode.\n", domain->name,
2280 domain->native_mode ? "" : "NOT "));
2282 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2283 "running active directory.\n", domain->name,
2284 domain->active_directory ? "" : "NOT "));
2286 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2288 domain->initialized = True;
2290 break;
2294 TALLOC_FREE(mem_ctx);
2296 return domain->initialized;
2299 /******************************************************************************
2300 We can 'sense' certain things about the DC by it's replies to certain
2301 questions.
2303 This tells us if this particular remote server is Active Directory, and if it
2304 is native mode.
2305 ******************************************************************************/
2307 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2309 NTSTATUS status, result;
2310 WERROR werr;
2311 TALLOC_CTX *mem_ctx = NULL;
2312 struct rpc_pipe_client *cli = NULL;
2313 struct policy_handle pol;
2314 union dssetup_DsRoleInfo info;
2315 union lsa_PolicyInformation *lsa_info = NULL;
2317 if (!domain->internal && !connection_ok(domain)) {
2318 return;
2321 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2322 domain->name);
2323 if (!mem_ctx) {
2324 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2325 return;
2328 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2330 if (domain->internal) {
2331 status = wb_open_internal_pipe(mem_ctx,
2332 &ndr_table_dssetup,
2333 &cli);
2334 } else {
2335 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2336 &ndr_table_dssetup,
2337 &cli);
2340 if (!NT_STATUS_IS_OK(status)) {
2341 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2342 "PI_DSSETUP on domain %s: (%s)\n",
2343 domain->name, nt_errstr(status)));
2345 /* if this is just a non-AD domain we need to continue
2346 * identifying so that we can in the end return with
2347 * domain->initialized = True - gd */
2349 goto no_dssetup;
2352 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2353 DS_ROLE_BASIC_INFORMATION,
2354 &info,
2355 &werr);
2356 TALLOC_FREE(cli);
2358 if (NT_STATUS_IS_OK(status)) {
2359 result = werror_to_ntstatus(werr);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2363 "on domain %s failed: (%s)\n",
2364 domain->name, nt_errstr(status)));
2366 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2367 * every opcode on the DSSETUP pipe, continue with
2368 * no_dssetup mode here as well to get domain->initialized
2369 * set - gd */
2371 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2372 goto no_dssetup;
2375 TALLOC_FREE(mem_ctx);
2376 return;
2379 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2380 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2381 domain->native_mode = True;
2382 } else {
2383 domain->native_mode = False;
2386 no_dssetup:
2387 if (domain->internal) {
2388 status = wb_open_internal_pipe(mem_ctx,
2389 &ndr_table_lsarpc,
2390 &cli);
2391 } else {
2392 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2393 &ndr_table_lsarpc, &cli);
2395 if (!NT_STATUS_IS_OK(status)) {
2396 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2397 "PI_LSARPC on domain %s: (%s)\n",
2398 domain->name, nt_errstr(status)));
2399 TALLOC_FREE(cli);
2400 TALLOC_FREE(mem_ctx);
2401 return;
2404 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2405 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2407 if (NT_STATUS_IS_OK(status)) {
2408 /* This particular query is exactly what Win2k clients use
2409 to determine that the DC is active directory */
2410 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2411 &pol,
2412 LSA_POLICY_INFO_DNS,
2413 &lsa_info,
2414 &result);
2417 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2418 domain->active_directory = True;
2420 if (lsa_info->dns.name.string) {
2421 if (!strequal(domain->name, lsa_info->dns.name.string))
2423 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2424 "for domain %s claimed it was a DC "
2425 "for domain %s, refusing to "
2426 "initialize\n",
2427 domain->name,
2428 lsa_info->dns.name.string));
2429 TALLOC_FREE(cli);
2430 TALLOC_FREE(mem_ctx);
2431 return;
2433 talloc_free(domain->name);
2434 domain->name = talloc_strdup(domain,
2435 lsa_info->dns.name.string);
2436 if (domain->name == NULL) {
2437 goto done;
2441 if (lsa_info->dns.dns_domain.string) {
2442 if (domain->alt_name != NULL &&
2443 !strequal(domain->alt_name,
2444 lsa_info->dns.dns_domain.string))
2446 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2447 "for domain %s (%s) claimed it was "
2448 "a DC for domain %s, refusing to "
2449 "initialize\n",
2450 domain->alt_name, domain->name,
2451 lsa_info->dns.dns_domain.string));
2452 TALLOC_FREE(cli);
2453 TALLOC_FREE(mem_ctx);
2454 return;
2456 talloc_free(domain->alt_name);
2457 domain->alt_name =
2458 talloc_strdup(domain,
2459 lsa_info->dns.dns_domain.string);
2460 if (domain->alt_name == NULL) {
2461 goto done;
2465 /* See if we can set some domain trust flags about
2466 ourself */
2468 if (lsa_info->dns.dns_forest.string) {
2469 talloc_free(domain->forest_name);
2470 domain->forest_name =
2471 talloc_strdup(domain,
2472 lsa_info->dns.dns_forest.string);
2473 if (domain->forest_name == NULL) {
2474 goto done;
2477 if (strequal(domain->forest_name, domain->alt_name)) {
2478 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2482 if (lsa_info->dns.sid) {
2483 if (!is_null_sid(&domain->sid) &&
2484 !dom_sid_equal(&domain->sid,
2485 lsa_info->dns.sid))
2487 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2488 "for domain %s (%s) claimed it was "
2489 "a DC for domain %s, refusing to "
2490 "initialize\n",
2491 dom_sid_string(talloc_tos(),
2492 &domain->sid),
2493 domain->name,
2494 dom_sid_string(talloc_tos(),
2495 lsa_info->dns.sid)));
2496 TALLOC_FREE(cli);
2497 TALLOC_FREE(mem_ctx);
2498 return;
2500 sid_copy(&domain->sid, lsa_info->dns.sid);
2502 } else {
2503 domain->active_directory = False;
2505 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2506 SEC_FLAG_MAXIMUM_ALLOWED,
2507 &pol);
2509 if (!NT_STATUS_IS_OK(status)) {
2510 goto done;
2513 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2514 &pol,
2515 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2516 &lsa_info,
2517 &result);
2518 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2520 if (lsa_info->account_domain.name.string) {
2521 if (!strequal(domain->name,
2522 lsa_info->account_domain.name.string))
2524 DEBUG(1,
2525 ("set_dc_type_and_flags_connect: "
2526 "DC for domain %s claimed it was"
2527 " a DC for domain %s, refusing "
2528 "to initialize\n", domain->name,
2529 lsa_info->
2530 account_domain.name.string));
2531 TALLOC_FREE(cli);
2532 TALLOC_FREE(mem_ctx);
2533 return;
2535 talloc_free(domain->name);
2536 domain->name =
2537 talloc_strdup(domain,
2538 lsa_info->account_domain.name.string);
2541 if (lsa_info->account_domain.sid) {
2542 if (!is_null_sid(&domain->sid) &&
2543 !dom_sid_equal(&domain->sid,
2544 lsa_info->account_domain.sid))
2546 DEBUG(1,
2547 ("set_dc_type_and_flags_connect: "
2548 "DC for domain %s (%s) claimed "
2549 "it was a DC for domain %s, "
2550 "refusing to initialize\n",
2551 dom_sid_string(talloc_tos(),
2552 &domain->sid),
2553 domain->name,
2554 dom_sid_string(talloc_tos(),
2555 lsa_info->account_domain.sid)));
2556 TALLOC_FREE(cli);
2557 TALLOC_FREE(mem_ctx);
2558 return;
2560 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2564 done:
2566 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2567 domain->name, domain->native_mode ? "" : "NOT "));
2569 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2570 domain->name, domain->active_directory ? "" : "NOT "));
2572 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2574 TALLOC_FREE(cli);
2576 TALLOC_FREE(mem_ctx);
2578 domain->initialized = True;
2581 /**********************************************************************
2582 Set the domain_flags (trust attributes, domain operating modes, etc...
2583 ***********************************************************************/
2585 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2587 /* we always have to contact our primary domain */
2589 if ( domain->primary || domain->internal) {
2590 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2591 "primary or internal domain\n"));
2592 set_dc_type_and_flags_connect( domain );
2593 return;
2596 /* Use our DC to get the information if possible */
2598 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2599 /* Otherwise, fallback to contacting the
2600 domain directly */
2601 set_dc_type_and_flags_connect( domain );
2604 return;
2609 /**********************************************************************
2610 ***********************************************************************/
2612 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2613 struct netlogon_creds_cli_context **ppdc)
2615 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2616 struct rpc_pipe_client *netlogon_pipe;
2618 *ppdc = NULL;
2620 if ((!IS_DC) && (!domain->primary)) {
2621 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2624 if (domain->conn.netlogon_creds_ctx != NULL) {
2625 *ppdc = domain->conn.netlogon_creds_ctx;
2626 return NT_STATUS_OK;
2629 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2630 if (!NT_STATUS_IS_OK(result)) {
2631 return result;
2634 return NT_STATUS_OK;
2637 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2638 bool need_rw_dc,
2639 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2641 struct winbindd_cm_conn *conn;
2642 NTSTATUS status, result;
2643 struct netlogon_creds_cli_context *p_creds;
2644 struct cli_credentials *creds = NULL;
2645 bool retry = false; /* allow one retry attempt for expired session */
2647 if (sid_check_is_our_sam(&domain->sid)) {
2648 if (domain->rodc == false || need_rw_dc == false) {
2649 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2653 retry:
2654 status = init_dc_connection_rpc(domain, need_rw_dc);
2655 if (!NT_STATUS_IS_OK(status)) {
2656 return status;
2659 conn = &domain->conn;
2661 if (rpccli_is_connected(conn->samr_pipe)) {
2662 goto done;
2665 TALLOC_FREE(conn->samr_pipe);
2668 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2669 * sign and sealed pipe using the machine account password by
2670 * preference. If we can't - try schannel, if that fails, try
2671 * anonymous.
2674 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2675 if (!NT_STATUS_IS_OK(result)) {
2676 DEBUG(10, ("cm_connect_sam: No user available for "
2677 "domain %s, trying schannel\n", domain->name));
2678 goto schannel;
2681 if (cli_credentials_is_anonymous(creds)) {
2682 goto anonymous;
2686 * We have an authenticated connection. Use a SPNEGO
2687 * authenticated SAMR pipe with sign & seal.
2689 status = cli_rpc_pipe_open_with_creds(conn->cli,
2690 &ndr_table_samr,
2691 NCACN_NP,
2692 DCERPC_AUTH_TYPE_SPNEGO,
2693 conn->auth_level,
2694 smbXcli_conn_remote_name(conn->cli->conn),
2695 creds,
2696 &conn->samr_pipe);
2698 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2699 && !retry) {
2700 invalidate_cm_connection(domain);
2701 retry = true;
2702 goto retry;
2705 if (!NT_STATUS_IS_OK(status)) {
2706 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2707 "pipe for domain %s using NTLMSSP "
2708 "authenticated pipe: user %s. Error was "
2709 "%s\n", domain->name,
2710 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2711 nt_errstr(status)));
2712 goto schannel;
2715 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2716 "domain %s using NTLMSSP authenticated "
2717 "pipe: user %s\n", domain->name,
2718 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2720 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2721 conn->samr_pipe->desthost,
2722 SEC_FLAG_MAXIMUM_ALLOWED,
2723 &conn->sam_connect_handle,
2724 &result);
2726 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2727 invalidate_cm_connection(domain);
2728 TALLOC_FREE(conn->samr_pipe);
2729 retry = true;
2730 goto retry;
2733 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2734 goto open_domain;
2736 if (NT_STATUS_IS_OK(status)) {
2737 status = result;
2740 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2741 "failed for domain %s, error was %s. Trying schannel\n",
2742 domain->name, nt_errstr(status) ));
2743 TALLOC_FREE(conn->samr_pipe);
2745 schannel:
2747 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2749 status = cm_get_schannel_creds(domain, &p_creds);
2750 if (!NT_STATUS_IS_OK(status)) {
2751 /* If this call fails - conn->cli can now be NULL ! */
2752 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2753 "for domain %s (error %s), trying anon\n",
2754 domain->name,
2755 nt_errstr(status) ));
2756 goto anonymous;
2758 TALLOC_FREE(creds);
2759 status = cli_rpc_pipe_open_schannel_with_creds(
2760 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2761 &conn->samr_pipe);
2763 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2764 && !retry) {
2765 invalidate_cm_connection(domain);
2766 retry = true;
2767 goto retry;
2770 if (!NT_STATUS_IS_OK(status)) {
2771 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2772 "domain %s using schannel. Error was %s\n",
2773 domain->name, nt_errstr(status) ));
2774 goto anonymous;
2776 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2777 "schannel.\n", domain->name ));
2779 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2780 conn->samr_pipe->desthost,
2781 SEC_FLAG_MAXIMUM_ALLOWED,
2782 &conn->sam_connect_handle,
2783 &result);
2785 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2786 invalidate_cm_connection(domain);
2787 TALLOC_FREE(conn->samr_pipe);
2788 retry = true;
2789 goto retry;
2792 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2793 goto open_domain;
2795 if (NT_STATUS_IS_OK(status)) {
2796 status = result;
2798 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2799 "for domain %s, error was %s. Trying anonymous\n",
2800 domain->name, nt_errstr(status) ));
2801 TALLOC_FREE(conn->samr_pipe);
2803 anonymous:
2805 /* Finally fall back to anonymous. */
2806 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2807 status = NT_STATUS_DOWNGRADE_DETECTED;
2808 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2809 "without connection level security, "
2810 "must set 'winbind sealed pipes = false' and "
2811 "'require strong key = false' to proceed: %s\n",
2812 domain->name, nt_errstr(status)));
2813 goto done;
2815 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2816 &conn->samr_pipe);
2818 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2819 && !retry) {
2820 invalidate_cm_connection(domain);
2821 retry = true;
2822 goto retry;
2825 if (!NT_STATUS_IS_OK(status)) {
2826 goto done;
2829 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2830 conn->samr_pipe->desthost,
2831 SEC_FLAG_MAXIMUM_ALLOWED,
2832 &conn->sam_connect_handle,
2833 &result);
2835 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2836 invalidate_cm_connection(domain);
2837 TALLOC_FREE(conn->samr_pipe);
2838 retry = true;
2839 goto retry;
2842 if (!NT_STATUS_IS_OK(status)) {
2843 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2844 "for domain %s Error was %s\n",
2845 domain->name, nt_errstr(status) ));
2846 goto done;
2848 if (!NT_STATUS_IS_OK(result)) {
2849 status = result;
2850 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2851 "for domain %s Error was %s\n",
2852 domain->name, nt_errstr(result)));
2853 goto done;
2856 open_domain:
2857 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2858 mem_ctx,
2859 &conn->sam_connect_handle,
2860 SEC_FLAG_MAXIMUM_ALLOWED,
2861 &domain->sid,
2862 &conn->sam_domain_handle,
2863 &result);
2864 if (!NT_STATUS_IS_OK(status)) {
2865 goto done;
2868 status = result;
2869 done:
2871 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2873 * if we got access denied, we might just have no access rights
2874 * to talk to the remote samr server server (e.g. when we are a
2875 * PDC and we are connecting a w2k8 pdc via an interdomain
2876 * trust). In that case do not invalidate the whole connection
2877 * stack
2879 TALLOC_FREE(conn->samr_pipe);
2880 ZERO_STRUCT(conn->sam_domain_handle);
2881 return status;
2882 } else if (!NT_STATUS_IS_OK(status)) {
2883 invalidate_cm_connection(domain);
2884 return status;
2887 *cli = conn->samr_pipe;
2888 *sam_handle = conn->sam_domain_handle;
2889 return status;
2892 /**********************************************************************
2893 open an schanneld ncacn_ip_tcp connection to LSA
2894 ***********************************************************************/
2896 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2897 TALLOC_CTX *mem_ctx,
2898 struct rpc_pipe_client **cli)
2900 struct winbindd_cm_conn *conn;
2901 struct netlogon_creds_cli_context *p_creds = NULL;
2902 NTSTATUS status;
2904 DEBUG(10,("cm_connect_lsa_tcp\n"));
2906 status = init_dc_connection_rpc(domain, false);
2907 if (!NT_STATUS_IS_OK(status)) {
2908 return status;
2911 conn = &domain->conn;
2914 * rpccli_is_connected handles more error cases
2916 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2917 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2918 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2919 goto done;
2922 TALLOC_FREE(conn->lsa_pipe_tcp);
2924 status = cm_get_schannel_creds(domain, &p_creds);
2925 if (!NT_STATUS_IS_OK(status)) {
2926 goto done;
2929 status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
2930 &ndr_table_lsarpc,
2931 NCACN_IP_TCP,
2932 p_creds,
2933 &conn->lsa_pipe_tcp);
2934 if (!NT_STATUS_IS_OK(status)) {
2935 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2936 nt_errstr(status)));
2937 goto done;
2940 done:
2941 if (!NT_STATUS_IS_OK(status)) {
2942 TALLOC_FREE(conn->lsa_pipe_tcp);
2943 return status;
2946 *cli = conn->lsa_pipe_tcp;
2948 return status;
2951 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2952 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2954 struct winbindd_cm_conn *conn;
2955 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2956 struct netlogon_creds_cli_context *p_creds;
2957 struct cli_credentials *creds = NULL;
2958 bool retry = false; /* allow one retry attempt for expired session */
2960 retry:
2961 result = init_dc_connection_rpc(domain, false);
2962 if (!NT_STATUS_IS_OK(result))
2963 return result;
2965 conn = &domain->conn;
2967 if (rpccli_is_connected(conn->lsa_pipe)) {
2968 goto done;
2971 TALLOC_FREE(conn->lsa_pipe);
2973 if (IS_AD_DC) {
2975 * Make sure we only use schannel as AD DC.
2977 goto schannel;
2980 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2981 if (!NT_STATUS_IS_OK(result)) {
2982 DEBUG(10, ("cm_connect_lsa: No user available for "
2983 "domain %s, trying schannel\n", domain->name));
2984 goto schannel;
2987 if (cli_credentials_is_anonymous(creds)) {
2988 goto anonymous;
2992 * We have an authenticated connection. Use a SPNEGO
2993 * authenticated LSA pipe with sign & seal.
2995 result = cli_rpc_pipe_open_with_creds
2996 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2997 DCERPC_AUTH_TYPE_SPNEGO,
2998 conn->auth_level,
2999 smbXcli_conn_remote_name(conn->cli->conn),
3000 creds,
3001 &conn->lsa_pipe);
3003 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3004 && !retry) {
3005 invalidate_cm_connection(domain);
3006 retry = true;
3007 goto retry;
3010 if (!NT_STATUS_IS_OK(result)) {
3011 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3012 "domain %s using NTLMSSP authenticated pipe: user "
3013 "%s. Error was %s. Trying schannel.\n",
3014 domain->name,
3015 cli_credentials_get_unparsed_name(creds, talloc_tos()),
3016 nt_errstr(result)));
3017 goto schannel;
3020 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3021 "NTLMSSP authenticated pipe: user %s\n",
3022 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3024 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3025 SEC_FLAG_MAXIMUM_ALLOWED,
3026 &conn->lsa_policy);
3027 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3028 invalidate_cm_connection(domain);
3029 TALLOC_FREE(conn->lsa_pipe);
3030 retry = true;
3031 goto retry;
3034 if (NT_STATUS_IS_OK(result)) {
3035 goto done;
3038 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3039 "schannel\n"));
3041 TALLOC_FREE(conn->lsa_pipe);
3043 schannel:
3045 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3047 result = cm_get_schannel_creds(domain, &p_creds);
3048 if (!NT_STATUS_IS_OK(result)) {
3049 /* If this call fails - conn->cli can now be NULL ! */
3050 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3051 "for domain %s (error %s), trying anon\n",
3052 domain->name,
3053 nt_errstr(result) ));
3054 goto anonymous;
3057 TALLOC_FREE(creds);
3058 result = cli_rpc_pipe_open_schannel_with_creds(
3059 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3060 &conn->lsa_pipe);
3062 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3063 && !retry) {
3064 invalidate_cm_connection(domain);
3065 retry = true;
3066 goto retry;
3069 if (!NT_STATUS_IS_OK(result)) {
3070 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3071 "domain %s using schannel. Error was %s\n",
3072 domain->name, nt_errstr(result) ));
3073 goto anonymous;
3075 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3076 "schannel.\n", domain->name ));
3078 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3079 SEC_FLAG_MAXIMUM_ALLOWED,
3080 &conn->lsa_policy);
3082 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3083 invalidate_cm_connection(domain);
3084 TALLOC_FREE(conn->lsa_pipe);
3085 retry = true;
3086 goto retry;
3089 if (NT_STATUS_IS_OK(result)) {
3090 goto done;
3093 if (IS_AD_DC) {
3095 * Make sure we only use schannel as AD DC.
3097 goto done;
3100 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3101 "anonymous\n"));
3103 TALLOC_FREE(conn->lsa_pipe);
3105 anonymous:
3107 if (IS_AD_DC) {
3109 * Make sure we only use schannel as AD DC.
3111 goto done;
3114 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3115 result = NT_STATUS_DOWNGRADE_DETECTED;
3116 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3117 "without connection level security, "
3118 "must set 'winbind sealed pipes = false' and "
3119 "'require strong key = false' to proceed: %s\n",
3120 domain->name, nt_errstr(result)));
3121 goto done;
3124 result = cli_rpc_pipe_open_noauth(conn->cli,
3125 &ndr_table_lsarpc,
3126 &conn->lsa_pipe);
3128 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3129 && !retry) {
3130 invalidate_cm_connection(domain);
3131 retry = true;
3132 goto retry;
3135 if (!NT_STATUS_IS_OK(result)) {
3136 goto done;
3139 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3140 SEC_FLAG_MAXIMUM_ALLOWED,
3141 &conn->lsa_policy);
3143 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3144 invalidate_cm_connection(domain);
3145 TALLOC_FREE(conn->lsa_pipe);
3146 retry = true;
3147 goto retry;
3150 done:
3151 if (!NT_STATUS_IS_OK(result)) {
3152 invalidate_cm_connection(domain);
3153 return result;
3156 *cli = conn->lsa_pipe;
3157 *lsa_policy = conn->lsa_policy;
3158 return result;
3161 /****************************************************************************
3162 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3163 ****************************************************************************/
3165 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3166 TALLOC_CTX *mem_ctx,
3167 struct rpc_pipe_client **cli,
3168 struct policy_handle *lsa_policy)
3170 NTSTATUS status;
3172 if (domain->can_do_ncacn_ip_tcp) {
3173 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3174 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3175 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3176 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3177 invalidate_cm_connection(domain);
3178 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3180 if (NT_STATUS_IS_OK(status)) {
3181 return status;
3185 * we tried twice to connect via ncan_ip_tcp and schannel and
3186 * failed - maybe it is a trusted domain we can't connect to ?
3187 * do not try tcp next time - gd
3189 * This also prevents NETLOGON over TCP
3191 domain->can_do_ncacn_ip_tcp = false;
3194 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3196 return status;
3199 /****************************************************************************
3200 Open the netlogon pipe to this DC.
3201 ****************************************************************************/
3203 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3204 enum dcerpc_transport_t transport,
3205 struct rpc_pipe_client **cli)
3207 struct messaging_context *msg_ctx = server_messaging_context();
3208 struct winbindd_cm_conn *conn;
3209 NTSTATUS result;
3210 enum netr_SchannelType sec_chan_type;
3211 struct cli_credentials *creds = NULL;
3213 *cli = NULL;
3215 if (IS_AD_DC) {
3216 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3218 * Make sure we don't even try to
3219 * connect to a foreign domain
3220 * without a direct outbound trust.
3222 return NT_STATUS_NO_TRUST_LSA_SECRET;
3226 result = init_dc_connection_rpc(domain, domain->rodc);
3227 if (!NT_STATUS_IS_OK(result)) {
3228 return result;
3231 conn = &domain->conn;
3233 if (rpccli_is_connected(conn->netlogon_pipe)) {
3234 *cli = conn->netlogon_pipe;
3235 return NT_STATUS_OK;
3238 TALLOC_FREE(conn->netlogon_pipe);
3239 TALLOC_FREE(conn->netlogon_creds_ctx);
3241 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3242 if (!NT_STATUS_IS_OK(result)) {
3243 DBG_DEBUG("No user available for domain %s when trying "
3244 "schannel\n", domain->name);
3245 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3248 if (cli_credentials_is_anonymous(creds)) {
3249 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3250 "unable to make get NETLOGON credentials\n",
3251 domain->name);
3252 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3255 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3256 if (sec_chan_type == SEC_CHAN_NULL) {
3257 if (transport == NCACN_IP_TCP) {
3258 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3259 "for %s, deny NCACN_IP_TCP and let the "
3260 "caller fallback to NCACN_NP.\n",
3261 domain->name);
3262 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3265 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3266 "fallback to noauth on NCACN_NP.\n",
3267 domain->name);
3269 result = cli_rpc_pipe_open_noauth_transport(
3270 conn->cli,
3271 transport,
3272 &ndr_table_netlogon,
3273 &conn->netlogon_pipe);
3274 if (!NT_STATUS_IS_OK(result)) {
3275 invalidate_cm_connection(domain);
3276 return result;
3279 *cli = conn->netlogon_pipe;
3280 return NT_STATUS_OK;
3283 result = rpccli_create_netlogon_creds_ctx(creds,
3284 domain->dcname,
3285 msg_ctx,
3286 domain,
3287 &conn->netlogon_creds_ctx);
3288 if (!NT_STATUS_IS_OK(result)) {
3289 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3290 "unable to create NETLOGON credentials: %s\n",
3291 domain->name, nt_errstr(result)));
3292 return result;
3295 result = rpccli_connect_netlogon(
3296 conn->cli, transport,
3297 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3298 &conn->netlogon_pipe);
3299 if (!NT_STATUS_IS_OK(result)) {
3300 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3301 nt_errstr(result));
3302 return result;
3305 *cli = conn->netlogon_pipe;
3306 return NT_STATUS_OK;
3309 /****************************************************************************
3310 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3311 ****************************************************************************/
3313 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3314 struct rpc_pipe_client **cli)
3316 NTSTATUS status;
3318 status = init_dc_connection_rpc(domain, domain->rodc);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 return status;
3323 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3324 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3325 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3326 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3327 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3328 invalidate_cm_connection(domain);
3329 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3331 if (NT_STATUS_IS_OK(status)) {
3332 return status;
3336 * we tried twice to connect via ncan_ip_tcp and schannel and
3337 * failed - maybe it is a trusted domain we can't connect to ?
3338 * do not try tcp next time - gd
3340 * This also prevents LSA over TCP
3342 domain->can_do_ncacn_ip_tcp = false;
3345 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3346 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3348 * SMB2 session expired, needs reauthentication. Drop
3349 * connection and retry.
3351 invalidate_cm_connection(domain);
3352 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3355 return status;
3358 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3359 struct rpc_pipe_client **cli,
3360 struct netlogon_creds_cli_context **ppdc)
3362 NTSTATUS status;
3364 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3365 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3368 status = cm_connect_netlogon(domain, cli);
3369 if (!NT_STATUS_IS_OK(status)) {
3370 return status;
3373 if (domain->conn.netlogon_creds_ctx == NULL) {
3374 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3377 *ppdc = domain->conn.netlogon_creds_ctx;
3378 return NT_STATUS_OK;
3381 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3382 void *private_data,
3383 uint32_t msg_type,
3384 struct server_id server_id,
3385 DATA_BLOB *data)
3387 struct winbindd_domain *domain;
3388 char *freeit = NULL;
3389 char *addr;
3391 if ((data == NULL)
3392 || (data->data == NULL)
3393 || (data->length == 0)
3394 || (data->data[data->length-1] != '\0')) {
3395 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3396 "string\n"));
3397 return;
3400 addr = (char *)data->data;
3401 DEBUG(10, ("IP %s dropped\n", addr));
3403 if (!is_ipaddress(addr)) {
3404 char *slash;
3406 * Some code sends us ip addresses with the /netmask
3407 * suffix
3409 slash = strchr(addr, '/');
3410 if (slash == NULL) {
3411 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3412 addr));
3413 return;
3415 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3416 if (freeit == NULL) {
3417 DEBUG(1, ("talloc failed\n"));
3418 return;
3420 addr = freeit;
3421 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3424 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3425 char sockaddr[INET6_ADDRSTRLEN];
3427 if (!cli_state_is_connected(domain->conn.cli)) {
3428 continue;
3431 print_sockaddr(sockaddr, sizeof(sockaddr),
3432 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3434 if (strequal(sockaddr, addr)) {
3435 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3438 TALLOC_FREE(freeit);