rpc_client3: Avoid "cli_credentials" in cli_rpc_pipe_open_schannel_with_creds
[Samba.git] / source3 / winbindd / winbindd_cm.c
bloba5e5ab3f4e35879618d27c48aa2ea09e5c3e2934
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
34 selection etc
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
46 implementation. -tpot
51 TODO:
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
57 various sam handles.
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "libsmb/libsmb.h"
73 #include "libsmb/clidgram.h"
74 #include "ads.h"
75 #include "secrets.h"
76 #include "../libcli/security/security.h"
77 #include "passdb.h"
78 #include "messages.h"
79 #include "auth/gensec/gensec.h"
80 #include "../libcli/smb/smbXcli_base.h"
81 #include "libcli/auth/netlogon_creds_cli.h"
82 #include "auth.h"
83 #include "rpc_server/rpc_ncacn_np.h"
84 #include "auth/credentials/credentials.h"
85 #include "lib/param/param.h"
87 #undef DBGC_CLASS
88 #define DBGC_CLASS DBGC_WINBIND
90 struct dc_name_ip {
91 fstring name;
92 struct sockaddr_storage ss;
95 extern struct winbindd_methods reconnect_methods;
96 extern bool override_logfile;
98 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
99 static void set_dc_type_and_flags( struct winbindd_domain *domain );
100 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
101 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
102 struct dc_name_ip **dcs, int *num_dcs,
103 uint32_t request_flags);
105 /****************************************************************
106 Child failed to find DC's. Reschedule check.
107 ****************************************************************/
109 static void msg_failed_to_go_online(struct messaging_context *msg,
110 void *private_data,
111 uint32_t msg_type,
112 struct server_id server_id,
113 DATA_BLOB *data)
115 struct winbindd_domain *domain;
116 const char *domainname = (const char *)data->data;
118 if (data->data == NULL || data->length == 0) {
119 return;
122 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
124 for (domain = domain_list(); domain; domain = domain->next) {
125 if (domain->internal) {
126 continue;
129 if (strequal(domain->name, domainname)) {
130 if (domain->online) {
131 /* We're already online, ignore. */
132 DEBUG(5,("msg_fail_to_go_online: domain %s "
133 "already online.\n", domainname));
134 continue;
137 /* Reschedule the online check. */
138 set_domain_offline(domain);
139 break;
144 /****************************************************************
145 Actually cause a reconnect from a message.
146 ****************************************************************/
148 static void msg_try_to_go_online(struct messaging_context *msg,
149 void *private_data,
150 uint32_t msg_type,
151 struct server_id server_id,
152 DATA_BLOB *data)
154 struct winbindd_domain *domain;
155 const char *domainname = (const char *)data->data;
157 if (data->data == NULL || data->length == 0) {
158 return;
161 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
163 for (domain = domain_list(); domain; domain = domain->next) {
164 if (domain->internal) {
165 continue;
168 if (strequal(domain->name, domainname)) {
170 if (domain->online) {
171 /* We're already online, ignore. */
172 DEBUG(5,("msg_try_to_go_online: domain %s "
173 "already online.\n", domainname));
174 continue;
177 /* This call takes care of setting the online
178 flag to true if we connected, or re-adding
179 the offline handler if false. Bypasses online
180 check so always does network calls. */
182 init_dc_connection_network(domain, true);
183 break;
188 /****************************************************************
189 Fork a child to try and contact a DC. Do this as contacting a
190 DC requires blocking lookups and we don't want to block our
191 parent.
192 ****************************************************************/
194 static bool fork_child_dc_connect(struct winbindd_domain *domain)
196 struct dc_name_ip *dcs = NULL;
197 int num_dcs = 0;
198 TALLOC_CTX *mem_ctx = NULL;
199 pid_t parent_pid = getpid();
200 char *lfile = NULL;
201 NTSTATUS status;
203 if (domain->dc_probe_pid != (pid_t)-1) {
205 * We might already have a DC probe
206 * child working, check.
208 if (process_exists_by_pid(domain->dc_probe_pid)) {
209 DEBUG(10,("fork_child_dc_connect: pid %u already "
210 "checking for DC's.\n",
211 (unsigned int)domain->dc_probe_pid));
212 return true;
214 domain->dc_probe_pid = (pid_t)-1;
217 domain->dc_probe_pid = fork();
219 if (domain->dc_probe_pid == (pid_t)-1) {
220 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
221 return False;
224 if (domain->dc_probe_pid != (pid_t)0) {
225 /* Parent */
226 messaging_register(winbind_messaging_context(), NULL,
227 MSG_WINBIND_TRY_TO_GO_ONLINE,
228 msg_try_to_go_online);
229 messaging_register(winbind_messaging_context(), NULL,
230 MSG_WINBIND_FAILED_TO_GO_ONLINE,
231 msg_failed_to_go_online);
232 return True;
235 /* Child. */
237 /* Leave messages blocked - we will never process one. */
239 if (!override_logfile) {
240 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
241 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
242 _exit(1);
246 status = winbindd_reinit_after_fork(NULL, lfile);
247 if (!NT_STATUS_IS_OK(status)) {
248 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
249 nt_errstr(status)));
250 messaging_send_buf(winbind_messaging_context(),
251 pid_to_procid(parent_pid),
252 MSG_WINBIND_FAILED_TO_GO_ONLINE,
253 (const uint8_t *)domain->name,
254 strlen(domain->name)+1);
255 _exit(1);
257 SAFE_FREE(lfile);
259 mem_ctx = talloc_init("fork_child_dc_connect");
260 if (!mem_ctx) {
261 DEBUG(0,("talloc_init failed.\n"));
262 messaging_send_buf(winbind_messaging_context(),
263 pid_to_procid(parent_pid),
264 MSG_WINBIND_FAILED_TO_GO_ONLINE,
265 (const uint8_t *)domain->name,
266 strlen(domain->name)+1);
267 _exit(1);
270 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs, 0)) || (num_dcs == 0)) {
271 /* Still offline ? Can't find DC's. */
272 messaging_send_buf(winbind_messaging_context(),
273 pid_to_procid(parent_pid),
274 MSG_WINBIND_FAILED_TO_GO_ONLINE,
275 (const uint8_t *)domain->name,
276 strlen(domain->name)+1);
277 _exit(0);
280 /* We got a DC. Send a message to our parent to get it to
281 try and do the same. */
283 messaging_send_buf(winbind_messaging_context(),
284 pid_to_procid(parent_pid),
285 MSG_WINBIND_TRY_TO_GO_ONLINE,
286 (const uint8_t *)domain->name,
287 strlen(domain->name)+1);
288 _exit(0);
291 /****************************************************************
292 Handler triggered if we're offline to try and detect a DC.
293 ****************************************************************/
295 static void check_domain_online_handler(struct tevent_context *ctx,
296 struct tevent_timer *te,
297 struct timeval now,
298 void *private_data)
300 struct winbindd_domain *domain =
301 (struct winbindd_domain *)private_data;
303 DEBUG(10,("check_domain_online_handler: called for domain "
304 "%s (online = %s)\n", domain->name,
305 domain->online ? "True" : "False" ));
307 TALLOC_FREE(domain->check_online_event);
309 /* Are we still in "startup" mode ? */
311 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
312 /* No longer in "startup" mode. */
313 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
314 domain->name ));
315 domain->startup = False;
318 /* We've been told to stay offline, so stay
319 that way. */
321 if (get_global_winbindd_state_offline()) {
322 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
323 domain->name ));
324 return;
327 /* Fork a child to test if it can contact a DC.
328 If it can then send ourselves a message to
329 cause a reconnect. */
331 fork_child_dc_connect(domain);
334 /****************************************************************
335 If we're still offline setup the timeout check.
336 ****************************************************************/
338 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
340 int wbr = lp_winbind_reconnect_delay();
342 if (domain->startup) {
343 domain->check_online_timeout = 10;
344 } else if (domain->check_online_timeout < wbr) {
345 domain->check_online_timeout = wbr;
349 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
350 void *private_data,
351 uint32_t msg_type,
352 struct server_id server_id,
353 DATA_BLOB *data)
355 const char *domain_name = (const char *)data->data;
356 struct winbindd_domain *domain;
358 domain = find_domain_from_name_noinit(domain_name);
359 if (domain == NULL) {
360 return;
363 domain->online = false;
365 DEBUG(10, ("Domain %s is marked as offline now.\n",
366 domain_name));
369 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
370 void *private_data,
371 uint32_t msg_type,
372 struct server_id server_id,
373 DATA_BLOB *data)
375 const char *domain_name = (const char *)data->data;
376 struct winbindd_domain *domain;
378 domain = find_domain_from_name_noinit(domain_name);
379 if (domain == NULL) {
380 return;
383 domain->online = true;
385 DEBUG(10, ("Domain %s is marked as online now.\n",
386 domain_name));
389 /****************************************************************
390 Set domain offline and also add handler to put us back online
391 if we detect a DC.
392 ****************************************************************/
394 void set_domain_offline(struct winbindd_domain *domain)
396 pid_t parent_pid = getppid();
398 DEBUG(10,("set_domain_offline: called for domain %s\n",
399 domain->name ));
401 TALLOC_FREE(domain->check_online_event);
403 if (domain->internal) {
404 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
405 domain->name ));
406 return;
409 domain->online = False;
411 /* Offline domains are always initialized. They're
412 re-initialized when they go back online. */
414 domain->initialized = True;
416 /* We only add the timeout handler that checks and
417 allows us to go back online when we've not
418 been told to remain offline. */
420 if (get_global_winbindd_state_offline()) {
421 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
422 domain->name ));
423 return;
426 /* If we're in startup mode, check again in 10 seconds, not in
427 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
429 calc_new_online_timeout_check(domain);
431 domain->check_online_event = tevent_add_timer(winbind_event_context(),
432 NULL,
433 timeval_current_ofs(domain->check_online_timeout,0),
434 check_domain_online_handler,
435 domain);
437 /* The above *has* to succeed for winbindd to work. */
438 if (!domain->check_online_event) {
439 smb_panic("set_domain_offline: failed to add online handler");
442 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
443 domain->name ));
445 /* Send a message to the parent that the domain is offline. */
446 if (parent_pid > 1 && !domain->internal) {
447 messaging_send_buf(winbind_messaging_context(),
448 pid_to_procid(parent_pid),
449 MSG_WINBIND_DOMAIN_OFFLINE,
450 (uint8_t *)domain->name,
451 strlen(domain->name) + 1);
454 /* Send an offline message to the idmap child when our
455 primary domain goes offline */
457 if ( domain->primary ) {
458 struct winbindd_child *idmap = idmap_child();
460 if ( idmap->pid != 0 ) {
461 messaging_send_buf(winbind_messaging_context(),
462 pid_to_procid(idmap->pid),
463 MSG_WINBIND_OFFLINE,
464 (const uint8_t *)domain->name,
465 strlen(domain->name)+1);
469 return;
472 /****************************************************************
473 Set domain online - if allowed.
474 ****************************************************************/
476 static void set_domain_online(struct winbindd_domain *domain)
478 pid_t parent_pid = getppid();
480 DEBUG(10,("set_domain_online: called for domain %s\n",
481 domain->name ));
483 if (domain->internal) {
484 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
485 domain->name ));
486 return;
489 if (get_global_winbindd_state_offline()) {
490 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
491 domain->name ));
492 return;
495 winbindd_set_locator_kdc_envs(domain);
497 /* If we are waiting to get a krb5 ticket, trigger immediately. */
498 ccache_regain_all_now();
500 /* Ok, we're out of any startup mode now... */
501 domain->startup = False;
503 if (domain->online == False) {
504 /* We were offline - now we're online. We default to
505 using the MS-RPC backend if we started offline,
506 and if we're going online for the first time we
507 should really re-initialize the backends and the
508 checks to see if we're talking to an AD or NT domain.
511 domain->initialized = False;
513 /* 'reconnect_methods' is the MS-RPC backend. */
514 if (domain->backend == &reconnect_methods) {
515 domain->backend = NULL;
519 /* Ensure we have no online timeout checks. */
520 domain->check_online_timeout = 0;
521 TALLOC_FREE(domain->check_online_event);
523 /* Ensure we ignore any pending child messages. */
524 messaging_deregister(winbind_messaging_context(),
525 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
526 messaging_deregister(winbind_messaging_context(),
527 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
529 domain->online = True;
531 /* Send a message to the parent that the domain is online. */
532 if (parent_pid > 1 && !domain->internal) {
533 messaging_send_buf(winbind_messaging_context(),
534 pid_to_procid(parent_pid),
535 MSG_WINBIND_DOMAIN_ONLINE,
536 (uint8_t *)domain->name,
537 strlen(domain->name) + 1);
540 /* Send an online message to the idmap child when our
541 primary domain comes online */
543 if ( domain->primary ) {
544 struct winbindd_child *idmap = idmap_child();
546 if ( idmap->pid != 0 ) {
547 messaging_send_buf(winbind_messaging_context(),
548 pid_to_procid(idmap->pid),
549 MSG_WINBIND_ONLINE,
550 (const uint8_t *)domain->name,
551 strlen(domain->name)+1);
555 return;
558 /****************************************************************
559 Requested to set a domain online.
560 ****************************************************************/
562 void set_domain_online_request(struct winbindd_domain *domain)
564 struct timeval tev;
566 DEBUG(10,("set_domain_online_request: called for domain %s\n",
567 domain->name ));
569 if (get_global_winbindd_state_offline()) {
570 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
571 domain->name ));
572 return;
575 if (domain->internal) {
576 DEBUG(10, ("set_domain_online_request: Internal domains are "
577 "always online\n"));
578 return;
581 /* We've been told it's safe to go online and
582 try and connect to a DC. But I don't believe it
583 because network manager seems to lie.
584 Wait at least 5 seconds. Heuristics suck... */
587 GetTimeOfDay(&tev);
589 /* Go into "startup" mode again. */
590 domain->startup_time = time_mono(NULL);
591 domain->startup = True;
593 tev.tv_sec += 5;
595 if (!domain->check_online_event) {
596 /* If we've come from being globally offline we
597 don't have a check online event handler set.
598 We need to add one now we're trying to go
599 back online. */
601 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
602 domain->name ));
605 TALLOC_FREE(domain->check_online_event);
607 domain->check_online_event = tevent_add_timer(winbind_event_context(),
608 NULL,
609 tev,
610 check_domain_online_handler,
611 domain);
613 /* The above *has* to succeed for winbindd to work. */
614 if (!domain->check_online_event) {
615 smb_panic("set_domain_online_request: failed to add online handler");
619 /****************************************************************
620 Add -ve connection cache entries for domain and realm.
621 ****************************************************************/
623 static void winbind_add_failed_connection_entry(
624 const struct winbindd_domain *domain,
625 const char *server,
626 NTSTATUS result)
628 add_failed_connection_entry(domain->name, server, result);
629 /* If this was the saf name for the last thing we talked to,
630 remove it. */
631 saf_delete(domain->name);
632 if (domain->alt_name != NULL) {
633 add_failed_connection_entry(domain->alt_name, server, result);
634 saf_delete(domain->alt_name);
636 winbindd_unset_locator_kdc_env(domain);
639 /* Choose between anonymous or authenticated connections. We need to use
640 an authenticated connection if DCs have the RestrictAnonymous registry
641 entry set > 0, or the "Additional restrictions for anonymous
642 connections" set in the win2k Local Security Policy.
644 Caller to free() result in domain, username, password
647 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
649 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
650 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
651 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
653 if (*username && **username) {
655 if (!*domain || !**domain)
656 *domain = smb_xstrdup(lp_workgroup());
658 if (!*password || !**password)
659 *password = smb_xstrdup("");
661 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
662 *domain, *username));
664 } else {
665 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
666 *username = smb_xstrdup("");
667 *domain = smb_xstrdup("");
668 *password = smb_xstrdup("");
672 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
673 struct cli_credentials **_creds)
676 TALLOC_CTX *frame = talloc_stackframe();
677 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
678 struct loadparm_context *lp_ctx;
679 char *username = NULL;
680 char *netbios_domain = NULL;
681 char *password = NULL;
682 struct cli_credentials *creds = NULL;
683 bool ok;
685 cm_get_ipc_userpass(&username, &netbios_domain, &password);
687 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
688 if (lp_ctx == NULL) {
689 DEBUG(1, ("loadparm_init_s3 failed\n"));
690 status = NT_STATUS_INTERNAL_ERROR;
691 goto fail;
694 creds = cli_credentials_init(mem_ctx);
695 if (creds == NULL) {
696 status = NT_STATUS_NO_MEMORY;
697 goto fail;
700 cli_credentials_set_conf(creds, lp_ctx);
701 cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
703 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
704 if (!ok) {
705 status = NT_STATUS_NO_MEMORY;
706 goto fail;
709 ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
710 if (!ok) {
711 status = NT_STATUS_NO_MEMORY;
712 goto fail;
715 ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
716 if (!ok) {
717 status = NT_STATUS_NO_MEMORY;
718 goto fail;
721 *_creds = creds;
722 creds = NULL;
723 status = NT_STATUS_OK;
724 fail:
725 TALLOC_FREE(creds);
726 SAFE_FREE(username);
727 SAFE_FREE(netbios_domain);
728 SAFE_FREE(password);
729 TALLOC_FREE(frame);
730 return status;
733 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
735 TALLOC_CTX *frame = talloc_stackframe();
736 char *ipc_account = NULL;
737 char *ipc_domain = NULL;
738 char *ipc_password = NULL;
739 const char *creds_account = NULL;
740 const char *creds_domain = NULL;
741 const char *creds_password = NULL;
742 bool ret = false;
744 cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
746 creds_account = cli_credentials_get_username(creds);
747 creds_domain = cli_credentials_get_domain(creds);
748 creds_password = cli_credentials_get_password(creds);
750 if (!strequal(ipc_domain, creds_domain)) {
751 goto done;
754 if (!strequal(ipc_account, creds_account)) {
755 goto done;
758 if (!strcsequal(ipc_password, creds_password)) {
759 goto done;
762 ret = true;
763 done:
764 SAFE_FREE(ipc_account);
765 SAFE_FREE(ipc_domain);
766 SAFE_FREE(ipc_password);
767 TALLOC_FREE(frame);
768 return ret;
771 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
772 fstring dcname,
773 struct sockaddr_storage *dc_ss,
774 uint32_t request_flags)
776 struct winbindd_domain *our_domain = NULL;
777 struct rpc_pipe_client *netlogon_pipe = NULL;
778 NTSTATUS result;
779 WERROR werr;
780 TALLOC_CTX *mem_ctx;
781 unsigned int orig_timeout;
782 const char *tmp = NULL;
783 const char *p;
784 struct dcerpc_binding_handle *b;
786 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
787 * moment.... */
789 if (IS_DC) {
790 return False;
793 if (domain->primary) {
794 return False;
797 our_domain = find_our_domain();
799 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
800 return False;
803 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
804 if (!NT_STATUS_IS_OK(result)) {
805 talloc_destroy(mem_ctx);
806 return False;
809 b = netlogon_pipe->binding_handle;
811 /* This call can take a long time - allow the server to time out.
812 35 seconds should do it. */
814 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
816 if (our_domain->active_directory) {
817 struct netr_DsRGetDCNameInfo *domain_info = NULL;
820 * TODO request flags are not respected in the server
821 * (and in some cases, like REQUIRE_PDC, causes an error)
823 result = dcerpc_netr_DsRGetDCName(b,
824 mem_ctx,
825 our_domain->dcname,
826 domain->name,
827 NULL,
828 NULL,
829 request_flags|DS_RETURN_DNS_NAME,
830 &domain_info,
831 &werr);
832 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
833 tmp = talloc_strdup(
834 mem_ctx, domain_info->dc_unc);
835 if (tmp == NULL) {
836 DEBUG(0, ("talloc_strdup failed\n"));
837 talloc_destroy(mem_ctx);
838 return false;
840 if (domain->alt_name == NULL) {
841 domain->alt_name = talloc_strdup(domain,
842 domain_info->domain_name);
843 if (domain->alt_name == NULL) {
844 DEBUG(0, ("talloc_strdup failed\n"));
845 talloc_destroy(mem_ctx);
846 return false;
849 if (domain->forest_name == NULL) {
850 domain->forest_name = talloc_strdup(domain,
851 domain_info->forest_name);
852 if (domain->forest_name == NULL) {
853 DEBUG(0, ("talloc_strdup failed\n"));
854 talloc_destroy(mem_ctx);
855 return false;
859 } else {
860 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
861 our_domain->dcname,
862 domain->name,
863 &tmp,
864 &werr);
867 /* And restore our original timeout. */
868 rpccli_set_timeout(netlogon_pipe, orig_timeout);
870 if (!NT_STATUS_IS_OK(result)) {
871 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
872 nt_errstr(result)));
873 talloc_destroy(mem_ctx);
874 return false;
877 if (!W_ERROR_IS_OK(werr)) {
878 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
879 win_errstr(werr)));
880 talloc_destroy(mem_ctx);
881 return false;
884 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
885 p = strip_hostname(tmp);
887 fstrcpy(dcname, p);
889 talloc_destroy(mem_ctx);
891 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
893 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
894 return False;
897 return True;
901 * Helper function to assemble trust password and account name
903 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
904 TALLOC_CTX *mem_ctx,
905 bool netlogon,
906 struct cli_credentials **_creds)
908 const struct winbindd_domain *creds_domain = NULL;
909 struct cli_credentials *creds;
910 NTSTATUS status;
911 bool force_machine_account = false;
913 /* If we are a DC and this is not our own domain */
915 if (!domain->active_directory) {
916 if (!netlogon) {
918 * For non active directory domains
919 * we can only use NTLMSSP for SMB.
921 * But the trust account is not allowed
922 * to use SMB with NTLMSSP.
924 force_machine_account = true;
928 if (IS_DC && !force_machine_account) {
929 creds_domain = domain;
930 } else {
931 creds_domain = find_our_domain();
932 if (creds_domain == NULL) {
933 return NT_STATUS_INVALID_SERVER_STATE;
937 status = pdb_get_trust_credentials(creds_domain->name,
938 creds_domain->alt_name,
939 mem_ctx,
940 &creds);
941 if (!NT_STATUS_IS_OK(status)) {
942 goto ipc_fallback;
945 if (creds_domain != domain) {
947 * We can only use schannel against a direct trust
949 cli_credentials_set_secure_channel_type(creds,
950 SEC_CHAN_NULL);
953 *_creds = creds;
954 return NT_STATUS_OK;
956 ipc_fallback:
957 if (netlogon) {
958 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
961 status = cm_get_ipc_credentials(mem_ctx, &creds);
962 if (!NT_STATUS_IS_OK(status)) {
963 return status;
966 *_creds = creds;
967 return NT_STATUS_OK;
970 /************************************************************************
971 Given a fd with a just-connected TCP connection to a DC, open a connection
972 to the pipe.
973 ************************************************************************/
975 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
976 const int sockfd,
977 const char *controller,
978 struct cli_state **cli,
979 bool *retry)
981 bool try_ipc_auth = false;
982 const char *machine_principal = NULL;
983 const char *machine_realm = NULL;
984 const char *machine_account = NULL;
985 const char *machine_domain = NULL;
986 int flags = 0;
987 struct cli_credentials *creds = NULL;
989 struct named_mutex *mutex;
991 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
992 NTSTATUS tmp_status;
993 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
995 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
997 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
999 * If we are connecting to our own AD domain, require
1000 * smb signing to disrupt MITM attacks
1002 if (domain->primary && lp_security() == SEC_ADS) {
1003 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1005 * If we are in or are an AD domain and connecting to another
1006 * AD domain in our forest
1007 * then require smb signing to disrupt MITM attacks
1009 } else if ((lp_security() == SEC_ADS ||
1010 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)
1011 && domain->active_directory
1012 && (domain->domain_trust_attribs
1013 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
1014 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1018 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1019 controller, domain->name ));
1021 *retry = True;
1023 mutex = grab_named_mutex(talloc_tos(), controller,
1024 WINBIND_SERVER_MUTEX_WAIT_TIME);
1025 if (mutex == NULL) {
1026 close(sockfd);
1027 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1028 controller));
1029 result = NT_STATUS_POSSIBLE_DEADLOCK;
1030 goto done;
1033 *cli = cli_state_create(NULL, sockfd, controller,
1034 smb_sign_client_connections, flags);
1035 if (*cli == NULL) {
1036 close(sockfd);
1037 DEBUG(1, ("Could not cli_initialize\n"));
1038 result = NT_STATUS_NO_MEMORY;
1039 goto done;
1042 cli_set_timeout(*cli, 10000); /* 10 seconds */
1044 set_socket_options(sockfd, lp_socket_options());
1046 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
1047 lp_client_ipc_min_protocol(),
1048 lp_client_ipc_max_protocol());
1050 if (!NT_STATUS_IS_OK(result)) {
1051 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
1052 goto done;
1055 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
1056 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
1057 try_ipc_auth = true;
1058 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1059 try_ipc_auth = true;
1060 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1062 * If we are forcing on SMB signing, then we must
1063 * require authentication unless this is a one-way
1064 * trust, and we have no stored user/password
1066 try_ipc_auth = true;
1069 if (try_ipc_auth) {
1070 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
1071 if (!NT_STATUS_IS_OK(result)) {
1072 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1073 domain->name, nt_errstr(result)));
1074 goto done;
1076 } else {
1078 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1079 * would try and authentication with our machine
1080 * account password and fail. This is very rare in
1081 * the modern world however
1083 creds = cli_credentials_init_anon(talloc_tos());
1084 if (creds == NULL) {
1085 result = NT_STATUS_NO_MEMORY;
1086 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1087 domain->name, nt_errstr(result)));
1088 goto done;
1092 machine_principal = cli_credentials_get_principal(creds,
1093 talloc_tos());
1094 machine_realm = cli_credentials_get_realm(creds);
1095 machine_account = cli_credentials_get_username(creds);
1096 machine_domain = cli_credentials_get_domain(creds);
1098 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1099 "[%s] and realm [%s]\n",
1100 controller, domain->name, domain->alt_name,
1101 machine_domain, machine_account,
1102 machine_principal, machine_realm));
1104 if (cli_credentials_is_anonymous(creds)) {
1105 goto anon_fallback;
1108 winbindd_set_locator_kdc_envs(domain);
1110 result = cli_session_setup_creds(*cli, creds);
1111 if (NT_STATUS_IS_OK(result)) {
1112 goto session_setup_done;
1115 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1116 controller,
1117 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1118 nt_errstr(result)));
1121 * If we are not going to validiate the conneciton
1122 * with SMB signing, then allow us to fall back to
1123 * anonymous
1125 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1126 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1127 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1128 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1129 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1131 if (!cm_is_ipc_credentials(creds)) {
1132 goto ipc_fallback;
1135 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1136 goto done;
1139 goto anon_fallback;
1142 goto done;
1144 ipc_fallback:
1145 TALLOC_FREE(creds);
1146 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1147 if (!NT_STATUS_IS_OK(tmp_status)) {
1148 result = tmp_status;
1149 goto done;
1152 if (cli_credentials_is_anonymous(creds)) {
1153 goto anon_fallback;
1156 machine_account = cli_credentials_get_username(creds);
1157 machine_domain = cli_credentials_get_domain(creds);
1159 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1160 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1161 machine_domain, machine_account));
1163 result = cli_session_setup_creds(*cli, creds);
1164 if (NT_STATUS_IS_OK(result)) {
1165 goto session_setup_done;
1168 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1169 controller,
1170 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1171 nt_errstr(result)));
1174 * If we are not going to validiate the conneciton
1175 * with SMB signing, then allow us to fall back to
1176 * anonymous
1178 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1179 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1180 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1181 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1182 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1184 goto anon_fallback;
1187 goto done;
1189 anon_fallback:
1190 TALLOC_FREE(creds);
1192 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1193 goto done;
1196 /* Fall back to anonymous connection, this might fail later */
1197 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1198 "connection for DC %s\n",
1199 controller ));
1201 result = cli_session_setup_anon(*cli);
1202 if (NT_STATUS_IS_OK(result)) {
1203 DEBUG(5, ("Connected anonymously\n"));
1204 goto session_setup_done;
1207 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1208 controller, nt_errstr(result)));
1210 /* We can't session setup */
1211 goto done;
1213 session_setup_done:
1214 TALLOC_FREE(creds);
1217 * This should be a short term hack until
1218 * dynamic re-authentication is implemented.
1220 * See Bug 9175 - winbindd doesn't recover from
1221 * NT_STATUS_NETWORK_SESSION_EXPIRED
1223 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1224 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1227 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1228 if (!NT_STATUS_IS_OK(result)) {
1229 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1230 goto done;
1232 tcon_status = result;
1234 /* cache the server name for later connections */
1236 saf_store(domain->name, controller);
1237 if (domain->alt_name) {
1238 saf_store(domain->alt_name, controller);
1241 winbindd_set_locator_kdc_envs(domain);
1243 TALLOC_FREE(mutex);
1244 *retry = False;
1246 result = NT_STATUS_OK;
1248 done:
1249 TALLOC_FREE(mutex);
1250 TALLOC_FREE(creds);
1252 if (NT_STATUS_IS_OK(result)) {
1253 result = tcon_status;
1256 if (!NT_STATUS_IS_OK(result)) {
1257 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1258 controller, nt_errstr(result)));
1259 winbind_add_failed_connection_entry(domain, controller, result);
1260 if ((*cli) != NULL) {
1261 cli_shutdown(*cli);
1262 *cli = NULL;
1266 return result;
1269 /*******************************************************************
1270 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1271 array.
1273 Keeps the list unique by not adding duplicate entries.
1275 @param[in] mem_ctx talloc memory context to allocate from
1276 @param[in] domain_name domain of the DC
1277 @param[in] dcname name of the DC to add to the list
1278 @param[in] pss Internet address and port pair to add to the list
1279 @param[in,out] dcs array of dc_name_ip structures to add to
1280 @param[in,out] num_dcs number of dcs returned in the dcs array
1281 @return true if the list was added to, false otherwise
1282 *******************************************************************/
1284 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1285 const char *dcname, struct sockaddr_storage *pss,
1286 struct dc_name_ip **dcs, int *num)
1288 int i = 0;
1290 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1291 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1292 return False;
1295 /* Make sure there's no duplicates in the list */
1296 for (i=0; i<*num; i++)
1297 if (sockaddr_equal(
1298 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1299 (struct sockaddr *)(void *)pss))
1300 return False;
1302 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1304 if (*dcs == NULL)
1305 return False;
1307 fstrcpy((*dcs)[*num].name, dcname);
1308 (*dcs)[*num].ss = *pss;
1309 *num += 1;
1310 return True;
1313 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1314 struct sockaddr_storage *pss, uint16_t port,
1315 struct sockaddr_storage **addrs, int *num)
1317 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1319 if (*addrs == NULL) {
1320 *num = 0;
1321 return False;
1324 (*addrs)[*num] = *pss;
1325 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1327 *num += 1;
1328 return True;
1331 /*******************************************************************
1332 convert an ip to a name
1333 For an AD Domain, it checks the requirements of the request flags.
1334 *******************************************************************/
1336 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1337 const struct winbindd_domain *domain,
1338 struct sockaddr_storage *pss,
1339 char **name, uint32_t request_flags)
1341 struct ip_service ip_list;
1342 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1343 NTSTATUS status;
1344 const char *dc_name;
1345 fstring nbtname;
1346 #ifdef HAVE_ADS
1347 bool is_ad_domain = false;
1348 #endif
1349 ip_list.ss = *pss;
1350 ip_list.port = 0;
1352 #ifdef HAVE_ADS
1353 /* For active directory servers, try to get the ldap server name.
1354 None of these failures should be considered critical for now */
1356 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1357 is_ad_domain = true;
1358 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1359 is_ad_domain = domain->active_directory;
1362 if (is_ad_domain) {
1363 ADS_STRUCT *ads;
1364 ADS_STATUS ads_status;
1365 char addr[INET6_ADDRSTRLEN];
1367 print_sockaddr(addr, sizeof(addr), pss);
1369 ads = ads_init(domain->alt_name, domain->name, addr);
1370 ads->auth.flags |= ADS_AUTH_NO_BIND;
1371 ads->config.flags |= request_flags;
1372 ads->server.no_fallback = true;
1374 ads_status = ads_connect(ads);
1375 if (ADS_ERR_OK(ads_status)) {
1376 /* We got a cldap packet. */
1377 *name = talloc_strdup(mem_ctx,
1378 ads->config.ldap_server_name);
1379 if (*name == NULL) {
1380 return false;
1382 namecache_store(*name, 0x20, 1, &ip_list);
1384 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1386 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1387 if (ads_closest_dc(ads)) {
1388 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1390 /* We're going to use this KDC for this realm/domain.
1391 If we are using sites, then force the krb5 libs
1392 to use this KDC. */
1394 create_local_private_krb5_conf_for_domain(domain->alt_name,
1395 domain->name,
1396 sitename,
1397 pss);
1399 TALLOC_FREE(sitename);
1400 } else {
1401 /* use an off site KDC */
1402 create_local_private_krb5_conf_for_domain(domain->alt_name,
1403 domain->name,
1404 NULL,
1405 pss);
1407 winbindd_set_locator_kdc_envs(domain);
1409 /* Ensure we contact this DC also. */
1410 saf_store(domain->name, *name);
1411 saf_store(domain->alt_name, *name);
1414 ads_destroy( &ads );
1415 return True;
1418 ads_destroy( &ads );
1419 return false;
1421 #endif
1423 status = nbt_getdc(winbind_messaging_context(), 10, pss, domain->name,
1424 &domain->sid, nt_version, mem_ctx, &nt_version,
1425 &dc_name, NULL);
1426 if (NT_STATUS_IS_OK(status)) {
1427 *name = talloc_strdup(mem_ctx, dc_name);
1428 if (*name == NULL) {
1429 return false;
1431 namecache_store(*name, 0x20, 1, &ip_list);
1432 return True;
1435 /* try node status request */
1437 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1438 namecache_store(nbtname, 0x20, 1, &ip_list);
1440 if (name != NULL) {
1441 *name = talloc_strdup(mem_ctx, nbtname);
1442 if (*name == NULL) {
1443 return false;
1447 return true;
1449 return False;
1452 /*******************************************************************
1453 Retrieve a list of IP addresses for domain controllers.
1455 The array is sorted in the preferred connection order.
1457 @param[in] mem_ctx talloc memory context to allocate from
1458 @param[in] domain domain to retrieve DCs for
1459 @param[out] dcs array of dcs that will be returned
1460 @param[out] num_dcs number of dcs returned in the dcs array
1461 @return always true
1462 *******************************************************************/
1464 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1465 struct dc_name_ip **dcs, int *num_dcs,
1466 uint32_t request_flags)
1468 fstring dcname;
1469 struct sockaddr_storage ss;
1470 struct ip_service *ip_list = NULL;
1471 int iplist_size = 0;
1472 int i;
1473 bool is_our_domain;
1474 enum security_types sec = (enum security_types)lp_security();
1476 is_our_domain = strequal(domain->name, lp_workgroup());
1478 /* If not our domain, get the preferred DC, by asking our primary DC */
1479 if ( !is_our_domain
1480 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1481 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1482 num_dcs) )
1484 char addr[INET6_ADDRSTRLEN];
1485 print_sockaddr(addr, sizeof(addr), &ss);
1486 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1487 dcname, addr));
1488 return True;
1491 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1492 char *sitename = NULL;
1494 /* We need to make sure we know the local site before
1495 doing any DNS queries, as this will restrict the
1496 get_sorted_dc_list() call below to only fetching
1497 DNS records for the correct site. */
1499 /* Find any DC to get the site record.
1500 We deliberately don't care about the
1501 return here. */
1503 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1505 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1506 if (sitename) {
1508 /* Do the site-specific AD dns lookup first. */
1509 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1510 &iplist_size, True);
1512 /* Add ips to the DC array. We don't look up the name
1513 of the DC in this function, but we fill in the char*
1514 of the ip now to make the failed connection cache
1515 work */
1516 for ( i=0; i<iplist_size; i++ ) {
1517 char addr[INET6_ADDRSTRLEN];
1518 print_sockaddr(addr, sizeof(addr),
1519 &ip_list[i].ss);
1520 add_one_dc_unique(mem_ctx,
1521 domain->name,
1522 addr,
1523 &ip_list[i].ss,
1524 dcs,
1525 num_dcs);
1528 SAFE_FREE(ip_list);
1529 TALLOC_FREE(sitename);
1530 iplist_size = 0;
1533 /* Now we add DCs from the main AD DNS lookup. */
1534 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1535 &iplist_size, True);
1537 for ( i=0; i<iplist_size; i++ ) {
1538 char addr[INET6_ADDRSTRLEN];
1539 print_sockaddr(addr, sizeof(addr),
1540 &ip_list[i].ss);
1541 add_one_dc_unique(mem_ctx,
1542 domain->name,
1543 addr,
1544 &ip_list[i].ss,
1545 dcs,
1546 num_dcs);
1549 SAFE_FREE(ip_list);
1550 iplist_size = 0;
1553 /* Try standard netbios queries if no ADS and fall back to DNS queries
1554 * if alt_name is available */
1555 if (*num_dcs == 0) {
1556 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1557 false);
1558 if (iplist_size == 0) {
1559 if (domain->alt_name != NULL) {
1560 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1561 &iplist_size, true);
1565 for ( i=0; i<iplist_size; i++ ) {
1566 char addr[INET6_ADDRSTRLEN];
1567 print_sockaddr(addr, sizeof(addr),
1568 &ip_list[i].ss);
1569 add_one_dc_unique(mem_ctx,
1570 domain->name,
1571 addr,
1572 &ip_list[i].ss,
1573 dcs,
1574 num_dcs);
1577 SAFE_FREE(ip_list);
1578 iplist_size = 0;
1581 return True;
1584 /*******************************************************************
1585 Find and make a connection to a DC in the given domain.
1587 @param[in] mem_ctx talloc memory context to allocate from
1588 @param[in] domain domain to find a dc in
1589 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1590 @param[out] pss DC Internet address and port
1591 @param[out] fd fd of the open socket connected to the newly found dc
1592 @return true when a DC connection is made, false otherwise
1593 *******************************************************************/
1595 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1596 struct winbindd_domain *domain,
1597 char **dcname, struct sockaddr_storage *pss, int *fd,
1598 uint32_t request_flags)
1600 struct dc_name_ip *dcs = NULL;
1601 int num_dcs = 0;
1603 const char **dcnames = NULL;
1604 size_t num_dcnames = 0;
1606 struct sockaddr_storage *addrs = NULL;
1607 int num_addrs = 0;
1609 int i;
1610 size_t fd_index;
1612 NTSTATUS status;
1614 *fd = -1;
1616 again:
1617 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1618 return False;
1620 for (i=0; i<num_dcs; i++) {
1622 if (!add_string_to_array(mem_ctx, dcs[i].name,
1623 &dcnames, &num_dcnames)) {
1624 return False;
1626 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1627 &addrs, &num_addrs)) {
1628 return False;
1632 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1633 return False;
1635 if ((addrs == NULL) || (dcnames == NULL))
1636 return False;
1638 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1639 num_addrs, 0, 10, fd, &fd_index, NULL);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 for (i=0; i<num_dcs; i++) {
1642 char ab[INET6_ADDRSTRLEN];
1643 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1644 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1645 "domain %s address %s. Error was %s\n",
1646 domain->name, ab, nt_errstr(status) ));
1647 winbind_add_failed_connection_entry(domain,
1648 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1650 return False;
1653 *pss = addrs[fd_index];
1655 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1656 /* Ok, we've got a name for the DC */
1657 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1658 if (*dcname == NULL) {
1659 return false;
1661 return true;
1664 /* Try to figure out the name */
1665 if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1666 return True;
1669 /* We can not continue without the DC's name */
1670 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1671 NT_STATUS_UNSUCCESSFUL);
1673 /* Throw away all arrays as we're doing this again. */
1674 TALLOC_FREE(dcs);
1675 num_dcs = 0;
1677 TALLOC_FREE(dcnames);
1678 num_dcnames = 0;
1680 TALLOC_FREE(addrs);
1681 num_addrs = 0;
1683 close(*fd);
1684 *fd = -1;
1686 goto again;
1689 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1691 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1692 domain_name);
1695 static void store_current_dc_in_gencache(const char *domain_name,
1696 const char *dc_name,
1697 struct cli_state *cli)
1699 char addr[INET6_ADDRSTRLEN];
1700 char *key = NULL;
1701 char *value = NULL;
1703 if (!cli_state_is_connected(cli)) {
1704 return;
1707 print_sockaddr(addr, sizeof(addr),
1708 smbXcli_conn_remote_sockaddr(cli->conn));
1710 key = current_dc_key(talloc_tos(), domain_name);
1711 if (key == NULL) {
1712 goto done;
1715 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1716 if (value == NULL) {
1717 goto done;
1720 gencache_set(key, value, 0x7fffffff);
1721 done:
1722 TALLOC_FREE(value);
1723 TALLOC_FREE(key);
1726 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1727 const char *domain_name,
1728 char **p_dc_name, char **p_dc_ip)
1730 char *key, *p;
1731 char *value = NULL;
1732 bool ret = false;
1733 char *dc_name = NULL;
1734 char *dc_ip = NULL;
1736 key = current_dc_key(talloc_tos(), domain_name);
1737 if (key == NULL) {
1738 goto done;
1740 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1741 goto done;
1743 p = strchr(value, ' ');
1744 if (p == NULL) {
1745 goto done;
1747 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1748 if (dc_ip == NULL) {
1749 goto done;
1751 dc_name = talloc_strdup(mem_ctx, p+1);
1752 if (dc_name == NULL) {
1753 goto done;
1756 if (p_dc_ip != NULL) {
1757 *p_dc_ip = dc_ip;
1758 dc_ip = NULL;
1760 if (p_dc_name != NULL) {
1761 *p_dc_name = dc_name;
1762 dc_name = NULL;
1764 ret = true;
1765 done:
1766 TALLOC_FREE(dc_name);
1767 TALLOC_FREE(dc_ip);
1768 TALLOC_FREE(key);
1769 TALLOC_FREE(value);
1770 return ret;
1773 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1774 const struct ndr_interface_table *table,
1775 struct rpc_pipe_client **ret_pipe)
1777 struct rpc_pipe_client *cli = NULL;
1778 const struct auth_session_info *session_info;
1779 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1782 session_info = get_session_info_system();
1783 SMB_ASSERT(session_info != NULL);
1785 /* create a connection to the specified pipe */
1786 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1787 status = rpc_pipe_open_interface(mem_ctx,
1788 table,
1789 session_info,
1790 NULL,
1791 NULL,
1792 winbind_messaging_context(),
1793 &cli);
1794 } else {
1795 status = rpc_pipe_open_internal(mem_ctx,
1796 table,
1797 session_info,
1798 NULL,
1799 NULL,
1800 winbind_messaging_context(),
1801 &cli);
1803 if (!NT_STATUS_IS_OK(status)) {
1804 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1805 table->name, nt_errstr(status)));
1806 return status;
1809 if (ret_pipe) {
1810 *ret_pipe = cli;
1813 return NT_STATUS_OK;
1816 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1817 struct winbindd_cm_conn *new_conn,
1818 bool need_rw_dc)
1820 TALLOC_CTX *mem_ctx;
1821 NTSTATUS result;
1822 char *saf_servername;
1823 int retries;
1824 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1826 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1827 set_domain_offline(domain);
1828 return NT_STATUS_NO_MEMORY;
1831 saf_servername = saf_fetch(mem_ctx, domain->name );
1833 /* we have to check the server affinity cache here since
1834 later we select a DC based on response time and not preference */
1836 /* Check the negative connection cache
1837 before talking to it. It going down may have
1838 triggered the reconnection. */
1840 if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1841 struct sockaddr_storage ss;
1842 char *dcname = NULL;
1843 bool resolved = true;
1845 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1846 saf_servername, domain->name));
1848 /* convert an ip address to a name */
1849 if (is_ipaddress(saf_servername)) {
1850 if (!interpret_string_addr(&ss, saf_servername,
1851 AI_NUMERICHOST)) {
1852 TALLOC_FREE(mem_ctx);
1853 return NT_STATUS_UNSUCCESSFUL;
1855 } else {
1856 if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1857 resolved = false;
1861 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1862 domain->dcname = talloc_strdup(domain,
1863 dcname);
1864 if (domain->dcname == NULL) {
1865 TALLOC_FREE(mem_ctx);
1866 return NT_STATUS_NO_MEMORY;
1869 domain->dcaddr = ss;
1870 } else {
1871 winbind_add_failed_connection_entry(domain, saf_servername,
1872 NT_STATUS_UNSUCCESSFUL);
1876 for (retries = 0; retries < 3; retries++) {
1877 int fd = -1;
1878 bool retry = False;
1879 char *dcname = NULL;
1881 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1883 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1884 domain->dcname ? domain->dcname : "", domain->name));
1886 if (domain->dcname != NULL &&
1887 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1888 domain->dcname)))
1890 NTSTATUS status;
1892 status = smbsock_connect(&domain->dcaddr, 0,
1893 NULL, -1, NULL, -1,
1894 &fd, NULL, 10);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 fd = -1;
1900 if ((fd == -1) &&
1901 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1903 /* This is the one place where we will
1904 set the global winbindd offline state
1905 to true, if a "WINBINDD_OFFLINE" entry
1906 is found in the winbindd cache. */
1907 set_global_winbindd_state_offline();
1908 break;
1910 if (dcname != NULL) {
1911 talloc_free(domain->dcname);
1913 domain->dcname = talloc_move(domain, &dcname);
1914 if (domain->dcname == NULL) {
1915 result = NT_STATUS_NO_MEMORY;
1916 break;
1920 new_conn->cli = NULL;
1922 result = cm_prepare_connection(domain, fd, domain->dcname,
1923 &new_conn->cli, &retry);
1924 if (!NT_STATUS_IS_OK(result)) {
1925 /* Don't leak the smb connection socket */
1926 close(fd);
1929 if (!retry)
1930 break;
1933 if (NT_STATUS_IS_OK(result)) {
1934 bool seal_pipes = true;
1936 winbindd_set_locator_kdc_envs(domain);
1938 if (domain->online == False) {
1939 /* We're changing state from offline to online. */
1940 set_global_winbindd_state_online();
1942 set_domain_online(domain);
1945 * Much as I hate global state, this seems to be the point
1946 * where we can be certain that we have a proper connection to
1947 * a DC. wbinfo --dc-info needs that information, store it in
1948 * gencache with a looong timeout. This will need revisiting
1949 * once we start to connect to multiple DCs, wbcDcInfo is
1950 * already prepared for that.
1952 store_current_dc_in_gencache(domain->name, domain->dcname,
1953 new_conn->cli);
1955 seal_pipes = lp_winbind_sealed_pipes();
1956 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1957 domain->name,
1958 seal_pipes);
1960 if (seal_pipes) {
1961 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1962 } else {
1963 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1965 } else {
1966 /* Ensure we setup the retry handler. */
1967 set_domain_offline(domain);
1970 talloc_destroy(mem_ctx);
1971 return result;
1974 /* Close down all open pipes on a connection. */
1976 void invalidate_cm_connection(struct winbindd_domain *domain)
1978 NTSTATUS result;
1979 struct winbindd_cm_conn *conn = &domain->conn;
1981 /* We're closing down a possibly dead
1982 connection. Don't have impossibly long (10s) timeouts. */
1984 if (conn->cli) {
1985 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1988 if (conn->samr_pipe != NULL) {
1989 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1990 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1991 talloc_tos(),
1992 &conn->sam_connect_handle,
1993 &result);
1995 TALLOC_FREE(conn->samr_pipe);
1996 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1997 if (conn->cli) {
1998 cli_set_timeout(conn->cli, 500);
2002 if (conn->lsa_pipe != NULL) {
2003 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2004 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2005 talloc_tos(),
2006 &conn->lsa_policy,
2007 &result);
2009 TALLOC_FREE(conn->lsa_pipe);
2010 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2011 if (conn->cli) {
2012 cli_set_timeout(conn->cli, 500);
2016 if (conn->lsa_pipe_tcp != NULL) {
2017 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2018 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2019 talloc_tos(),
2020 &conn->lsa_policy,
2021 &result);
2023 TALLOC_FREE(conn->lsa_pipe_tcp);
2024 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2025 if (conn->cli) {
2026 cli_set_timeout(conn->cli, 500);
2030 if (conn->netlogon_pipe != NULL) {
2031 TALLOC_FREE(conn->netlogon_pipe);
2032 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2033 if (conn->cli) {
2034 cli_set_timeout(conn->cli, 500);
2038 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2039 conn->netlogon_force_reauth = false;
2040 conn->netlogon_flags = 0;
2041 TALLOC_FREE(conn->netlogon_creds_ctx);
2043 if (conn->cli) {
2044 cli_shutdown(conn->cli);
2047 conn->cli = NULL;
2050 void close_conns_after_fork(void)
2052 struct winbindd_domain *domain;
2053 struct winbindd_cli_state *cli_state;
2055 for (domain = domain_list(); domain; domain = domain->next) {
2057 * first close the low level SMB TCP connection
2058 * so that we don't generate any SMBclose
2059 * requests in invalidate_cm_connection()
2061 if (cli_state_is_connected(domain->conn.cli)) {
2062 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2065 invalidate_cm_connection(domain);
2068 for (cli_state = winbindd_client_list();
2069 cli_state != NULL;
2070 cli_state = cli_state->next) {
2071 if (cli_state->sock >= 0) {
2072 close(cli_state->sock);
2073 cli_state->sock = -1;
2078 static bool connection_ok(struct winbindd_domain *domain)
2080 bool ok;
2082 ok = cli_state_is_connected(domain->conn.cli);
2083 if (!ok) {
2084 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2085 domain->dcname, domain->name));
2086 return False;
2089 if (domain->online == False) {
2090 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2091 return False;
2094 return True;
2097 /* Initialize a new connection up to the RPC BIND.
2098 Bypass online status check so always does network calls. */
2100 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2102 NTSTATUS result;
2103 bool skip_connection = domain->internal;
2104 if (need_rw_dc && domain->rodc) {
2105 skip_connection = false;
2108 /* Internal connections never use the network. */
2109 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2110 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2113 /* Still ask the internal LSA and SAMR server about the local domain */
2114 if (skip_connection || connection_ok(domain)) {
2115 if (!domain->initialized) {
2116 set_dc_type_and_flags(domain);
2118 return NT_STATUS_OK;
2121 invalidate_cm_connection(domain);
2123 if (!domain->primary && !domain->initialized) {
2125 * Before we connect to a trust, work out if it is an
2126 * AD domain by asking our own domain.
2128 set_dc_type_and_flags_trustinfo(domain);
2131 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2133 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2134 set_dc_type_and_flags(domain);
2137 return result;
2140 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2142 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2143 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2146 if (domain->initialized && !domain->online) {
2147 /* We check for online status elsewhere. */
2148 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2151 return init_dc_connection_network(domain, need_rw_dc);
2154 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2156 NTSTATUS status;
2158 status = init_dc_connection(domain, need_rw_dc);
2159 if (!NT_STATUS_IS_OK(status)) {
2160 return status;
2163 if (!domain->internal && domain->conn.cli == NULL) {
2164 /* happens for trusted domains without inbound trust */
2165 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2168 return NT_STATUS_OK;
2171 /******************************************************************************
2172 Set the trust flags (direction and forest location) for a domain
2173 ******************************************************************************/
2175 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2177 struct winbindd_domain *our_domain;
2178 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2179 WERROR werr;
2180 struct netr_DomainTrustList trusts;
2181 int i;
2182 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2183 NETR_TRUST_FLAG_OUTBOUND |
2184 NETR_TRUST_FLAG_INBOUND);
2185 struct rpc_pipe_client *cli;
2186 TALLOC_CTX *mem_ctx = NULL;
2187 struct dcerpc_binding_handle *b;
2189 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2191 /* Our primary domain doesn't need to worry about trust flags.
2192 Force it to go through the network setup */
2193 if ( domain->primary ) {
2194 return False;
2197 mem_ctx = talloc_stackframe();
2198 our_domain = find_our_domain();
2199 if (our_domain->internal) {
2200 result = init_dc_connection(our_domain, false);
2201 if (!NT_STATUS_IS_OK(result)) {
2202 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2203 "Not able to make a connection to our domain: %s\n",
2204 nt_errstr(result)));
2205 TALLOC_FREE(mem_ctx);
2206 return false;
2210 /* This won't work unless our domain is AD */
2211 if ( !our_domain->active_directory ) {
2212 TALLOC_FREE(mem_ctx);
2213 return False;
2216 if (our_domain->internal) {
2217 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2218 } else if (!connection_ok(our_domain)) {
2219 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2220 "No connection to our domain!\n"));
2221 TALLOC_FREE(mem_ctx);
2222 return False;
2223 } else {
2224 result = cm_connect_netlogon(our_domain, &cli);
2227 if (!NT_STATUS_IS_OK(result)) {
2228 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2229 "a connection to %s for PIPE_NETLOGON (%s)\n",
2230 domain->name, nt_errstr(result)));
2231 TALLOC_FREE(mem_ctx);
2232 return False;
2234 b = cli->binding_handle;
2236 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2237 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2238 cli->desthost,
2239 flags,
2240 &trusts,
2241 &werr);
2242 if (!NT_STATUS_IS_OK(result)) {
2243 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2244 "failed to query trusted domain list: %s\n",
2245 nt_errstr(result)));
2246 TALLOC_FREE(mem_ctx);
2247 return false;
2249 if (!W_ERROR_IS_OK(werr)) {
2250 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2251 "failed to query trusted domain list: %s\n",
2252 win_errstr(werr)));
2253 TALLOC_FREE(mem_ctx);
2254 return false;
2257 /* Now find the domain name and get the flags */
2259 for ( i=0; i<trusts.count; i++ ) {
2260 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2261 domain->domain_flags = trusts.array[i].trust_flags;
2262 domain->domain_type = trusts.array[i].trust_type;
2263 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2265 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2266 domain->active_directory = True;
2268 /* This flag is only set if the domain is *our*
2269 primary domain and the primary domain is in
2270 native mode */
2272 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2274 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2275 "native mode.\n", domain->name,
2276 domain->native_mode ? "" : "NOT "));
2278 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2279 "running active directory.\n", domain->name,
2280 domain->active_directory ? "" : "NOT "));
2282 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2284 domain->initialized = True;
2286 break;
2290 TALLOC_FREE(mem_ctx);
2292 return domain->initialized;
2295 /******************************************************************************
2296 We can 'sense' certain things about the DC by it's replies to certain
2297 questions.
2299 This tells us if this particular remote server is Active Directory, and if it
2300 is native mode.
2301 ******************************************************************************/
2303 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2305 NTSTATUS status, result;
2306 WERROR werr;
2307 TALLOC_CTX *mem_ctx = NULL;
2308 struct rpc_pipe_client *cli = NULL;
2309 struct policy_handle pol;
2310 union dssetup_DsRoleInfo info;
2311 union lsa_PolicyInformation *lsa_info = NULL;
2313 if (!domain->internal && !connection_ok(domain)) {
2314 return;
2317 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2318 domain->name);
2319 if (!mem_ctx) {
2320 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2321 return;
2324 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2326 if (domain->internal) {
2327 status = wb_open_internal_pipe(mem_ctx,
2328 &ndr_table_dssetup,
2329 &cli);
2330 } else {
2331 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2332 &ndr_table_dssetup,
2333 &cli);
2336 if (!NT_STATUS_IS_OK(status)) {
2337 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2338 "PI_DSSETUP on domain %s: (%s)\n",
2339 domain->name, nt_errstr(status)));
2341 /* if this is just a non-AD domain we need to continue
2342 * identifying so that we can in the end return with
2343 * domain->initialized = True - gd */
2345 goto no_dssetup;
2348 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2349 DS_ROLE_BASIC_INFORMATION,
2350 &info,
2351 &werr);
2352 TALLOC_FREE(cli);
2354 if (NT_STATUS_IS_OK(status)) {
2355 result = werror_to_ntstatus(werr);
2357 if (!NT_STATUS_IS_OK(status)) {
2358 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2359 "on domain %s failed: (%s)\n",
2360 domain->name, nt_errstr(status)));
2362 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2363 * every opcode on the DSSETUP pipe, continue with
2364 * no_dssetup mode here as well to get domain->initialized
2365 * set - gd */
2367 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2368 goto no_dssetup;
2371 TALLOC_FREE(mem_ctx);
2372 return;
2375 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2376 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2377 domain->native_mode = True;
2378 } else {
2379 domain->native_mode = False;
2382 no_dssetup:
2383 if (domain->internal) {
2384 status = wb_open_internal_pipe(mem_ctx,
2385 &ndr_table_lsarpc,
2386 &cli);
2387 } else {
2388 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2389 &ndr_table_lsarpc, &cli);
2391 if (!NT_STATUS_IS_OK(status)) {
2392 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2393 "PI_LSARPC on domain %s: (%s)\n",
2394 domain->name, nt_errstr(status)));
2395 TALLOC_FREE(cli);
2396 TALLOC_FREE(mem_ctx);
2397 return;
2400 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2401 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2403 if (NT_STATUS_IS_OK(status)) {
2404 /* This particular query is exactly what Win2k clients use
2405 to determine that the DC is active directory */
2406 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2407 &pol,
2408 LSA_POLICY_INFO_DNS,
2409 &lsa_info,
2410 &result);
2413 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2414 domain->active_directory = True;
2416 if (lsa_info->dns.name.string) {
2417 if (!strequal(domain->name, lsa_info->dns.name.string))
2419 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2420 "for domain %s claimed it was a DC "
2421 "for domain %s, refusing to "
2422 "initialize\n",
2423 domain->name,
2424 lsa_info->dns.name.string));
2425 TALLOC_FREE(cli);
2426 TALLOC_FREE(mem_ctx);
2427 return;
2429 talloc_free(domain->name);
2430 domain->name = talloc_strdup(domain,
2431 lsa_info->dns.name.string);
2432 if (domain->name == NULL) {
2433 goto done;
2437 if (lsa_info->dns.dns_domain.string) {
2438 if (domain->alt_name != NULL &&
2439 !strequal(domain->alt_name,
2440 lsa_info->dns.dns_domain.string))
2442 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2443 "for domain %s (%s) claimed it was "
2444 "a DC for domain %s, refusing to "
2445 "initialize\n",
2446 domain->alt_name, domain->name,
2447 lsa_info->dns.dns_domain.string));
2448 TALLOC_FREE(cli);
2449 TALLOC_FREE(mem_ctx);
2450 return;
2452 talloc_free(domain->alt_name);
2453 domain->alt_name =
2454 talloc_strdup(domain,
2455 lsa_info->dns.dns_domain.string);
2456 if (domain->alt_name == NULL) {
2457 goto done;
2461 /* See if we can set some domain trust flags about
2462 ourself */
2464 if (lsa_info->dns.dns_forest.string) {
2465 talloc_free(domain->forest_name);
2466 domain->forest_name =
2467 talloc_strdup(domain,
2468 lsa_info->dns.dns_forest.string);
2469 if (domain->forest_name == NULL) {
2470 goto done;
2473 if (strequal(domain->forest_name, domain->alt_name)) {
2474 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2478 if (lsa_info->dns.sid) {
2479 if (!is_null_sid(&domain->sid) &&
2480 !dom_sid_equal(&domain->sid,
2481 lsa_info->dns.sid))
2483 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2484 "for domain %s (%s) claimed it was "
2485 "a DC for domain %s, refusing to "
2486 "initialize\n",
2487 dom_sid_string(talloc_tos(),
2488 &domain->sid),
2489 domain->name,
2490 dom_sid_string(talloc_tos(),
2491 lsa_info->dns.sid)));
2492 TALLOC_FREE(cli);
2493 TALLOC_FREE(mem_ctx);
2494 return;
2496 sid_copy(&domain->sid, lsa_info->dns.sid);
2498 } else {
2499 domain->active_directory = False;
2501 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2502 SEC_FLAG_MAXIMUM_ALLOWED,
2503 &pol);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 goto done;
2509 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2510 &pol,
2511 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2512 &lsa_info,
2513 &result);
2514 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2516 if (lsa_info->account_domain.name.string) {
2517 if (!strequal(domain->name,
2518 lsa_info->account_domain.name.string))
2520 DEBUG(1,
2521 ("set_dc_type_and_flags_connect: "
2522 "DC for domain %s claimed it was"
2523 " a DC for domain %s, refusing "
2524 "to initialize\n", domain->name,
2525 lsa_info->
2526 account_domain.name.string));
2527 TALLOC_FREE(cli);
2528 TALLOC_FREE(mem_ctx);
2529 return;
2531 talloc_free(domain->name);
2532 domain->name =
2533 talloc_strdup(domain,
2534 lsa_info->account_domain.name.string);
2537 if (lsa_info->account_domain.sid) {
2538 if (!is_null_sid(&domain->sid) &&
2539 !dom_sid_equal(&domain->sid,
2540 lsa_info->account_domain.sid))
2542 DEBUG(1,
2543 ("set_dc_type_and_flags_connect: "
2544 "DC for domain %s (%s) claimed "
2545 "it was a DC for domain %s, "
2546 "refusing to initialize\n",
2547 dom_sid_string(talloc_tos(),
2548 &domain->sid),
2549 domain->name,
2550 dom_sid_string(talloc_tos(),
2551 lsa_info->account_domain.sid)));
2552 TALLOC_FREE(cli);
2553 TALLOC_FREE(mem_ctx);
2554 return;
2556 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2560 done:
2562 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2563 domain->name, domain->native_mode ? "" : "NOT "));
2565 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2566 domain->name, domain->active_directory ? "" : "NOT "));
2568 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2570 TALLOC_FREE(cli);
2572 TALLOC_FREE(mem_ctx);
2574 domain->initialized = True;
2577 /**********************************************************************
2578 Set the domain_flags (trust attributes, domain operating modes, etc...
2579 ***********************************************************************/
2581 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2583 /* we always have to contact our primary domain */
2585 if ( domain->primary || domain->internal) {
2586 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2587 "primary or internal domain\n"));
2588 set_dc_type_and_flags_connect( domain );
2589 return;
2592 /* Use our DC to get the information if possible */
2594 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2595 /* Otherwise, fallback to contacting the
2596 domain directly */
2597 set_dc_type_and_flags_connect( domain );
2600 return;
2605 /**********************************************************************
2606 ***********************************************************************/
2608 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2609 struct netlogon_creds_cli_context **ppdc)
2611 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2612 struct rpc_pipe_client *netlogon_pipe;
2614 *ppdc = NULL;
2616 if ((!IS_DC) && (!domain->primary)) {
2617 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2620 if (domain->conn.netlogon_creds_ctx != NULL) {
2621 if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2622 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2624 *ppdc = domain->conn.netlogon_creds_ctx;
2625 return NT_STATUS_OK;
2628 result = cm_connect_netlogon(domain, &netlogon_pipe);
2629 if (!NT_STATUS_IS_OK(result)) {
2630 return result;
2633 if (domain->conn.netlogon_creds_ctx == NULL) {
2634 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2637 if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2638 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2641 *ppdc = domain->conn.netlogon_creds_ctx;
2642 return NT_STATUS_OK;
2645 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2646 bool need_rw_dc,
2647 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2649 struct winbindd_cm_conn *conn;
2650 NTSTATUS status, result;
2651 struct netlogon_creds_cli_context *p_creds;
2652 struct cli_credentials *creds = NULL;
2653 bool retry = false; /* allow one retry attempt for expired session */
2655 if (sid_check_is_our_sam(&domain->sid)) {
2656 if (domain->rodc == false || need_rw_dc == false) {
2657 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2661 retry:
2662 status = init_dc_connection_rpc(domain, need_rw_dc);
2663 if (!NT_STATUS_IS_OK(status)) {
2664 return status;
2667 conn = &domain->conn;
2669 if (rpccli_is_connected(conn->samr_pipe)) {
2670 goto done;
2673 TALLOC_FREE(conn->samr_pipe);
2676 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2677 * sign and sealed pipe using the machine account password by
2678 * preference. If we can't - try schannel, if that fails, try
2679 * anonymous.
2682 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2683 if (!NT_STATUS_IS_OK(result)) {
2684 DEBUG(10, ("cm_connect_sam: No user available for "
2685 "domain %s, trying schannel\n", domain->name));
2686 goto schannel;
2689 if (cli_credentials_is_anonymous(creds)) {
2690 goto anonymous;
2694 * We have an authenticated connection. Use a SPNEGO
2695 * authenticated SAMR pipe with sign & seal.
2697 status = cli_rpc_pipe_open_with_creds(conn->cli,
2698 &ndr_table_samr,
2699 NCACN_NP,
2700 DCERPC_AUTH_TYPE_SPNEGO,
2701 conn->auth_level,
2702 smbXcli_conn_remote_name(conn->cli->conn),
2703 creds,
2704 &conn->samr_pipe);
2706 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2707 && !retry) {
2708 invalidate_cm_connection(domain);
2709 retry = true;
2710 goto retry;
2713 if (!NT_STATUS_IS_OK(status)) {
2714 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2715 "pipe for domain %s using NTLMSSP "
2716 "authenticated pipe: user %s. Error was "
2717 "%s\n", domain->name,
2718 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2719 nt_errstr(status)));
2720 goto schannel;
2723 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2724 "domain %s using NTLMSSP authenticated "
2725 "pipe: user %s\n", domain->name,
2726 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2728 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2729 conn->samr_pipe->desthost,
2730 SEC_FLAG_MAXIMUM_ALLOWED,
2731 &conn->sam_connect_handle,
2732 &result);
2734 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2735 invalidate_cm_connection(domain);
2736 TALLOC_FREE(conn->samr_pipe);
2737 retry = true;
2738 goto retry;
2741 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2742 goto open_domain;
2744 if (NT_STATUS_IS_OK(status)) {
2745 status = result;
2748 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2749 "failed for domain %s, error was %s. Trying schannel\n",
2750 domain->name, nt_errstr(status) ));
2751 TALLOC_FREE(conn->samr_pipe);
2753 schannel:
2755 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2757 status = cm_get_schannel_creds(domain, &p_creds);
2758 if (!NT_STATUS_IS_OK(status)) {
2759 /* If this call fails - conn->cli can now be NULL ! */
2760 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2761 "for domain %s (error %s), trying anon\n",
2762 domain->name,
2763 nt_errstr(status) ));
2764 goto anonymous;
2766 TALLOC_FREE(creds);
2767 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
2768 if (!NT_STATUS_IS_OK(result)) {
2769 DEBUG(10, ("cm_connect_sam: No user available for "
2770 "domain %s (error %s), trying anon\n", domain->name,
2771 nt_errstr(result)));
2772 goto anonymous;
2774 status = cli_rpc_pipe_open_schannel_with_creds(
2775 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2776 &conn->samr_pipe);
2778 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2779 && !retry) {
2780 invalidate_cm_connection(domain);
2781 retry = true;
2782 goto retry;
2785 if (!NT_STATUS_IS_OK(status)) {
2786 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2787 "domain %s using schannel. Error was %s\n",
2788 domain->name, nt_errstr(status) ));
2789 goto anonymous;
2791 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2792 "schannel.\n", domain->name ));
2794 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2795 conn->samr_pipe->desthost,
2796 SEC_FLAG_MAXIMUM_ALLOWED,
2797 &conn->sam_connect_handle,
2798 &result);
2800 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2801 invalidate_cm_connection(domain);
2802 TALLOC_FREE(conn->samr_pipe);
2803 retry = true;
2804 goto retry;
2807 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2808 goto open_domain;
2810 if (NT_STATUS_IS_OK(status)) {
2811 status = result;
2813 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2814 "for domain %s, error was %s. Trying anonymous\n",
2815 domain->name, nt_errstr(status) ));
2816 TALLOC_FREE(conn->samr_pipe);
2818 anonymous:
2820 /* Finally fall back to anonymous. */
2821 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2822 status = NT_STATUS_DOWNGRADE_DETECTED;
2823 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2824 "without connection level security, "
2825 "must set 'winbind sealed pipes = false' and "
2826 "'require strong key = false' to proceed: %s\n",
2827 domain->name, nt_errstr(status)));
2828 goto done;
2830 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2831 &conn->samr_pipe);
2833 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2834 && !retry) {
2835 invalidate_cm_connection(domain);
2836 retry = true;
2837 goto retry;
2840 if (!NT_STATUS_IS_OK(status)) {
2841 goto done;
2844 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2845 conn->samr_pipe->desthost,
2846 SEC_FLAG_MAXIMUM_ALLOWED,
2847 &conn->sam_connect_handle,
2848 &result);
2850 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2851 invalidate_cm_connection(domain);
2852 TALLOC_FREE(conn->samr_pipe);
2853 retry = true;
2854 goto retry;
2857 if (!NT_STATUS_IS_OK(status)) {
2858 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2859 "for domain %s Error was %s\n",
2860 domain->name, nt_errstr(status) ));
2861 goto done;
2863 if (!NT_STATUS_IS_OK(result)) {
2864 status = result;
2865 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2866 "for domain %s Error was %s\n",
2867 domain->name, nt_errstr(result)));
2868 goto done;
2871 open_domain:
2872 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2873 mem_ctx,
2874 &conn->sam_connect_handle,
2875 SEC_FLAG_MAXIMUM_ALLOWED,
2876 &domain->sid,
2877 &conn->sam_domain_handle,
2878 &result);
2879 if (!NT_STATUS_IS_OK(status)) {
2880 goto done;
2883 status = result;
2884 done:
2886 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2888 * if we got access denied, we might just have no access rights
2889 * to talk to the remote samr server server (e.g. when we are a
2890 * PDC and we are connecting a w2k8 pdc via an interdomain
2891 * trust). In that case do not invalidate the whole connection
2892 * stack
2894 TALLOC_FREE(conn->samr_pipe);
2895 ZERO_STRUCT(conn->sam_domain_handle);
2896 return status;
2897 } else if (!NT_STATUS_IS_OK(status)) {
2898 invalidate_cm_connection(domain);
2899 return status;
2902 *cli = conn->samr_pipe;
2903 *sam_handle = conn->sam_domain_handle;
2904 return status;
2907 /**********************************************************************
2908 open an schanneld ncacn_ip_tcp connection to LSA
2909 ***********************************************************************/
2911 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2912 TALLOC_CTX *mem_ctx,
2913 struct rpc_pipe_client **cli)
2915 struct winbindd_cm_conn *conn;
2916 struct netlogon_creds_cli_context *p_creds = NULL;
2917 struct cli_credentials *creds = NULL;
2918 NTSTATUS status;
2920 DEBUG(10,("cm_connect_lsa_tcp\n"));
2922 status = init_dc_connection_rpc(domain, false);
2923 if (!NT_STATUS_IS_OK(status)) {
2924 return status;
2927 conn = &domain->conn;
2930 * rpccli_is_connected handles more error cases
2932 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2933 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2934 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2935 goto done;
2938 TALLOC_FREE(conn->lsa_pipe_tcp);
2940 status = cm_get_schannel_creds(domain, &p_creds);
2941 if (!NT_STATUS_IS_OK(status)) {
2942 goto done;
2945 status = get_trust_credentials(domain, talloc_tos(), true, &creds);
2946 if (!NT_STATUS_IS_OK(status)) {
2947 goto done;
2950 status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
2951 &ndr_table_lsarpc,
2952 NCACN_IP_TCP,
2953 p_creds,
2954 &conn->lsa_pipe_tcp);
2955 if (!NT_STATUS_IS_OK(status)) {
2956 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2957 nt_errstr(status)));
2958 goto done;
2961 done:
2962 if (!NT_STATUS_IS_OK(status)) {
2963 TALLOC_FREE(conn->lsa_pipe_tcp);
2964 return status;
2967 *cli = conn->lsa_pipe_tcp;
2969 return status;
2972 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2973 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2975 struct winbindd_cm_conn *conn;
2976 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2977 struct netlogon_creds_cli_context *p_creds;
2978 struct cli_credentials *creds = NULL;
2979 bool retry = false; /* allow one retry attempt for expired session */
2981 retry:
2982 result = init_dc_connection_rpc(domain, false);
2983 if (!NT_STATUS_IS_OK(result))
2984 return result;
2986 conn = &domain->conn;
2988 if (rpccli_is_connected(conn->lsa_pipe)) {
2989 goto done;
2992 TALLOC_FREE(conn->lsa_pipe);
2994 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2995 if (!NT_STATUS_IS_OK(result)) {
2996 DEBUG(10, ("cm_connect_lsa: No user available for "
2997 "domain %s, trying schannel\n", domain->name));
2998 goto schannel;
3001 if (cli_credentials_is_anonymous(creds)) {
3002 goto anonymous;
3006 * We have an authenticated connection. Use a SPNEGO
3007 * authenticated LSA pipe with sign & seal.
3009 result = cli_rpc_pipe_open_with_creds
3010 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
3011 DCERPC_AUTH_TYPE_SPNEGO,
3012 conn->auth_level,
3013 smbXcli_conn_remote_name(conn->cli->conn),
3014 creds,
3015 &conn->lsa_pipe);
3017 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3018 && !retry) {
3019 invalidate_cm_connection(domain);
3020 retry = true;
3021 goto retry;
3024 if (!NT_STATUS_IS_OK(result)) {
3025 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3026 "domain %s using NTLMSSP authenticated pipe: user "
3027 "%s. Error was %s. Trying schannel.\n",
3028 domain->name,
3029 cli_credentials_get_unparsed_name(creds, talloc_tos()),
3030 nt_errstr(result)));
3031 goto schannel;
3034 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3035 "NTLMSSP authenticated pipe: user %s\n",
3036 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3038 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3039 SEC_FLAG_MAXIMUM_ALLOWED,
3040 &conn->lsa_policy);
3041 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3042 invalidate_cm_connection(domain);
3043 TALLOC_FREE(conn->lsa_pipe);
3044 retry = true;
3045 goto retry;
3048 if (NT_STATUS_IS_OK(result)) {
3049 goto done;
3052 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3053 "schannel\n"));
3055 TALLOC_FREE(conn->lsa_pipe);
3057 schannel:
3059 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3061 result = cm_get_schannel_creds(domain, &p_creds);
3062 if (!NT_STATUS_IS_OK(result)) {
3063 /* If this call fails - conn->cli can now be NULL ! */
3064 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3065 "for domain %s (error %s), trying anon\n",
3066 domain->name,
3067 nt_errstr(result) ));
3068 goto anonymous;
3071 TALLOC_FREE(creds);
3072 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3073 if (!NT_STATUS_IS_OK(result)) {
3074 DEBUG(10, ("cm_connect_lsa: No user available for "
3075 "domain %s (error %s), trying anon\n", domain->name,
3076 nt_errstr(result)));
3077 goto anonymous;
3079 result = cli_rpc_pipe_open_schannel_with_creds(
3080 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3081 &conn->lsa_pipe);
3083 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3084 && !retry) {
3085 invalidate_cm_connection(domain);
3086 retry = true;
3087 goto retry;
3090 if (!NT_STATUS_IS_OK(result)) {
3091 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3092 "domain %s using schannel. Error was %s\n",
3093 domain->name, nt_errstr(result) ));
3094 goto anonymous;
3096 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3097 "schannel.\n", domain->name ));
3099 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3100 SEC_FLAG_MAXIMUM_ALLOWED,
3101 &conn->lsa_policy);
3103 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3104 invalidate_cm_connection(domain);
3105 TALLOC_FREE(conn->lsa_pipe);
3106 retry = true;
3107 goto retry;
3110 if (NT_STATUS_IS_OK(result)) {
3111 goto done;
3114 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3115 "anonymous\n"));
3117 TALLOC_FREE(conn->lsa_pipe);
3119 anonymous:
3121 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3122 result = NT_STATUS_DOWNGRADE_DETECTED;
3123 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3124 "without connection level security, "
3125 "must set 'winbind sealed pipes = false' and "
3126 "'require strong key = false' to proceed: %s\n",
3127 domain->name, nt_errstr(result)));
3128 goto done;
3131 result = cli_rpc_pipe_open_noauth(conn->cli,
3132 &ndr_table_lsarpc,
3133 &conn->lsa_pipe);
3135 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3136 && !retry) {
3137 invalidate_cm_connection(domain);
3138 retry = true;
3139 goto retry;
3142 if (!NT_STATUS_IS_OK(result)) {
3143 goto done;
3146 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3147 SEC_FLAG_MAXIMUM_ALLOWED,
3148 &conn->lsa_policy);
3150 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3151 invalidate_cm_connection(domain);
3152 TALLOC_FREE(conn->lsa_pipe);
3153 retry = true;
3154 goto retry;
3157 done:
3158 if (!NT_STATUS_IS_OK(result)) {
3159 invalidate_cm_connection(domain);
3160 return result;
3163 *cli = conn->lsa_pipe;
3164 *lsa_policy = conn->lsa_policy;
3165 return result;
3168 /****************************************************************************
3169 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3170 ****************************************************************************/
3172 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3173 TALLOC_CTX *mem_ctx,
3174 struct rpc_pipe_client **cli,
3175 struct policy_handle *lsa_policy)
3177 NTSTATUS status;
3179 if (domain->can_do_ncacn_ip_tcp) {
3180 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3181 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3182 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3183 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3184 invalidate_cm_connection(domain);
3185 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3187 if (NT_STATUS_IS_OK(status)) {
3188 return status;
3192 * we tried twice to connect via ncan_ip_tcp and schannel and
3193 * failed - maybe it is a trusted domain we can't connect to ?
3194 * do not try tcp next time - gd
3196 * This also prevents NETLOGON over TCP
3198 domain->can_do_ncacn_ip_tcp = false;
3201 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3203 return status;
3206 /****************************************************************************
3207 Open the netlogon pipe to this DC.
3208 ****************************************************************************/
3210 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3211 enum dcerpc_transport_t transport,
3212 struct rpc_pipe_client **cli)
3214 struct messaging_context *msg_ctx = winbind_messaging_context();
3215 struct winbindd_cm_conn *conn;
3216 NTSTATUS result;
3217 enum netr_SchannelType sec_chan_type;
3218 struct netlogon_creds_CredentialState *netlogon_creds = NULL;
3219 struct cli_credentials *creds = NULL;
3221 *cli = NULL;
3223 result = init_dc_connection_rpc(domain, domain->rodc);
3224 if (!NT_STATUS_IS_OK(result)) {
3225 return result;
3228 conn = &domain->conn;
3230 if (rpccli_is_connected(conn->netlogon_pipe)) {
3231 *cli = conn->netlogon_pipe;
3232 return NT_STATUS_OK;
3235 TALLOC_FREE(conn->netlogon_pipe);
3236 conn->netlogon_flags = 0;
3237 TALLOC_FREE(conn->netlogon_creds_ctx);
3239 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3240 if (!NT_STATUS_IS_OK(result)) {
3241 DBG_DEBUG("No user available for domain %s when trying "
3242 "schannel\n", domain->name);
3243 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3246 if (cli_credentials_is_anonymous(creds)) {
3247 DEBUG(1, ("get_trust_credential only gave anonymous for %s, unable to make get NETLOGON credentials\n",
3248 domain->name));
3249 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3252 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3253 if (sec_chan_type == SEC_CHAN_NULL) {
3254 if (transport == NCACN_IP_TCP) {
3255 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3256 " deny NCACN_IP_TCP and let the caller fallback to NCACN_NP.\n",
3257 domain->name);
3258 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3261 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3262 "fallback to noauth on NCACN_NP.\n",
3263 domain->name);
3265 result = cli_rpc_pipe_open_noauth_transport(conn->cli,
3266 transport,
3267 &ndr_table_netlogon,
3268 &conn->netlogon_pipe);
3269 if (!NT_STATUS_IS_OK(result)) {
3270 invalidate_cm_connection(domain);
3271 return result;
3274 *cli = conn->netlogon_pipe;
3275 return NT_STATUS_OK;
3278 result = rpccli_create_netlogon_creds_ctx(creds,
3279 domain->dcname,
3280 msg_ctx,
3281 domain,
3282 &conn->netlogon_creds_ctx);
3283 if (!NT_STATUS_IS_OK(result)) {
3284 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3285 "unable to create NETLOGON credentials: %s\n",
3286 domain->name, nt_errstr(result)));
3287 return result;
3290 result = rpccli_setup_netlogon_creds(conn->cli, transport,
3291 conn->netlogon_creds_ctx,
3292 conn->netlogon_force_reauth,
3293 creds);
3294 conn->netlogon_force_reauth = false;
3295 if (!NT_STATUS_IS_OK(result)) {
3296 DEBUG(1, ("rpccli_setup_netlogon_creds failed for %s, "
3297 "unable to setup NETLOGON credentials: %s\n",
3298 domain->name, nt_errstr(result)));
3299 return result;
3302 result = netlogon_creds_cli_get(conn->netlogon_creds_ctx,
3303 talloc_tos(),
3304 &netlogon_creds);
3305 if (!NT_STATUS_IS_OK(result)) {
3306 DEBUG(1, ("netlogon_creds_cli_get failed for %s, "
3307 "unable to get NETLOGON credentials: %s\n",
3308 domain->name, nt_errstr(result)));
3309 return result;
3311 conn->netlogon_flags = netlogon_creds->negotiate_flags;
3312 TALLOC_FREE(netlogon_creds);
3314 if (!(conn->netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
3315 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3316 result = NT_STATUS_DOWNGRADE_DETECTED;
3317 DEBUG(1, ("Unwilling to make connection to domain %s"
3318 "without connection level security, "
3319 "must set 'winbind sealed pipes = false' and "
3320 "'require strong key = false' to proceed: %s\n",
3321 domain->name, nt_errstr(result)));
3322 invalidate_cm_connection(domain);
3323 return result;
3325 result = cli_rpc_pipe_open_noauth_transport(conn->cli,
3326 transport,
3327 &ndr_table_netlogon,
3328 &conn->netlogon_pipe);
3329 if (!NT_STATUS_IS_OK(result)) {
3330 invalidate_cm_connection(domain);
3331 return result;
3334 *cli = conn->netlogon_pipe;
3335 return NT_STATUS_OK;
3338 /* Using the credentials from the first pipe, open a signed and sealed
3339 second netlogon pipe. The session key is stored in the schannel
3340 part of the new pipe auth struct.
3343 result = cli_rpc_pipe_open_schannel_with_creds(
3344 conn->cli, &ndr_table_netlogon, transport,
3345 conn->netlogon_creds_ctx,
3346 &conn->netlogon_pipe);
3347 if (!NT_STATUS_IS_OK(result)) {
3348 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
3349 "was %s\n", nt_errstr(result)));
3351 invalidate_cm_connection(domain);
3352 return result;
3355 *cli = conn->netlogon_pipe;
3356 return NT_STATUS_OK;
3359 /****************************************************************************
3360 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3361 ****************************************************************************/
3363 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3364 struct rpc_pipe_client **cli)
3366 NTSTATUS status;
3368 status = init_dc_connection_rpc(domain, domain->rodc);
3369 if (!NT_STATUS_IS_OK(status)) {
3370 return status;
3373 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3374 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3375 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3376 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3377 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3378 invalidate_cm_connection(domain);
3379 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3381 if (NT_STATUS_IS_OK(status)) {
3382 return status;
3386 * we tried twice to connect via ncan_ip_tcp and schannel and
3387 * failed - maybe it is a trusted domain we can't connect to ?
3388 * do not try tcp next time - gd
3390 * This also prevents LSA over TCP
3392 domain->can_do_ncacn_ip_tcp = false;
3395 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3396 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3398 * SMB2 session expired, needs reauthentication. Drop
3399 * connection and retry.
3401 invalidate_cm_connection(domain);
3402 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3405 return status;
3408 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3409 void *private_data,
3410 uint32_t msg_type,
3411 struct server_id server_id,
3412 DATA_BLOB *data)
3414 struct winbindd_domain *domain;
3415 char *freeit = NULL;
3416 char *addr;
3418 if ((data == NULL)
3419 || (data->data == NULL)
3420 || (data->length == 0)
3421 || (data->data[data->length-1] != '\0')) {
3422 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3423 "string\n"));
3424 return;
3427 addr = (char *)data->data;
3428 DEBUG(10, ("IP %s dropped\n", addr));
3430 if (!is_ipaddress(addr)) {
3431 char *slash;
3433 * Some code sends us ip addresses with the /netmask
3434 * suffix
3436 slash = strchr(addr, '/');
3437 if (slash == NULL) {
3438 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3439 addr));
3440 return;
3442 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3443 if (freeit == NULL) {
3444 DEBUG(1, ("talloc failed\n"));
3445 return;
3447 addr = freeit;
3448 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3451 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3452 char sockaddr[INET6_ADDRSTRLEN];
3454 if (!cli_state_is_connected(domain->conn.cli)) {
3455 continue;
3458 print_sockaddr(sockaddr, sizeof(sockaddr),
3459 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3461 if (strequal(sockaddr, addr)) {
3462 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3465 TALLOC_FREE(freeit);