winbind: Keep "force_reauth" in invalidate_cm_connection
[Samba.git] / source3 / winbindd / winbindd_cm.c
blobbf5a2b4d7b1c06b85c2af8728145451be66952e8
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
34 selection etc
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
46 implementation. -tpot
51 TODO:
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
57 various sam handles.
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "libsmb/libsmb.h"
73 #include "libsmb/clidgram.h"
74 #include "ads.h"
75 #include "secrets.h"
76 #include "../libcli/security/security.h"
77 #include "passdb.h"
78 #include "messages.h"
79 #include "auth/gensec/gensec.h"
80 #include "../libcli/smb/smbXcli_base.h"
81 #include "libcli/auth/netlogon_creds_cli.h"
82 #include "auth.h"
83 #include "rpc_server/rpc_ncacn_np.h"
84 #include "auth/credentials/credentials.h"
85 #include "lib/param/param.h"
87 #undef DBGC_CLASS
88 #define DBGC_CLASS DBGC_WINBIND
90 struct dc_name_ip {
91 fstring name;
92 struct sockaddr_storage ss;
95 extern struct winbindd_methods reconnect_methods;
96 extern bool override_logfile;
98 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
99 static void set_dc_type_and_flags( struct winbindd_domain *domain );
100 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
101 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
102 struct dc_name_ip **dcs, int *num_dcs,
103 uint32_t request_flags);
105 /****************************************************************
106 Child failed to find DC's. Reschedule check.
107 ****************************************************************/
109 static void msg_failed_to_go_online(struct messaging_context *msg,
110 void *private_data,
111 uint32_t msg_type,
112 struct server_id server_id,
113 DATA_BLOB *data)
115 struct winbindd_domain *domain;
116 const char *domainname = (const char *)data->data;
118 if (data->data == NULL || data->length == 0) {
119 return;
122 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
124 for (domain = domain_list(); domain; domain = domain->next) {
125 if (domain->internal) {
126 continue;
129 if (strequal(domain->name, domainname)) {
130 if (domain->online) {
131 /* We're already online, ignore. */
132 DEBUG(5,("msg_fail_to_go_online: domain %s "
133 "already online.\n", domainname));
134 continue;
137 /* Reschedule the online check. */
138 set_domain_offline(domain);
139 break;
144 /****************************************************************
145 Actually cause a reconnect from a message.
146 ****************************************************************/
148 static void msg_try_to_go_online(struct messaging_context *msg,
149 void *private_data,
150 uint32_t msg_type,
151 struct server_id server_id,
152 DATA_BLOB *data)
154 struct winbindd_domain *domain;
155 const char *domainname = (const char *)data->data;
157 if (data->data == NULL || data->length == 0) {
158 return;
161 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
163 for (domain = domain_list(); domain; domain = domain->next) {
164 if (domain->internal) {
165 continue;
168 if (strequal(domain->name, domainname)) {
170 if (domain->online) {
171 /* We're already online, ignore. */
172 DEBUG(5,("msg_try_to_go_online: domain %s "
173 "already online.\n", domainname));
174 continue;
177 /* This call takes care of setting the online
178 flag to true if we connected, or re-adding
179 the offline handler if false. Bypasses online
180 check so always does network calls. */
182 init_dc_connection_network(domain, true);
183 break;
188 /****************************************************************
189 Fork a child to try and contact a DC. Do this as contacting a
190 DC requires blocking lookups and we don't want to block our
191 parent.
192 ****************************************************************/
194 static bool fork_child_dc_connect(struct winbindd_domain *domain)
196 struct dc_name_ip *dcs = NULL;
197 int num_dcs = 0;
198 TALLOC_CTX *mem_ctx = NULL;
199 pid_t parent_pid = getpid();
200 char *lfile = NULL;
201 NTSTATUS status;
202 bool ok;
204 if (domain->dc_probe_pid != (pid_t)-1) {
206 * We might already have a DC probe
207 * child working, check.
209 if (process_exists_by_pid(domain->dc_probe_pid)) {
210 DEBUG(10,("fork_child_dc_connect: pid %u already "
211 "checking for DC's.\n",
212 (unsigned int)domain->dc_probe_pid));
213 return true;
215 domain->dc_probe_pid = (pid_t)-1;
218 domain->dc_probe_pid = fork();
220 if (domain->dc_probe_pid == (pid_t)-1) {
221 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
222 return False;
225 if (domain->dc_probe_pid != (pid_t)0) {
226 /* Parent */
227 messaging_register(server_messaging_context(), NULL,
228 MSG_WINBIND_TRY_TO_GO_ONLINE,
229 msg_try_to_go_online);
230 messaging_register(server_messaging_context(), NULL,
231 MSG_WINBIND_FAILED_TO_GO_ONLINE,
232 msg_failed_to_go_online);
233 return True;
236 /* Child. */
238 /* Leave messages blocked - we will never process one. */
240 if (!override_logfile) {
241 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
242 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
243 _exit(1);
247 status = winbindd_reinit_after_fork(NULL, lfile);
248 if (!NT_STATUS_IS_OK(status)) {
249 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
250 nt_errstr(status)));
251 messaging_send_buf(server_messaging_context(),
252 pid_to_procid(parent_pid),
253 MSG_WINBIND_FAILED_TO_GO_ONLINE,
254 (const uint8_t *)domain->name,
255 strlen(domain->name)+1);
256 _exit(1);
258 SAFE_FREE(lfile);
260 setproctitle("dc-connect child");
262 mem_ctx = talloc_init("fork_child_dc_connect");
263 if (!mem_ctx) {
264 DEBUG(0,("talloc_init failed.\n"));
265 messaging_send_buf(server_messaging_context(),
266 pid_to_procid(parent_pid),
267 MSG_WINBIND_FAILED_TO_GO_ONLINE,
268 (const uint8_t *)domain->name,
269 strlen(domain->name)+1);
270 _exit(1);
273 ok = get_dcs(mem_ctx, domain, &dcs, &num_dcs, 0);
274 TALLOC_FREE(mem_ctx);
275 if (!ok || (num_dcs == 0)) {
276 /* Still offline ? Can't find DC's. */
277 messaging_send_buf(server_messaging_context(),
278 pid_to_procid(parent_pid),
279 MSG_WINBIND_FAILED_TO_GO_ONLINE,
280 (const uint8_t *)domain->name,
281 strlen(domain->name)+1);
282 _exit(0);
285 /* We got a DC. Send a message to our parent to get it to
286 try and do the same. */
288 messaging_send_buf(server_messaging_context(),
289 pid_to_procid(parent_pid),
290 MSG_WINBIND_TRY_TO_GO_ONLINE,
291 (const uint8_t *)domain->name,
292 strlen(domain->name)+1);
293 _exit(0);
296 /****************************************************************
297 Handler triggered if we're offline to try and detect a DC.
298 ****************************************************************/
300 static void check_domain_online_handler(struct tevent_context *ctx,
301 struct tevent_timer *te,
302 struct timeval now,
303 void *private_data)
305 struct winbindd_domain *domain =
306 (struct winbindd_domain *)private_data;
308 DEBUG(10,("check_domain_online_handler: called for domain "
309 "%s (online = %s)\n", domain->name,
310 domain->online ? "True" : "False" ));
312 TALLOC_FREE(domain->check_online_event);
314 /* Are we still in "startup" mode ? */
316 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
317 /* No longer in "startup" mode. */
318 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
319 domain->name ));
320 domain->startup = False;
323 /* We've been told to stay offline, so stay
324 that way. */
326 if (get_global_winbindd_state_offline()) {
327 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
328 domain->name ));
329 return;
332 /* Fork a child to test if it can contact a DC.
333 If it can then send ourselves a message to
334 cause a reconnect. */
336 fork_child_dc_connect(domain);
339 /****************************************************************
340 If we're still offline setup the timeout check.
341 ****************************************************************/
343 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
345 int wbr = lp_winbind_reconnect_delay();
347 if (domain->startup) {
348 domain->check_online_timeout = 10;
349 } else if (domain->check_online_timeout < wbr) {
350 domain->check_online_timeout = wbr;
354 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
355 void *private_data,
356 uint32_t msg_type,
357 struct server_id server_id,
358 DATA_BLOB *data)
360 const char *domain_name = (const char *)data->data;
361 struct winbindd_domain *domain;
363 domain = find_domain_from_name_noinit(domain_name);
364 if (domain == NULL) {
365 return;
368 domain->online = false;
370 DEBUG(10, ("Domain %s is marked as offline now.\n",
371 domain_name));
374 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
375 void *private_data,
376 uint32_t msg_type,
377 struct server_id server_id,
378 DATA_BLOB *data)
380 const char *domain_name = (const char *)data->data;
381 struct winbindd_domain *domain;
383 domain = find_domain_from_name_noinit(domain_name);
384 if (domain == NULL) {
385 return;
388 domain->online = true;
390 DEBUG(10, ("Domain %s is marked as online now.\n",
391 domain_name));
394 /****************************************************************
395 Set domain offline and also add handler to put us back online
396 if we detect a DC.
397 ****************************************************************/
399 void set_domain_offline(struct winbindd_domain *domain)
401 pid_t parent_pid = getppid();
403 DEBUG(10,("set_domain_offline: called for domain %s\n",
404 domain->name ));
406 TALLOC_FREE(domain->check_online_event);
408 if (domain->internal) {
409 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
410 domain->name ));
411 return;
414 domain->online = False;
416 /* Offline domains are always initialized. They're
417 re-initialized when they go back online. */
419 domain->initialized = True;
421 /* We only add the timeout handler that checks and
422 allows us to go back online when we've not
423 been told to remain offline. */
425 if (get_global_winbindd_state_offline()) {
426 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
427 domain->name ));
428 return;
431 /* If we're in startup mode, check again in 10 seconds, not in
432 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
434 calc_new_online_timeout_check(domain);
436 domain->check_online_event = tevent_add_timer(server_event_context(),
437 NULL,
438 timeval_current_ofs(domain->check_online_timeout,0),
439 check_domain_online_handler,
440 domain);
442 /* The above *has* to succeed for winbindd to work. */
443 if (!domain->check_online_event) {
444 smb_panic("set_domain_offline: failed to add online handler");
447 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
448 domain->name ));
450 /* Send a message to the parent that the domain is offline. */
451 if (parent_pid > 1 && !domain->internal) {
452 messaging_send_buf(server_messaging_context(),
453 pid_to_procid(parent_pid),
454 MSG_WINBIND_DOMAIN_OFFLINE,
455 (uint8_t *)domain->name,
456 strlen(domain->name) + 1);
459 /* Send an offline message to the idmap child when our
460 primary domain goes offline */
462 if ( domain->primary ) {
463 struct winbindd_child *idmap = idmap_child();
465 if ( idmap->pid != 0 ) {
466 messaging_send_buf(server_messaging_context(),
467 pid_to_procid(idmap->pid),
468 MSG_WINBIND_OFFLINE,
469 (const uint8_t *)domain->name,
470 strlen(domain->name)+1);
474 return;
477 /****************************************************************
478 Set domain online - if allowed.
479 ****************************************************************/
481 static void set_domain_online(struct winbindd_domain *domain)
483 pid_t parent_pid = getppid();
485 DEBUG(10,("set_domain_online: called for domain %s\n",
486 domain->name ));
488 if (domain->internal) {
489 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
490 domain->name ));
491 return;
494 if (get_global_winbindd_state_offline()) {
495 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
496 domain->name ));
497 return;
500 winbindd_set_locator_kdc_envs(domain);
502 /* If we are waiting to get a krb5 ticket, trigger immediately. */
503 ccache_regain_all_now();
505 /* Ok, we're out of any startup mode now... */
506 domain->startup = False;
508 if (domain->online == False) {
509 /* We were offline - now we're online. We default to
510 using the MS-RPC backend if we started offline,
511 and if we're going online for the first time we
512 should really re-initialize the backends and the
513 checks to see if we're talking to an AD or NT domain.
516 domain->initialized = False;
518 /* 'reconnect_methods' is the MS-RPC backend. */
519 if (domain->backend == &reconnect_methods) {
520 domain->backend = NULL;
524 /* Ensure we have no online timeout checks. */
525 domain->check_online_timeout = 0;
526 TALLOC_FREE(domain->check_online_event);
528 /* Ensure we ignore any pending child messages. */
529 messaging_deregister(server_messaging_context(),
530 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
531 messaging_deregister(server_messaging_context(),
532 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
534 domain->online = True;
536 /* Send a message to the parent that the domain is online. */
537 if (parent_pid > 1 && !domain->internal) {
538 messaging_send_buf(server_messaging_context(),
539 pid_to_procid(parent_pid),
540 MSG_WINBIND_DOMAIN_ONLINE,
541 (uint8_t *)domain->name,
542 strlen(domain->name) + 1);
545 /* Send an online message to the idmap child when our
546 primary domain comes online */
548 if ( domain->primary ) {
549 struct winbindd_child *idmap = idmap_child();
551 if ( idmap->pid != 0 ) {
552 messaging_send_buf(server_messaging_context(),
553 pid_to_procid(idmap->pid),
554 MSG_WINBIND_ONLINE,
555 (const uint8_t *)domain->name,
556 strlen(domain->name)+1);
560 return;
563 /****************************************************************
564 Requested to set a domain online.
565 ****************************************************************/
567 void set_domain_online_request(struct winbindd_domain *domain)
569 struct timeval tev;
571 DEBUG(10,("set_domain_online_request: called for domain %s\n",
572 domain->name ));
574 if (get_global_winbindd_state_offline()) {
575 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
576 domain->name ));
577 return;
580 if (domain->internal) {
581 DEBUG(10, ("set_domain_online_request: Internal domains are "
582 "always online\n"));
583 return;
586 /* We've been told it's safe to go online and
587 try and connect to a DC. But I don't believe it
588 because network manager seems to lie.
589 Wait at least 5 seconds. Heuristics suck... */
592 GetTimeOfDay(&tev);
594 /* Go into "startup" mode again. */
595 domain->startup_time = time_mono(NULL);
596 domain->startup = True;
598 tev.tv_sec += 5;
600 if (!domain->check_online_event) {
601 /* If we've come from being globally offline we
602 don't have a check online event handler set.
603 We need to add one now we're trying to go
604 back online. */
606 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
607 domain->name ));
610 TALLOC_FREE(domain->check_online_event);
612 domain->check_online_event = tevent_add_timer(server_event_context(),
613 NULL,
614 tev,
615 check_domain_online_handler,
616 domain);
618 /* The above *has* to succeed for winbindd to work. */
619 if (!domain->check_online_event) {
620 smb_panic("set_domain_online_request: failed to add online handler");
624 /****************************************************************
625 Add -ve connection cache entries for domain and realm.
626 ****************************************************************/
628 static void winbind_add_failed_connection_entry(
629 const struct winbindd_domain *domain,
630 const char *server,
631 NTSTATUS result)
633 add_failed_connection_entry(domain->name, server, result);
634 /* If this was the saf name for the last thing we talked to,
635 remove it. */
636 saf_delete(domain->name);
637 if (domain->alt_name != NULL) {
638 add_failed_connection_entry(domain->alt_name, server, result);
639 saf_delete(domain->alt_name);
641 winbindd_unset_locator_kdc_env(domain);
644 /* Choose between anonymous or authenticated connections. We need to use
645 an authenticated connection if DCs have the RestrictAnonymous registry
646 entry set > 0, or the "Additional restrictions for anonymous
647 connections" set in the win2k Local Security Policy.
649 Caller to free() result in domain, username, password
652 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
654 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
655 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
656 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
658 if (*username && **username) {
660 if (!*domain || !**domain)
661 *domain = smb_xstrdup(lp_workgroup());
663 if (!*password || !**password)
664 *password = smb_xstrdup("");
666 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
667 *domain, *username));
669 } else {
670 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
671 *username = smb_xstrdup("");
672 *domain = smb_xstrdup("");
673 *password = smb_xstrdup("");
677 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
678 struct cli_credentials **_creds)
681 TALLOC_CTX *frame = talloc_stackframe();
682 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
683 struct loadparm_context *lp_ctx;
684 char *username = NULL;
685 char *netbios_domain = NULL;
686 char *password = NULL;
687 struct cli_credentials *creds = NULL;
688 bool ok;
690 cm_get_ipc_userpass(&username, &netbios_domain, &password);
692 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
693 if (lp_ctx == NULL) {
694 DEBUG(1, ("loadparm_init_s3 failed\n"));
695 status = NT_STATUS_INTERNAL_ERROR;
696 goto fail;
699 creds = cli_credentials_init(mem_ctx);
700 if (creds == NULL) {
701 status = NT_STATUS_NO_MEMORY;
702 goto fail;
705 cli_credentials_set_conf(creds, lp_ctx);
706 cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
708 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
709 if (!ok) {
710 status = NT_STATUS_NO_MEMORY;
711 goto fail;
714 ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
715 if (!ok) {
716 status = NT_STATUS_NO_MEMORY;
717 goto fail;
720 ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
721 if (!ok) {
722 status = NT_STATUS_NO_MEMORY;
723 goto fail;
726 *_creds = creds;
727 creds = NULL;
728 status = NT_STATUS_OK;
729 fail:
730 TALLOC_FREE(creds);
731 SAFE_FREE(username);
732 SAFE_FREE(netbios_domain);
733 SAFE_FREE(password);
734 TALLOC_FREE(frame);
735 return status;
738 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
740 TALLOC_CTX *frame = talloc_stackframe();
741 char *ipc_account = NULL;
742 char *ipc_domain = NULL;
743 char *ipc_password = NULL;
744 const char *creds_account = NULL;
745 const char *creds_domain = NULL;
746 const char *creds_password = NULL;
747 bool ret = false;
749 cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
751 creds_account = cli_credentials_get_username(creds);
752 creds_domain = cli_credentials_get_domain(creds);
753 creds_password = cli_credentials_get_password(creds);
755 if (!strequal(ipc_domain, creds_domain)) {
756 goto done;
759 if (!strequal(ipc_account, creds_account)) {
760 goto done;
763 if (!strcsequal(ipc_password, creds_password)) {
764 goto done;
767 ret = true;
768 done:
769 SAFE_FREE(ipc_account);
770 SAFE_FREE(ipc_domain);
771 SAFE_FREE(ipc_password);
772 TALLOC_FREE(frame);
773 return ret;
776 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
777 fstring dcname,
778 struct sockaddr_storage *dc_ss,
779 uint32_t request_flags)
781 struct winbindd_domain *our_domain = NULL;
782 struct rpc_pipe_client *netlogon_pipe = NULL;
783 NTSTATUS result;
784 WERROR werr;
785 TALLOC_CTX *mem_ctx;
786 unsigned int orig_timeout;
787 const char *tmp = NULL;
788 const char *p;
789 struct dcerpc_binding_handle *b;
791 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
792 * moment.... */
794 if (IS_DC) {
795 return False;
798 if (domain->primary) {
799 return False;
802 our_domain = find_our_domain();
804 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
805 return False;
808 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
809 if (!NT_STATUS_IS_OK(result)) {
810 talloc_destroy(mem_ctx);
811 return False;
814 b = netlogon_pipe->binding_handle;
816 /* This call can take a long time - allow the server to time out.
817 35 seconds should do it. */
819 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
821 if (our_domain->active_directory) {
822 struct netr_DsRGetDCNameInfo *domain_info = NULL;
825 * TODO request flags are not respected in the server
826 * (and in some cases, like REQUIRE_PDC, causes an error)
828 result = dcerpc_netr_DsRGetDCName(b,
829 mem_ctx,
830 our_domain->dcname,
831 domain->name,
832 NULL,
833 NULL,
834 request_flags|DS_RETURN_DNS_NAME,
835 &domain_info,
836 &werr);
837 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
838 tmp = talloc_strdup(
839 mem_ctx, domain_info->dc_unc);
840 if (tmp == NULL) {
841 DEBUG(0, ("talloc_strdup failed\n"));
842 talloc_destroy(mem_ctx);
843 return false;
845 if (domain->alt_name == NULL) {
846 domain->alt_name = talloc_strdup(domain,
847 domain_info->domain_name);
848 if (domain->alt_name == NULL) {
849 DEBUG(0, ("talloc_strdup failed\n"));
850 talloc_destroy(mem_ctx);
851 return false;
854 if (domain->forest_name == NULL) {
855 domain->forest_name = talloc_strdup(domain,
856 domain_info->forest_name);
857 if (domain->forest_name == NULL) {
858 DEBUG(0, ("talloc_strdup failed\n"));
859 talloc_destroy(mem_ctx);
860 return false;
864 } else {
865 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
866 our_domain->dcname,
867 domain->name,
868 &tmp,
869 &werr);
872 /* And restore our original timeout. */
873 rpccli_set_timeout(netlogon_pipe, orig_timeout);
875 if (!NT_STATUS_IS_OK(result)) {
876 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
877 nt_errstr(result)));
878 talloc_destroy(mem_ctx);
879 return false;
882 if (!W_ERROR_IS_OK(werr)) {
883 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
884 win_errstr(werr)));
885 talloc_destroy(mem_ctx);
886 return false;
889 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
890 p = strip_hostname(tmp);
892 fstrcpy(dcname, p);
894 talloc_destroy(mem_ctx);
896 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
898 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
899 return False;
902 return True;
906 * Helper function to assemble trust password and account name
908 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
909 TALLOC_CTX *mem_ctx,
910 bool netlogon,
911 struct cli_credentials **_creds)
913 const struct winbindd_domain *creds_domain = NULL;
914 struct cli_credentials *creds;
915 NTSTATUS status;
916 bool force_machine_account = false;
918 /* If we are a DC and this is not our own domain */
920 if (!domain->active_directory) {
921 if (!netlogon) {
923 * For non active directory domains
924 * we can only use NTLMSSP for SMB.
926 * But the trust account is not allowed
927 * to use SMB with NTLMSSP.
929 force_machine_account = true;
933 if (IS_DC && !force_machine_account) {
934 creds_domain = domain;
935 } else {
936 creds_domain = find_our_domain();
937 if (creds_domain == NULL) {
938 return NT_STATUS_INVALID_SERVER_STATE;
942 status = pdb_get_trust_credentials(creds_domain->name,
943 creds_domain->alt_name,
944 mem_ctx,
945 &creds);
946 if (!NT_STATUS_IS_OK(status)) {
947 goto ipc_fallback;
950 if (creds_domain != domain) {
952 * We can only use schannel against a direct trust
954 cli_credentials_set_secure_channel_type(creds,
955 SEC_CHAN_NULL);
958 *_creds = creds;
959 return NT_STATUS_OK;
961 ipc_fallback:
962 if (netlogon) {
963 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
966 status = cm_get_ipc_credentials(mem_ctx, &creds);
967 if (!NT_STATUS_IS_OK(status)) {
968 return status;
971 *_creds = creds;
972 return NT_STATUS_OK;
975 /************************************************************************
976 Given a fd with a just-connected TCP connection to a DC, open a connection
977 to the pipe.
978 ************************************************************************/
980 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
981 const int sockfd,
982 const char *controller,
983 struct cli_state **cli,
984 bool *retry)
986 bool try_ipc_auth = false;
987 const char *machine_principal = NULL;
988 const char *machine_realm = NULL;
989 const char *machine_account = NULL;
990 const char *machine_domain = NULL;
991 int flags = 0;
992 struct cli_credentials *creds = NULL;
994 struct named_mutex *mutex;
996 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
997 NTSTATUS tmp_status;
998 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
1000 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
1002 if (IS_AD_DC) {
1003 if (domain->secure_channel_type == SEC_CHAN_NULL) {
1005 * Make sure we don't even try to
1006 * connect to a foreign domain
1007 * without a direct outbound trust.
1009 return NT_STATUS_NO_TRUST_LSA_SECRET;
1013 * As AD DC we only use netlogon and lsa
1014 * using schannel over an anonymous transport
1015 * (ncacn_ip_tcp or ncacn_np).
1017 * Currently we always establish the SMB connection,
1018 * even if we don't use it, because we later use ncacn_ip_tcp.
1020 * As we won't use the SMB connection there's no
1021 * need to try kerberos. And NT4 domains expect
1022 * an anonymous IPC$ connection anyway.
1024 smb_sign_client_connections = SMB_SIGNING_OFF;
1027 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
1029 * If we are connecting to our own AD domain, require
1030 * smb signing to disrupt MITM attacks
1032 if (domain->primary && lp_security() == SEC_ADS) {
1033 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1035 * If we are in or are an AD domain and connecting to another
1036 * AD domain in our forest
1037 * then require smb signing to disrupt MITM attacks
1039 } else if ((lp_security() == SEC_ADS)
1040 && domain->active_directory
1041 && (domain->domain_trust_attribs
1042 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
1043 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1047 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1048 controller, domain->name ));
1050 *retry = True;
1052 mutex = grab_named_mutex(talloc_tos(), controller,
1053 WINBIND_SERVER_MUTEX_WAIT_TIME);
1054 if (mutex == NULL) {
1055 close(sockfd);
1056 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1057 controller));
1058 result = NT_STATUS_POSSIBLE_DEADLOCK;
1059 goto done;
1062 *cli = cli_state_create(NULL, sockfd, controller,
1063 smb_sign_client_connections, flags);
1064 if (*cli == NULL) {
1065 close(sockfd);
1066 DEBUG(1, ("Could not cli_initialize\n"));
1067 result = NT_STATUS_NO_MEMORY;
1068 goto done;
1071 cli_set_timeout(*cli, 10000); /* 10 seconds */
1073 set_socket_options(sockfd, lp_socket_options());
1075 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
1076 lp_client_ipc_min_protocol(),
1077 lp_client_ipc_max_protocol());
1079 if (!NT_STATUS_IS_OK(result)) {
1080 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
1081 goto done;
1084 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
1085 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
1086 try_ipc_auth = true;
1087 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1088 try_ipc_auth = true;
1089 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1091 * If we are forcing on SMB signing, then we must
1092 * require authentication unless this is a one-way
1093 * trust, and we have no stored user/password
1095 try_ipc_auth = true;
1098 if (IS_AD_DC) {
1100 * As AD DC we only use netlogon and lsa
1101 * using schannel over an anonymous transport
1102 * (ncacn_ip_tcp or ncacn_np).
1104 * Currently we always establish the SMB connection,
1105 * even if we don't use it, because we later use ncacn_ip_tcp.
1107 * As we won't use the SMB connection there's no
1108 * need to try kerberos. And NT4 domains expect
1109 * an anonymous IPC$ connection anyway.
1111 try_ipc_auth = false;
1114 if (try_ipc_auth) {
1115 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
1116 if (!NT_STATUS_IS_OK(result)) {
1117 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1118 domain->name, nt_errstr(result)));
1119 goto done;
1121 } else {
1123 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1124 * would try and authentication with our machine
1125 * account password and fail. This is very rare in
1126 * the modern world however
1128 creds = cli_credentials_init_anon(talloc_tos());
1129 if (creds == NULL) {
1130 result = NT_STATUS_NO_MEMORY;
1131 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1132 domain->name, nt_errstr(result)));
1133 goto done;
1137 machine_principal = cli_credentials_get_principal(creds,
1138 talloc_tos());
1139 machine_realm = cli_credentials_get_realm(creds);
1140 machine_account = cli_credentials_get_username(creds);
1141 machine_domain = cli_credentials_get_domain(creds);
1143 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1144 "[%s] and realm [%s]\n",
1145 controller, domain->name, domain->alt_name,
1146 machine_domain, machine_account,
1147 machine_principal, machine_realm));
1149 if (cli_credentials_is_anonymous(creds)) {
1150 goto anon_fallback;
1153 winbindd_set_locator_kdc_envs(domain);
1155 result = cli_session_setup_creds(*cli, creds);
1156 if (NT_STATUS_IS_OK(result)) {
1157 goto session_setup_done;
1160 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1161 controller,
1162 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1163 nt_errstr(result)));
1166 * If we are not going to validiate the conneciton
1167 * with SMB signing, then allow us to fall back to
1168 * anonymous
1170 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1171 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1172 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1173 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1174 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1176 if (!cm_is_ipc_credentials(creds)) {
1177 goto ipc_fallback;
1180 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1181 goto done;
1184 goto anon_fallback;
1187 goto done;
1189 ipc_fallback:
1190 TALLOC_FREE(creds);
1191 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1192 if (!NT_STATUS_IS_OK(tmp_status)) {
1193 result = tmp_status;
1194 goto done;
1197 if (cli_credentials_is_anonymous(creds)) {
1198 goto anon_fallback;
1201 machine_account = cli_credentials_get_username(creds);
1202 machine_domain = cli_credentials_get_domain(creds);
1204 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1205 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1206 machine_domain, machine_account));
1208 result = cli_session_setup_creds(*cli, creds);
1209 if (NT_STATUS_IS_OK(result)) {
1210 goto session_setup_done;
1213 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1214 controller,
1215 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1216 nt_errstr(result)));
1219 * If we are not going to validiate the conneciton
1220 * with SMB signing, then allow us to fall back to
1221 * anonymous
1223 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1224 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1225 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1226 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1227 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1229 goto anon_fallback;
1232 goto done;
1234 anon_fallback:
1235 TALLOC_FREE(creds);
1237 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1238 goto done;
1241 /* Fall back to anonymous connection, this might fail later */
1242 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1243 "connection for DC %s\n",
1244 controller ));
1246 result = cli_session_setup_anon(*cli);
1247 if (NT_STATUS_IS_OK(result)) {
1248 DEBUG(5, ("Connected anonymously\n"));
1249 goto session_setup_done;
1252 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1253 controller, nt_errstr(result)));
1255 /* We can't session setup */
1256 goto done;
1258 session_setup_done:
1259 TALLOC_FREE(creds);
1262 * This should be a short term hack until
1263 * dynamic re-authentication is implemented.
1265 * See Bug 9175 - winbindd doesn't recover from
1266 * NT_STATUS_NETWORK_SESSION_EXPIRED
1268 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1269 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1272 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1273 if (!NT_STATUS_IS_OK(result)) {
1274 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1275 goto done;
1277 tcon_status = result;
1279 /* cache the server name for later connections */
1281 saf_store(domain->name, controller);
1282 if (domain->alt_name) {
1283 saf_store(domain->alt_name, controller);
1286 winbindd_set_locator_kdc_envs(domain);
1288 TALLOC_FREE(mutex);
1289 *retry = False;
1291 result = NT_STATUS_OK;
1293 done:
1294 TALLOC_FREE(mutex);
1295 TALLOC_FREE(creds);
1297 if (NT_STATUS_IS_OK(result)) {
1298 result = tcon_status;
1301 if (!NT_STATUS_IS_OK(result)) {
1302 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1303 controller, nt_errstr(result)));
1304 winbind_add_failed_connection_entry(domain, controller, result);
1305 if ((*cli) != NULL) {
1306 cli_shutdown(*cli);
1307 *cli = NULL;
1311 return result;
1314 /*******************************************************************
1315 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1316 array.
1318 Keeps the list unique by not adding duplicate entries.
1320 @param[in] mem_ctx talloc memory context to allocate from
1321 @param[in] domain_name domain of the DC
1322 @param[in] dcname name of the DC to add to the list
1323 @param[in] pss Internet address and port pair to add to the list
1324 @param[in,out] dcs array of dc_name_ip structures to add to
1325 @param[in,out] num_dcs number of dcs returned in the dcs array
1326 @return true if the list was added to, false otherwise
1327 *******************************************************************/
1329 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1330 const char *dcname, struct sockaddr_storage *pss,
1331 struct dc_name_ip **dcs, int *num)
1333 int i = 0;
1335 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1336 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1337 return False;
1340 /* Make sure there's no duplicates in the list */
1341 for (i=0; i<*num; i++)
1342 if (sockaddr_equal(
1343 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1344 (struct sockaddr *)(void *)pss))
1345 return False;
1347 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1349 if (*dcs == NULL)
1350 return False;
1352 fstrcpy((*dcs)[*num].name, dcname);
1353 (*dcs)[*num].ss = *pss;
1354 *num += 1;
1355 return True;
1358 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1359 struct sockaddr_storage *pss, uint16_t port,
1360 struct sockaddr_storage **addrs, int *num)
1362 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1364 if (*addrs == NULL) {
1365 *num = 0;
1366 return False;
1369 (*addrs)[*num] = *pss;
1370 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1372 *num += 1;
1373 return True;
1376 /*******************************************************************
1377 convert an ip to a name
1378 For an AD Domain, it checks the requirements of the request flags.
1379 *******************************************************************/
1381 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1382 const struct winbindd_domain *domain,
1383 struct sockaddr_storage *pss,
1384 char **name, uint32_t request_flags)
1386 struct ip_service ip_list;
1387 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1388 NTSTATUS status;
1389 const char *dc_name;
1390 fstring nbtname;
1391 #ifdef HAVE_ADS
1392 bool is_ad_domain = false;
1393 #endif
1394 ip_list.ss = *pss;
1395 ip_list.port = 0;
1397 #ifdef HAVE_ADS
1398 /* For active directory servers, try to get the ldap server name.
1399 None of these failures should be considered critical for now */
1401 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1402 is_ad_domain = true;
1403 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1404 is_ad_domain = domain->active_directory;
1407 if (is_ad_domain) {
1408 ADS_STRUCT *ads;
1409 ADS_STATUS ads_status;
1410 char addr[INET6_ADDRSTRLEN];
1412 print_sockaddr(addr, sizeof(addr), pss);
1414 ads = ads_init(domain->alt_name, domain->name, addr);
1415 ads->auth.flags |= ADS_AUTH_NO_BIND;
1416 ads->config.flags |= request_flags;
1417 ads->server.no_fallback = true;
1419 ads_status = ads_connect(ads);
1420 if (ADS_ERR_OK(ads_status)) {
1421 /* We got a cldap packet. */
1422 *name = talloc_strdup(mem_ctx,
1423 ads->config.ldap_server_name);
1424 if (*name == NULL) {
1425 return false;
1427 namecache_store(*name, 0x20, 1, &ip_list);
1429 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1431 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1432 if (ads_closest_dc(ads)) {
1433 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1435 /* We're going to use this KDC for this realm/domain.
1436 If we are using sites, then force the krb5 libs
1437 to use this KDC. */
1439 create_local_private_krb5_conf_for_domain(domain->alt_name,
1440 domain->name,
1441 sitename,
1442 pss);
1444 TALLOC_FREE(sitename);
1445 } else {
1446 /* use an off site KDC */
1447 create_local_private_krb5_conf_for_domain(domain->alt_name,
1448 domain->name,
1449 NULL,
1450 pss);
1452 winbindd_set_locator_kdc_envs(domain);
1454 /* Ensure we contact this DC also. */
1455 saf_store(domain->name, *name);
1456 saf_store(domain->alt_name, *name);
1459 ads_destroy( &ads );
1460 return True;
1463 ads_destroy( &ads );
1464 return false;
1466 #endif
1468 status = nbt_getdc(server_messaging_context(), 10, pss, domain->name,
1469 &domain->sid, nt_version, mem_ctx, &nt_version,
1470 &dc_name, NULL);
1471 if (NT_STATUS_IS_OK(status)) {
1472 *name = talloc_strdup(mem_ctx, dc_name);
1473 if (*name == NULL) {
1474 return false;
1476 namecache_store(*name, 0x20, 1, &ip_list);
1477 return True;
1480 /* try node status request */
1482 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1483 namecache_store(nbtname, 0x20, 1, &ip_list);
1485 if (name != NULL) {
1486 *name = talloc_strdup(mem_ctx, nbtname);
1487 if (*name == NULL) {
1488 return false;
1492 return true;
1494 return False;
1497 /*******************************************************************
1498 Retrieve a list of IP addresses for domain controllers.
1500 The array is sorted in the preferred connection order.
1502 @param[in] mem_ctx talloc memory context to allocate from
1503 @param[in] domain domain to retrieve DCs for
1504 @param[out] dcs array of dcs that will be returned
1505 @param[out] num_dcs number of dcs returned in the dcs array
1506 @return always true
1507 *******************************************************************/
1509 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1510 struct dc_name_ip **dcs, int *num_dcs,
1511 uint32_t request_flags)
1513 fstring dcname;
1514 struct sockaddr_storage ss;
1515 struct ip_service *ip_list = NULL;
1516 int iplist_size = 0;
1517 int i;
1518 bool is_our_domain;
1519 enum security_types sec = (enum security_types)lp_security();
1521 is_our_domain = strequal(domain->name, lp_workgroup());
1523 /* If not our domain, get the preferred DC, by asking our primary DC */
1524 if ( !is_our_domain
1525 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1526 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1527 num_dcs) )
1529 char addr[INET6_ADDRSTRLEN];
1530 print_sockaddr(addr, sizeof(addr), &ss);
1531 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1532 dcname, addr));
1533 return True;
1536 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1537 char *sitename = NULL;
1539 /* We need to make sure we know the local site before
1540 doing any DNS queries, as this will restrict the
1541 get_sorted_dc_list() call below to only fetching
1542 DNS records for the correct site. */
1544 /* Find any DC to get the site record.
1545 We deliberately don't care about the
1546 return here. */
1548 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1550 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1551 if (sitename) {
1553 /* Do the site-specific AD dns lookup first. */
1554 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1555 &iplist_size, True);
1557 /* Add ips to the DC array. We don't look up the name
1558 of the DC in this function, but we fill in the char*
1559 of the ip now to make the failed connection cache
1560 work */
1561 for ( i=0; i<iplist_size; i++ ) {
1562 char addr[INET6_ADDRSTRLEN];
1563 print_sockaddr(addr, sizeof(addr),
1564 &ip_list[i].ss);
1565 add_one_dc_unique(mem_ctx,
1566 domain->name,
1567 addr,
1568 &ip_list[i].ss,
1569 dcs,
1570 num_dcs);
1573 SAFE_FREE(ip_list);
1574 TALLOC_FREE(sitename);
1575 iplist_size = 0;
1578 /* Now we add DCs from the main AD DNS lookup. */
1579 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1580 &iplist_size, True);
1582 for ( i=0; i<iplist_size; i++ ) {
1583 char addr[INET6_ADDRSTRLEN];
1584 print_sockaddr(addr, sizeof(addr),
1585 &ip_list[i].ss);
1586 add_one_dc_unique(mem_ctx,
1587 domain->name,
1588 addr,
1589 &ip_list[i].ss,
1590 dcs,
1591 num_dcs);
1594 SAFE_FREE(ip_list);
1595 iplist_size = 0;
1598 /* Try standard netbios queries if no ADS and fall back to DNS queries
1599 * if alt_name is available */
1600 if (*num_dcs == 0) {
1601 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1602 false);
1603 if (iplist_size == 0) {
1604 if (domain->alt_name != NULL) {
1605 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1606 &iplist_size, true);
1610 for ( i=0; i<iplist_size; i++ ) {
1611 char addr[INET6_ADDRSTRLEN];
1612 print_sockaddr(addr, sizeof(addr),
1613 &ip_list[i].ss);
1614 add_one_dc_unique(mem_ctx,
1615 domain->name,
1616 addr,
1617 &ip_list[i].ss,
1618 dcs,
1619 num_dcs);
1622 SAFE_FREE(ip_list);
1623 iplist_size = 0;
1626 return True;
1629 /*******************************************************************
1630 Find and make a connection to a DC in the given domain.
1632 @param[in] mem_ctx talloc memory context to allocate from
1633 @param[in] domain domain to find a dc in
1634 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1635 @param[out] pss DC Internet address and port
1636 @param[out] fd fd of the open socket connected to the newly found dc
1637 @return true when a DC connection is made, false otherwise
1638 *******************************************************************/
1640 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1641 struct winbindd_domain *domain,
1642 char **dcname, struct sockaddr_storage *pss, int *fd,
1643 uint32_t request_flags)
1645 struct dc_name_ip *dcs = NULL;
1646 int num_dcs = 0;
1648 const char **dcnames = NULL;
1649 size_t num_dcnames = 0;
1651 struct sockaddr_storage *addrs = NULL;
1652 int num_addrs = 0;
1654 int i;
1655 size_t fd_index;
1657 NTSTATUS status;
1659 *fd = -1;
1661 again:
1662 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1663 return False;
1665 for (i=0; i<num_dcs; i++) {
1667 if (!add_string_to_array(mem_ctx, dcs[i].name,
1668 &dcnames, &num_dcnames)) {
1669 return False;
1671 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1672 &addrs, &num_addrs)) {
1673 return False;
1677 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1678 return False;
1680 if ((addrs == NULL) || (dcnames == NULL))
1681 return False;
1683 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1684 num_addrs, 0, 10, fd, &fd_index, NULL);
1685 if (!NT_STATUS_IS_OK(status)) {
1686 for (i=0; i<num_dcs; i++) {
1687 char ab[INET6_ADDRSTRLEN];
1688 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1689 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1690 "domain %s address %s. Error was %s\n",
1691 domain->name, ab, nt_errstr(status) ));
1692 winbind_add_failed_connection_entry(domain,
1693 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1695 return False;
1698 *pss = addrs[fd_index];
1700 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1701 /* Ok, we've got a name for the DC */
1702 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1703 if (*dcname == NULL) {
1704 return false;
1706 return true;
1709 /* Try to figure out the name */
1710 if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1711 return True;
1714 /* We can not continue without the DC's name */
1715 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1716 NT_STATUS_UNSUCCESSFUL);
1718 /* Throw away all arrays as we're doing this again. */
1719 TALLOC_FREE(dcs);
1720 num_dcs = 0;
1722 TALLOC_FREE(dcnames);
1723 num_dcnames = 0;
1725 TALLOC_FREE(addrs);
1726 num_addrs = 0;
1728 close(*fd);
1729 *fd = -1;
1731 goto again;
1734 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1736 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1737 domain_name);
1740 static void store_current_dc_in_gencache(const char *domain_name,
1741 const char *dc_name,
1742 struct cli_state *cli)
1744 char addr[INET6_ADDRSTRLEN];
1745 char *key = NULL;
1746 char *value = NULL;
1748 if (!cli_state_is_connected(cli)) {
1749 return;
1752 print_sockaddr(addr, sizeof(addr),
1753 smbXcli_conn_remote_sockaddr(cli->conn));
1755 key = current_dc_key(talloc_tos(), domain_name);
1756 if (key == NULL) {
1757 goto done;
1760 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1761 if (value == NULL) {
1762 goto done;
1765 gencache_set(key, value, 0x7fffffff);
1766 done:
1767 TALLOC_FREE(value);
1768 TALLOC_FREE(key);
1771 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1772 const char *domain_name,
1773 char **p_dc_name, char **p_dc_ip)
1775 char *key, *p;
1776 char *value = NULL;
1777 bool ret = false;
1778 char *dc_name = NULL;
1779 char *dc_ip = NULL;
1781 key = current_dc_key(talloc_tos(), domain_name);
1782 if (key == NULL) {
1783 goto done;
1785 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1786 goto done;
1788 p = strchr(value, ' ');
1789 if (p == NULL) {
1790 goto done;
1792 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1793 if (dc_ip == NULL) {
1794 goto done;
1796 dc_name = talloc_strdup(mem_ctx, p+1);
1797 if (dc_name == NULL) {
1798 goto done;
1801 if (p_dc_ip != NULL) {
1802 *p_dc_ip = dc_ip;
1803 dc_ip = NULL;
1805 if (p_dc_name != NULL) {
1806 *p_dc_name = dc_name;
1807 dc_name = NULL;
1809 ret = true;
1810 done:
1811 TALLOC_FREE(dc_name);
1812 TALLOC_FREE(dc_ip);
1813 TALLOC_FREE(key);
1814 TALLOC_FREE(value);
1815 return ret;
1818 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1819 const struct ndr_interface_table *table,
1820 struct rpc_pipe_client **ret_pipe)
1822 struct rpc_pipe_client *cli = NULL;
1823 const struct auth_session_info *session_info;
1824 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1827 session_info = get_session_info_system();
1828 SMB_ASSERT(session_info != NULL);
1830 /* create a connection to the specified pipe */
1831 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1832 status = rpc_pipe_open_interface(mem_ctx,
1833 table,
1834 session_info,
1835 NULL,
1836 NULL,
1837 server_messaging_context(),
1838 &cli);
1839 } else {
1840 status = rpc_pipe_open_internal(mem_ctx,
1841 table,
1842 session_info,
1843 NULL,
1844 NULL,
1845 server_messaging_context(),
1846 &cli);
1848 if (!NT_STATUS_IS_OK(status)) {
1849 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1850 table->name, nt_errstr(status)));
1851 return status;
1854 if (ret_pipe) {
1855 *ret_pipe = cli;
1858 return NT_STATUS_OK;
1861 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1862 struct winbindd_cm_conn *new_conn,
1863 bool need_rw_dc)
1865 TALLOC_CTX *mem_ctx;
1866 NTSTATUS result;
1867 char *saf_servername;
1868 int retries;
1869 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1871 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1872 set_domain_offline(domain);
1873 return NT_STATUS_NO_MEMORY;
1876 saf_servername = saf_fetch(mem_ctx, domain->name );
1878 /* we have to check the server affinity cache here since
1879 later we select a DC based on response time and not preference */
1881 /* Check the negative connection cache
1882 before talking to it. It going down may have
1883 triggered the reconnection. */
1885 if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1886 struct sockaddr_storage ss;
1887 char *dcname = NULL;
1888 bool resolved = true;
1890 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1891 saf_servername, domain->name));
1893 /* convert an ip address to a name */
1894 if (is_ipaddress(saf_servername)) {
1895 if (!interpret_string_addr(&ss, saf_servername,
1896 AI_NUMERICHOST)) {
1897 TALLOC_FREE(mem_ctx);
1898 return NT_STATUS_UNSUCCESSFUL;
1900 } else {
1901 if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1902 resolved = false;
1906 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1907 domain->dcname = talloc_strdup(domain,
1908 dcname);
1909 if (domain->dcname == NULL) {
1910 TALLOC_FREE(mem_ctx);
1911 return NT_STATUS_NO_MEMORY;
1914 domain->dcaddr = ss;
1915 } else {
1916 winbind_add_failed_connection_entry(domain, saf_servername,
1917 NT_STATUS_UNSUCCESSFUL);
1921 for (retries = 0; retries < 3; retries++) {
1922 int fd = -1;
1923 bool retry = False;
1924 char *dcname = NULL;
1926 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1928 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1929 domain->dcname ? domain->dcname : "", domain->name));
1931 if (domain->dcname != NULL &&
1932 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1933 domain->dcname)))
1935 NTSTATUS status;
1937 status = smbsock_connect(&domain->dcaddr, 0,
1938 NULL, -1, NULL, -1,
1939 &fd, NULL, 10);
1940 if (!NT_STATUS_IS_OK(status)) {
1941 fd = -1;
1945 if ((fd == -1) &&
1946 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1948 /* This is the one place where we will
1949 set the global winbindd offline state
1950 to true, if a "WINBINDD_OFFLINE" entry
1951 is found in the winbindd cache. */
1952 set_global_winbindd_state_offline();
1953 break;
1955 if (dcname != NULL) {
1956 talloc_free(domain->dcname);
1958 domain->dcname = talloc_move(domain, &dcname);
1959 if (domain->dcname == NULL) {
1960 result = NT_STATUS_NO_MEMORY;
1961 break;
1965 new_conn->cli = NULL;
1967 result = cm_prepare_connection(domain, fd, domain->dcname,
1968 &new_conn->cli, &retry);
1969 if (!NT_STATUS_IS_OK(result)) {
1970 /* Don't leak the smb connection socket */
1971 close(fd);
1974 if (!retry)
1975 break;
1978 if (NT_STATUS_IS_OK(result)) {
1979 bool seal_pipes = true;
1981 winbindd_set_locator_kdc_envs(domain);
1983 if (domain->online == False) {
1984 /* We're changing state from offline to online. */
1985 set_global_winbindd_state_online();
1987 set_domain_online(domain);
1990 * Much as I hate global state, this seems to be the point
1991 * where we can be certain that we have a proper connection to
1992 * a DC. wbinfo --dc-info needs that information, store it in
1993 * gencache with a looong timeout. This will need revisiting
1994 * once we start to connect to multiple DCs, wbcDcInfo is
1995 * already prepared for that.
1997 store_current_dc_in_gencache(domain->name, domain->dcname,
1998 new_conn->cli);
2000 seal_pipes = lp_winbind_sealed_pipes();
2001 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2002 domain->name,
2003 seal_pipes);
2005 if (seal_pipes) {
2006 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2007 } else {
2008 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2010 } else {
2011 /* Ensure we setup the retry handler. */
2012 set_domain_offline(domain);
2015 talloc_destroy(mem_ctx);
2016 return result;
2019 /* Close down all open pipes on a connection. */
2021 void invalidate_cm_connection(struct winbindd_domain *domain)
2023 NTSTATUS result;
2024 struct winbindd_cm_conn *conn = &domain->conn;
2026 /* We're closing down a possibly dead
2027 connection. Don't have impossibly long (10s) timeouts. */
2029 if (conn->cli) {
2030 cli_set_timeout(conn->cli, 1000); /* 1 second. */
2033 if (conn->samr_pipe != NULL) {
2034 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
2035 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
2036 talloc_tos(),
2037 &conn->sam_connect_handle,
2038 &result);
2040 TALLOC_FREE(conn->samr_pipe);
2041 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2042 if (conn->cli) {
2043 cli_set_timeout(conn->cli, 500);
2047 if (conn->lsa_pipe != NULL) {
2048 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2049 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2050 talloc_tos(),
2051 &conn->lsa_policy,
2052 &result);
2054 TALLOC_FREE(conn->lsa_pipe);
2055 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2056 if (conn->cli) {
2057 cli_set_timeout(conn->cli, 500);
2061 if (conn->lsa_pipe_tcp != NULL) {
2062 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2063 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2064 talloc_tos(),
2065 &conn->lsa_policy,
2066 &result);
2068 TALLOC_FREE(conn->lsa_pipe_tcp);
2069 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2070 if (conn->cli) {
2071 cli_set_timeout(conn->cli, 500);
2075 if (conn->netlogon_pipe != NULL) {
2076 TALLOC_FREE(conn->netlogon_pipe);
2077 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2078 if (conn->cli) {
2079 cli_set_timeout(conn->cli, 500);
2083 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2084 TALLOC_FREE(conn->netlogon_creds_ctx);
2086 if (conn->cli) {
2087 cli_shutdown(conn->cli);
2090 conn->cli = NULL;
2093 void close_conns_after_fork(void)
2095 struct winbindd_domain *domain;
2096 struct winbindd_cli_state *cli_state;
2098 for (domain = domain_list(); domain; domain = domain->next) {
2100 * first close the low level SMB TCP connection
2101 * so that we don't generate any SMBclose
2102 * requests in invalidate_cm_connection()
2104 if (cli_state_is_connected(domain->conn.cli)) {
2105 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2108 invalidate_cm_connection(domain);
2111 for (cli_state = winbindd_client_list();
2112 cli_state != NULL;
2113 cli_state = cli_state->next) {
2114 if (cli_state->sock >= 0) {
2115 close(cli_state->sock);
2116 cli_state->sock = -1;
2121 static bool connection_ok(struct winbindd_domain *domain)
2123 bool ok;
2125 ok = cli_state_is_connected(domain->conn.cli);
2126 if (!ok) {
2127 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2128 domain->dcname, domain->name));
2129 return False;
2132 if (domain->online == False) {
2133 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2134 return False;
2137 return True;
2140 /* Initialize a new connection up to the RPC BIND.
2141 Bypass online status check so always does network calls. */
2143 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2145 NTSTATUS result;
2146 bool skip_connection = domain->internal;
2147 if (need_rw_dc && domain->rodc) {
2148 skip_connection = false;
2151 /* Internal connections never use the network. */
2152 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2153 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2156 /* Still ask the internal LSA and SAMR server about the local domain */
2157 if (skip_connection || connection_ok(domain)) {
2158 if (!domain->initialized) {
2159 set_dc_type_and_flags(domain);
2161 return NT_STATUS_OK;
2164 invalidate_cm_connection(domain);
2166 if (!domain->primary && !domain->initialized) {
2168 * Before we connect to a trust, work out if it is an
2169 * AD domain by asking our own domain.
2171 set_dc_type_and_flags_trustinfo(domain);
2174 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2176 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2177 set_dc_type_and_flags(domain);
2180 return result;
2183 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2185 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2186 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2189 if (domain->initialized && !domain->online) {
2190 /* We check for online status elsewhere. */
2191 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2194 return init_dc_connection_network(domain, need_rw_dc);
2197 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2199 NTSTATUS status;
2201 status = init_dc_connection(domain, need_rw_dc);
2202 if (!NT_STATUS_IS_OK(status)) {
2203 return status;
2206 if (!domain->internal && domain->conn.cli == NULL) {
2207 /* happens for trusted domains without inbound trust */
2208 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2211 return NT_STATUS_OK;
2214 /******************************************************************************
2215 Set the trust flags (direction and forest location) for a domain
2216 ******************************************************************************/
2218 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2220 struct winbindd_domain *our_domain;
2221 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2222 WERROR werr;
2223 struct netr_DomainTrustList trusts;
2224 int i;
2225 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2226 NETR_TRUST_FLAG_OUTBOUND |
2227 NETR_TRUST_FLAG_INBOUND);
2228 struct rpc_pipe_client *cli;
2229 TALLOC_CTX *mem_ctx = NULL;
2230 struct dcerpc_binding_handle *b;
2232 if (IS_DC) {
2234 * On a DC we loaded all trusts
2235 * from configuration and never learn
2236 * new domains.
2238 return true;
2241 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2243 /* Our primary domain doesn't need to worry about trust flags.
2244 Force it to go through the network setup */
2245 if ( domain->primary ) {
2246 return False;
2249 mem_ctx = talloc_stackframe();
2250 our_domain = find_our_domain();
2251 if (our_domain->internal) {
2252 result = init_dc_connection(our_domain, false);
2253 if (!NT_STATUS_IS_OK(result)) {
2254 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2255 "Not able to make a connection to our domain: %s\n",
2256 nt_errstr(result)));
2257 TALLOC_FREE(mem_ctx);
2258 return false;
2262 /* This won't work unless our domain is AD */
2263 if ( !our_domain->active_directory ) {
2264 TALLOC_FREE(mem_ctx);
2265 return False;
2268 if (our_domain->internal) {
2269 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2270 } else if (!connection_ok(our_domain)) {
2271 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2272 "No connection to our domain!\n"));
2273 TALLOC_FREE(mem_ctx);
2274 return False;
2275 } else {
2276 result = cm_connect_netlogon(our_domain, &cli);
2279 if (!NT_STATUS_IS_OK(result)) {
2280 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2281 "a connection to %s for PIPE_NETLOGON (%s)\n",
2282 domain->name, nt_errstr(result)));
2283 TALLOC_FREE(mem_ctx);
2284 return False;
2286 b = cli->binding_handle;
2288 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2289 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2290 cli->desthost,
2291 flags,
2292 &trusts,
2293 &werr);
2294 if (!NT_STATUS_IS_OK(result)) {
2295 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2296 "failed to query trusted domain list: %s\n",
2297 nt_errstr(result)));
2298 TALLOC_FREE(mem_ctx);
2299 return false;
2301 if (!W_ERROR_IS_OK(werr)) {
2302 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2303 "failed to query trusted domain list: %s\n",
2304 win_errstr(werr)));
2305 TALLOC_FREE(mem_ctx);
2306 return false;
2309 /* Now find the domain name and get the flags */
2311 for ( i=0; i<trusts.count; i++ ) {
2312 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2313 domain->domain_flags = trusts.array[i].trust_flags;
2314 domain->domain_type = trusts.array[i].trust_type;
2315 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2317 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2318 domain->active_directory = True;
2320 /* This flag is only set if the domain is *our*
2321 primary domain and the primary domain is in
2322 native mode */
2324 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2326 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2327 "native mode.\n", domain->name,
2328 domain->native_mode ? "" : "NOT "));
2330 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2331 "running active directory.\n", domain->name,
2332 domain->active_directory ? "" : "NOT "));
2334 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2336 domain->initialized = True;
2338 break;
2342 TALLOC_FREE(mem_ctx);
2344 return domain->initialized;
2347 /******************************************************************************
2348 We can 'sense' certain things about the DC by it's replies to certain
2349 questions.
2351 This tells us if this particular remote server is Active Directory, and if it
2352 is native mode.
2353 ******************************************************************************/
2355 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2357 NTSTATUS status, result;
2358 WERROR werr;
2359 TALLOC_CTX *mem_ctx = NULL;
2360 struct rpc_pipe_client *cli = NULL;
2361 struct policy_handle pol;
2362 union dssetup_DsRoleInfo info;
2363 union lsa_PolicyInformation *lsa_info = NULL;
2365 if (!domain->internal && !connection_ok(domain)) {
2366 return;
2369 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2370 domain->name);
2371 if (!mem_ctx) {
2372 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2373 return;
2376 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2378 if (domain->internal) {
2379 status = wb_open_internal_pipe(mem_ctx,
2380 &ndr_table_dssetup,
2381 &cli);
2382 } else {
2383 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2384 &ndr_table_dssetup,
2385 &cli);
2388 if (!NT_STATUS_IS_OK(status)) {
2389 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2390 "PI_DSSETUP on domain %s: (%s)\n",
2391 domain->name, nt_errstr(status)));
2393 /* if this is just a non-AD domain we need to continue
2394 * identifying so that we can in the end return with
2395 * domain->initialized = True - gd */
2397 goto no_dssetup;
2400 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2401 DS_ROLE_BASIC_INFORMATION,
2402 &info,
2403 &werr);
2404 TALLOC_FREE(cli);
2406 if (NT_STATUS_IS_OK(status)) {
2407 result = werror_to_ntstatus(werr);
2409 if (!NT_STATUS_IS_OK(status)) {
2410 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2411 "on domain %s failed: (%s)\n",
2412 domain->name, nt_errstr(status)));
2414 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2415 * every opcode on the DSSETUP pipe, continue with
2416 * no_dssetup mode here as well to get domain->initialized
2417 * set - gd */
2419 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2420 goto no_dssetup;
2423 TALLOC_FREE(mem_ctx);
2424 return;
2427 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2428 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2429 domain->native_mode = True;
2430 } else {
2431 domain->native_mode = False;
2434 no_dssetup:
2435 if (domain->internal) {
2436 status = wb_open_internal_pipe(mem_ctx,
2437 &ndr_table_lsarpc,
2438 &cli);
2439 } else {
2440 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2441 &ndr_table_lsarpc, &cli);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2445 "PI_LSARPC on domain %s: (%s)\n",
2446 domain->name, nt_errstr(status)));
2447 TALLOC_FREE(cli);
2448 TALLOC_FREE(mem_ctx);
2449 return;
2452 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2453 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2455 if (NT_STATUS_IS_OK(status)) {
2456 /* This particular query is exactly what Win2k clients use
2457 to determine that the DC is active directory */
2458 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2459 &pol,
2460 LSA_POLICY_INFO_DNS,
2461 &lsa_info,
2462 &result);
2465 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2466 domain->active_directory = True;
2468 if (lsa_info->dns.name.string) {
2469 if (!strequal(domain->name, lsa_info->dns.name.string))
2471 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2472 "for domain %s claimed it was a DC "
2473 "for domain %s, refusing to "
2474 "initialize\n",
2475 domain->name,
2476 lsa_info->dns.name.string));
2477 TALLOC_FREE(cli);
2478 TALLOC_FREE(mem_ctx);
2479 return;
2481 talloc_free(domain->name);
2482 domain->name = talloc_strdup(domain,
2483 lsa_info->dns.name.string);
2484 if (domain->name == NULL) {
2485 goto done;
2489 if (lsa_info->dns.dns_domain.string) {
2490 if (domain->alt_name != NULL &&
2491 !strequal(domain->alt_name,
2492 lsa_info->dns.dns_domain.string))
2494 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2495 "for domain %s (%s) claimed it was "
2496 "a DC for domain %s, refusing to "
2497 "initialize\n",
2498 domain->alt_name, domain->name,
2499 lsa_info->dns.dns_domain.string));
2500 TALLOC_FREE(cli);
2501 TALLOC_FREE(mem_ctx);
2502 return;
2504 talloc_free(domain->alt_name);
2505 domain->alt_name =
2506 talloc_strdup(domain,
2507 lsa_info->dns.dns_domain.string);
2508 if (domain->alt_name == NULL) {
2509 goto done;
2513 /* See if we can set some domain trust flags about
2514 ourself */
2516 if (lsa_info->dns.dns_forest.string) {
2517 talloc_free(domain->forest_name);
2518 domain->forest_name =
2519 talloc_strdup(domain,
2520 lsa_info->dns.dns_forest.string);
2521 if (domain->forest_name == NULL) {
2522 goto done;
2525 if (strequal(domain->forest_name, domain->alt_name)) {
2526 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2530 if (lsa_info->dns.sid) {
2531 if (!is_null_sid(&domain->sid) &&
2532 !dom_sid_equal(&domain->sid,
2533 lsa_info->dns.sid))
2535 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2536 "for domain %s (%s) claimed it was "
2537 "a DC for domain %s, refusing to "
2538 "initialize\n",
2539 dom_sid_string(talloc_tos(),
2540 &domain->sid),
2541 domain->name,
2542 dom_sid_string(talloc_tos(),
2543 lsa_info->dns.sid)));
2544 TALLOC_FREE(cli);
2545 TALLOC_FREE(mem_ctx);
2546 return;
2548 sid_copy(&domain->sid, lsa_info->dns.sid);
2550 } else {
2551 domain->active_directory = False;
2553 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2554 SEC_FLAG_MAXIMUM_ALLOWED,
2555 &pol);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 goto done;
2561 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2562 &pol,
2563 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2564 &lsa_info,
2565 &result);
2566 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2568 if (lsa_info->account_domain.name.string) {
2569 if (!strequal(domain->name,
2570 lsa_info->account_domain.name.string))
2572 DEBUG(1,
2573 ("set_dc_type_and_flags_connect: "
2574 "DC for domain %s claimed it was"
2575 " a DC for domain %s, refusing "
2576 "to initialize\n", domain->name,
2577 lsa_info->
2578 account_domain.name.string));
2579 TALLOC_FREE(cli);
2580 TALLOC_FREE(mem_ctx);
2581 return;
2583 talloc_free(domain->name);
2584 domain->name =
2585 talloc_strdup(domain,
2586 lsa_info->account_domain.name.string);
2589 if (lsa_info->account_domain.sid) {
2590 if (!is_null_sid(&domain->sid) &&
2591 !dom_sid_equal(&domain->sid,
2592 lsa_info->account_domain.sid))
2594 DEBUG(1,
2595 ("set_dc_type_and_flags_connect: "
2596 "DC for domain %s (%s) claimed "
2597 "it was a DC for domain %s, "
2598 "refusing to initialize\n",
2599 dom_sid_string(talloc_tos(),
2600 &domain->sid),
2601 domain->name,
2602 dom_sid_string(talloc_tos(),
2603 lsa_info->account_domain.sid)));
2604 TALLOC_FREE(cli);
2605 TALLOC_FREE(mem_ctx);
2606 return;
2608 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2612 done:
2614 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2615 domain->name, domain->native_mode ? "" : "NOT "));
2617 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2618 domain->name, domain->active_directory ? "" : "NOT "));
2620 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2622 TALLOC_FREE(cli);
2624 TALLOC_FREE(mem_ctx);
2626 domain->initialized = True;
2629 /**********************************************************************
2630 Set the domain_flags (trust attributes, domain operating modes, etc...
2631 ***********************************************************************/
2633 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2635 if (IS_DC) {
2637 * On a DC we loaded all trusts
2638 * from configuration and never learn
2639 * new domains.
2641 return;
2644 /* we always have to contact our primary domain */
2646 if ( domain->primary || domain->internal) {
2647 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2648 "primary or internal domain\n"));
2649 set_dc_type_and_flags_connect( domain );
2650 return;
2653 /* Use our DC to get the information if possible */
2655 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2656 /* Otherwise, fallback to contacting the
2657 domain directly */
2658 set_dc_type_and_flags_connect( domain );
2661 return;
2666 /**********************************************************************
2667 ***********************************************************************/
2669 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2670 struct netlogon_creds_cli_context **ppdc)
2672 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2673 struct rpc_pipe_client *netlogon_pipe;
2675 *ppdc = NULL;
2677 if ((!IS_DC) && (!domain->primary)) {
2678 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2681 if (domain->conn.netlogon_creds_ctx != NULL) {
2682 *ppdc = domain->conn.netlogon_creds_ctx;
2683 return NT_STATUS_OK;
2686 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2687 if (!NT_STATUS_IS_OK(result)) {
2688 return result;
2691 return NT_STATUS_OK;
2694 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2695 bool need_rw_dc,
2696 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2698 struct winbindd_cm_conn *conn;
2699 NTSTATUS status, result;
2700 struct netlogon_creds_cli_context *p_creds;
2701 struct cli_credentials *creds = NULL;
2702 bool retry = false; /* allow one retry attempt for expired session */
2704 if (sid_check_is_our_sam(&domain->sid)) {
2705 if (domain->rodc == false || need_rw_dc == false) {
2706 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2710 if (IS_AD_DC) {
2712 * In theory we should not use SAMR within
2713 * winbindd at all, but that's a larger task to
2714 * remove this and avoid breaking existing
2715 * setups.
2717 * At least as AD DC we have the restriction
2718 * to avoid SAMR against trusted domains,
2719 * as there're no existing setups.
2721 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2724 retry:
2725 status = init_dc_connection_rpc(domain, need_rw_dc);
2726 if (!NT_STATUS_IS_OK(status)) {
2727 return status;
2730 conn = &domain->conn;
2732 if (rpccli_is_connected(conn->samr_pipe)) {
2733 goto done;
2736 TALLOC_FREE(conn->samr_pipe);
2739 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2740 * sign and sealed pipe using the machine account password by
2741 * preference. If we can't - try schannel, if that fails, try
2742 * anonymous.
2745 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2746 if (!NT_STATUS_IS_OK(result)) {
2747 DEBUG(10, ("cm_connect_sam: No user available for "
2748 "domain %s, trying schannel\n", domain->name));
2749 goto schannel;
2752 if (cli_credentials_is_anonymous(creds)) {
2753 goto anonymous;
2757 * We have an authenticated connection. Use a SPNEGO
2758 * authenticated SAMR pipe with sign & seal.
2760 status = cli_rpc_pipe_open_with_creds(conn->cli,
2761 &ndr_table_samr,
2762 NCACN_NP,
2763 DCERPC_AUTH_TYPE_SPNEGO,
2764 conn->auth_level,
2765 smbXcli_conn_remote_name(conn->cli->conn),
2766 creds,
2767 &conn->samr_pipe);
2769 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2770 && !retry) {
2771 invalidate_cm_connection(domain);
2772 retry = true;
2773 goto retry;
2776 if (!NT_STATUS_IS_OK(status)) {
2777 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2778 "pipe for domain %s using NTLMSSP "
2779 "authenticated pipe: user %s. Error was "
2780 "%s\n", domain->name,
2781 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2782 nt_errstr(status)));
2783 goto schannel;
2786 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2787 "domain %s using NTLMSSP authenticated "
2788 "pipe: user %s\n", domain->name,
2789 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2791 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2792 conn->samr_pipe->desthost,
2793 SEC_FLAG_MAXIMUM_ALLOWED,
2794 &conn->sam_connect_handle,
2795 &result);
2797 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2798 invalidate_cm_connection(domain);
2799 TALLOC_FREE(conn->samr_pipe);
2800 retry = true;
2801 goto retry;
2804 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2805 goto open_domain;
2807 if (NT_STATUS_IS_OK(status)) {
2808 status = result;
2811 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2812 "failed for domain %s, error was %s. Trying schannel\n",
2813 domain->name, nt_errstr(status) ));
2814 TALLOC_FREE(conn->samr_pipe);
2816 schannel:
2818 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2820 status = cm_get_schannel_creds(domain, &p_creds);
2821 if (!NT_STATUS_IS_OK(status)) {
2822 /* If this call fails - conn->cli can now be NULL ! */
2823 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2824 "for domain %s (error %s), trying anon\n",
2825 domain->name,
2826 nt_errstr(status) ));
2827 goto anonymous;
2829 TALLOC_FREE(creds);
2830 status = cli_rpc_pipe_open_schannel_with_creds(
2831 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2832 &conn->samr_pipe);
2834 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2835 && !retry) {
2836 invalidate_cm_connection(domain);
2837 retry = true;
2838 goto retry;
2841 if (!NT_STATUS_IS_OK(status)) {
2842 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2843 "domain %s using schannel. Error was %s\n",
2844 domain->name, nt_errstr(status) ));
2845 goto anonymous;
2847 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2848 "schannel.\n", domain->name ));
2850 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2851 conn->samr_pipe->desthost,
2852 SEC_FLAG_MAXIMUM_ALLOWED,
2853 &conn->sam_connect_handle,
2854 &result);
2856 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2857 invalidate_cm_connection(domain);
2858 TALLOC_FREE(conn->samr_pipe);
2859 retry = true;
2860 goto retry;
2863 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2864 goto open_domain;
2866 if (NT_STATUS_IS_OK(status)) {
2867 status = result;
2869 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2870 "for domain %s, error was %s. Trying anonymous\n",
2871 domain->name, nt_errstr(status) ));
2872 TALLOC_FREE(conn->samr_pipe);
2874 anonymous:
2876 /* Finally fall back to anonymous. */
2877 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2878 status = NT_STATUS_DOWNGRADE_DETECTED;
2879 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2880 "without connection level security, "
2881 "must set 'winbind sealed pipes = false' and "
2882 "'require strong key = false' to proceed: %s\n",
2883 domain->name, nt_errstr(status)));
2884 goto done;
2886 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2887 &conn->samr_pipe);
2889 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2890 && !retry) {
2891 invalidate_cm_connection(domain);
2892 retry = true;
2893 goto retry;
2896 if (!NT_STATUS_IS_OK(status)) {
2897 goto done;
2900 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2901 conn->samr_pipe->desthost,
2902 SEC_FLAG_MAXIMUM_ALLOWED,
2903 &conn->sam_connect_handle,
2904 &result);
2906 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2907 invalidate_cm_connection(domain);
2908 TALLOC_FREE(conn->samr_pipe);
2909 retry = true;
2910 goto retry;
2913 if (!NT_STATUS_IS_OK(status)) {
2914 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2915 "for domain %s Error was %s\n",
2916 domain->name, nt_errstr(status) ));
2917 goto done;
2919 if (!NT_STATUS_IS_OK(result)) {
2920 status = result;
2921 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2922 "for domain %s Error was %s\n",
2923 domain->name, nt_errstr(result)));
2924 goto done;
2927 open_domain:
2928 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2929 mem_ctx,
2930 &conn->sam_connect_handle,
2931 SEC_FLAG_MAXIMUM_ALLOWED,
2932 &domain->sid,
2933 &conn->sam_domain_handle,
2934 &result);
2935 if (!NT_STATUS_IS_OK(status)) {
2936 goto done;
2939 status = result;
2940 done:
2942 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2944 * if we got access denied, we might just have no access rights
2945 * to talk to the remote samr server server (e.g. when we are a
2946 * PDC and we are connecting a w2k8 pdc via an interdomain
2947 * trust). In that case do not invalidate the whole connection
2948 * stack
2950 TALLOC_FREE(conn->samr_pipe);
2951 ZERO_STRUCT(conn->sam_domain_handle);
2952 return status;
2953 } else if (!NT_STATUS_IS_OK(status)) {
2954 invalidate_cm_connection(domain);
2955 return status;
2958 *cli = conn->samr_pipe;
2959 *sam_handle = conn->sam_domain_handle;
2960 return status;
2963 /**********************************************************************
2964 open an schanneld ncacn_ip_tcp connection to LSA
2965 ***********************************************************************/
2967 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2968 TALLOC_CTX *mem_ctx,
2969 struct rpc_pipe_client **cli)
2971 struct winbindd_cm_conn *conn;
2972 struct netlogon_creds_cli_context *p_creds = NULL;
2973 NTSTATUS status;
2975 DEBUG(10,("cm_connect_lsa_tcp\n"));
2977 status = init_dc_connection_rpc(domain, false);
2978 if (!NT_STATUS_IS_OK(status)) {
2979 return status;
2982 conn = &domain->conn;
2985 * rpccli_is_connected handles more error cases
2987 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2988 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2989 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2990 goto done;
2993 TALLOC_FREE(conn->lsa_pipe_tcp);
2995 status = cm_get_schannel_creds(domain, &p_creds);
2996 if (!NT_STATUS_IS_OK(status)) {
2997 goto done;
3000 status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
3001 &ndr_table_lsarpc,
3002 NCACN_IP_TCP,
3003 p_creds,
3004 &conn->lsa_pipe_tcp);
3005 if (!NT_STATUS_IS_OK(status)) {
3006 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
3007 nt_errstr(status)));
3008 goto done;
3011 done:
3012 if (!NT_STATUS_IS_OK(status)) {
3013 TALLOC_FREE(conn->lsa_pipe_tcp);
3014 return status;
3017 *cli = conn->lsa_pipe_tcp;
3019 return status;
3022 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
3023 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
3025 struct winbindd_cm_conn *conn;
3026 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
3027 struct netlogon_creds_cli_context *p_creds;
3028 struct cli_credentials *creds = NULL;
3029 bool retry = false; /* allow one retry attempt for expired session */
3031 retry:
3032 result = init_dc_connection_rpc(domain, false);
3033 if (!NT_STATUS_IS_OK(result))
3034 return result;
3036 conn = &domain->conn;
3038 if (rpccli_is_connected(conn->lsa_pipe)) {
3039 goto done;
3042 TALLOC_FREE(conn->lsa_pipe);
3044 if (IS_AD_DC) {
3046 * Make sure we only use schannel as AD DC.
3048 goto schannel;
3051 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
3052 if (!NT_STATUS_IS_OK(result)) {
3053 DEBUG(10, ("cm_connect_lsa: No user available for "
3054 "domain %s, trying schannel\n", domain->name));
3055 goto schannel;
3058 if (cli_credentials_is_anonymous(creds)) {
3059 goto anonymous;
3063 * We have an authenticated connection. Use a SPNEGO
3064 * authenticated LSA pipe with sign & seal.
3066 result = cli_rpc_pipe_open_with_creds
3067 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
3068 DCERPC_AUTH_TYPE_SPNEGO,
3069 conn->auth_level,
3070 smbXcli_conn_remote_name(conn->cli->conn),
3071 creds,
3072 &conn->lsa_pipe);
3074 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3075 && !retry) {
3076 invalidate_cm_connection(domain);
3077 retry = true;
3078 goto retry;
3081 if (!NT_STATUS_IS_OK(result)) {
3082 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3083 "domain %s using NTLMSSP authenticated pipe: user "
3084 "%s. Error was %s. Trying schannel.\n",
3085 domain->name,
3086 cli_credentials_get_unparsed_name(creds, talloc_tos()),
3087 nt_errstr(result)));
3088 goto schannel;
3091 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3092 "NTLMSSP authenticated pipe: user %s\n",
3093 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3095 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3096 SEC_FLAG_MAXIMUM_ALLOWED,
3097 &conn->lsa_policy);
3098 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3099 invalidate_cm_connection(domain);
3100 TALLOC_FREE(conn->lsa_pipe);
3101 retry = true;
3102 goto retry;
3105 if (NT_STATUS_IS_OK(result)) {
3106 goto done;
3109 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3110 "schannel\n"));
3112 TALLOC_FREE(conn->lsa_pipe);
3114 schannel:
3116 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3118 result = cm_get_schannel_creds(domain, &p_creds);
3119 if (!NT_STATUS_IS_OK(result)) {
3120 /* If this call fails - conn->cli can now be NULL ! */
3121 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3122 "for domain %s (error %s), trying anon\n",
3123 domain->name,
3124 nt_errstr(result) ));
3125 goto anonymous;
3128 TALLOC_FREE(creds);
3129 result = cli_rpc_pipe_open_schannel_with_creds(
3130 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3131 &conn->lsa_pipe);
3133 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3134 && !retry) {
3135 invalidate_cm_connection(domain);
3136 retry = true;
3137 goto retry;
3140 if (!NT_STATUS_IS_OK(result)) {
3141 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3142 "domain %s using schannel. Error was %s\n",
3143 domain->name, nt_errstr(result) ));
3144 goto anonymous;
3146 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3147 "schannel.\n", domain->name ));
3149 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3150 SEC_FLAG_MAXIMUM_ALLOWED,
3151 &conn->lsa_policy);
3153 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3154 invalidate_cm_connection(domain);
3155 TALLOC_FREE(conn->lsa_pipe);
3156 retry = true;
3157 goto retry;
3160 if (NT_STATUS_IS_OK(result)) {
3161 goto done;
3164 if (IS_AD_DC) {
3166 * Make sure we only use schannel as AD DC.
3168 goto done;
3171 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3172 "anonymous\n"));
3174 TALLOC_FREE(conn->lsa_pipe);
3176 anonymous:
3178 if (IS_AD_DC) {
3180 * Make sure we only use schannel as AD DC.
3182 goto done;
3185 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3186 result = NT_STATUS_DOWNGRADE_DETECTED;
3187 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3188 "without connection level security, "
3189 "must set 'winbind sealed pipes = false' and "
3190 "'require strong key = false' to proceed: %s\n",
3191 domain->name, nt_errstr(result)));
3192 goto done;
3195 result = cli_rpc_pipe_open_noauth(conn->cli,
3196 &ndr_table_lsarpc,
3197 &conn->lsa_pipe);
3199 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3200 && !retry) {
3201 invalidate_cm_connection(domain);
3202 retry = true;
3203 goto retry;
3206 if (!NT_STATUS_IS_OK(result)) {
3207 goto done;
3210 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3211 SEC_FLAG_MAXIMUM_ALLOWED,
3212 &conn->lsa_policy);
3214 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3215 invalidate_cm_connection(domain);
3216 TALLOC_FREE(conn->lsa_pipe);
3217 retry = true;
3218 goto retry;
3221 done:
3222 if (!NT_STATUS_IS_OK(result)) {
3223 invalidate_cm_connection(domain);
3224 return result;
3227 *cli = conn->lsa_pipe;
3228 *lsa_policy = conn->lsa_policy;
3229 return result;
3232 /****************************************************************************
3233 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3234 ****************************************************************************/
3236 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3237 TALLOC_CTX *mem_ctx,
3238 struct rpc_pipe_client **cli,
3239 struct policy_handle *lsa_policy)
3241 NTSTATUS status;
3243 if (domain->can_do_ncacn_ip_tcp) {
3244 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3245 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3246 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3247 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3248 invalidate_cm_connection(domain);
3249 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3251 if (NT_STATUS_IS_OK(status)) {
3252 return status;
3256 * we tried twice to connect via ncan_ip_tcp and schannel and
3257 * failed - maybe it is a trusted domain we can't connect to ?
3258 * do not try tcp next time - gd
3260 * This also prevents NETLOGON over TCP
3262 domain->can_do_ncacn_ip_tcp = false;
3265 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3267 return status;
3270 /****************************************************************************
3271 Open the netlogon pipe to this DC.
3272 ****************************************************************************/
3274 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3275 enum dcerpc_transport_t transport,
3276 struct rpc_pipe_client **cli)
3278 struct messaging_context *msg_ctx = server_messaging_context();
3279 struct winbindd_cm_conn *conn;
3280 NTSTATUS result;
3281 enum netr_SchannelType sec_chan_type;
3282 struct cli_credentials *creds = NULL;
3284 *cli = NULL;
3286 if (IS_AD_DC) {
3287 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3289 * Make sure we don't even try to
3290 * connect to a foreign domain
3291 * without a direct outbound trust.
3293 return NT_STATUS_NO_TRUST_LSA_SECRET;
3297 result = init_dc_connection_rpc(domain, domain->rodc);
3298 if (!NT_STATUS_IS_OK(result)) {
3299 return result;
3302 conn = &domain->conn;
3304 if (rpccli_is_connected(conn->netlogon_pipe)) {
3305 *cli = conn->netlogon_pipe;
3306 return NT_STATUS_OK;
3309 TALLOC_FREE(conn->netlogon_pipe);
3310 TALLOC_FREE(conn->netlogon_creds_ctx);
3312 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3313 if (!NT_STATUS_IS_OK(result)) {
3314 DBG_DEBUG("No user available for domain %s when trying "
3315 "schannel\n", domain->name);
3316 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3319 if (cli_credentials_is_anonymous(creds)) {
3320 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3321 "unable to make get NETLOGON credentials\n",
3322 domain->name);
3323 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3326 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3327 if (sec_chan_type == SEC_CHAN_NULL) {
3328 if (transport == NCACN_IP_TCP) {
3329 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3330 "for %s, deny NCACN_IP_TCP and let the "
3331 "caller fallback to NCACN_NP.\n",
3332 domain->name);
3333 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3336 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3337 "fallback to noauth on NCACN_NP.\n",
3338 domain->name);
3340 result = cli_rpc_pipe_open_noauth_transport(
3341 conn->cli,
3342 transport,
3343 &ndr_table_netlogon,
3344 &conn->netlogon_pipe);
3345 if (!NT_STATUS_IS_OK(result)) {
3346 invalidate_cm_connection(domain);
3347 return result;
3350 *cli = conn->netlogon_pipe;
3351 return NT_STATUS_OK;
3354 result = rpccli_create_netlogon_creds_ctx(creds,
3355 domain->dcname,
3356 msg_ctx,
3357 domain,
3358 &conn->netlogon_creds_ctx);
3359 if (!NT_STATUS_IS_OK(result)) {
3360 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3361 "unable to create NETLOGON credentials: %s\n",
3362 domain->name, nt_errstr(result)));
3363 return result;
3366 result = rpccli_connect_netlogon(
3367 conn->cli, transport,
3368 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3369 &conn->netlogon_pipe);
3370 conn->netlogon_force_reauth = false;
3371 if (!NT_STATUS_IS_OK(result)) {
3372 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3373 nt_errstr(result));
3374 return result;
3377 *cli = conn->netlogon_pipe;
3378 return NT_STATUS_OK;
3381 /****************************************************************************
3382 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3383 ****************************************************************************/
3385 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3386 struct rpc_pipe_client **cli)
3388 NTSTATUS status;
3390 status = init_dc_connection_rpc(domain, domain->rodc);
3391 if (!NT_STATUS_IS_OK(status)) {
3392 return status;
3395 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3396 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3397 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3398 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3399 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3400 invalidate_cm_connection(domain);
3401 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3403 if (NT_STATUS_IS_OK(status)) {
3404 return status;
3408 * we tried twice to connect via ncan_ip_tcp and schannel and
3409 * failed - maybe it is a trusted domain we can't connect to ?
3410 * do not try tcp next time - gd
3412 * This also prevents LSA over TCP
3414 domain->can_do_ncacn_ip_tcp = false;
3417 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3418 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3420 * SMB2 session expired, needs reauthentication. Drop
3421 * connection and retry.
3423 invalidate_cm_connection(domain);
3424 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3427 return status;
3430 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3431 struct rpc_pipe_client **cli,
3432 struct netlogon_creds_cli_context **ppdc)
3434 NTSTATUS status;
3436 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3437 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3440 status = cm_connect_netlogon(domain, cli);
3441 if (!NT_STATUS_IS_OK(status)) {
3442 return status;
3445 if (domain->conn.netlogon_creds_ctx == NULL) {
3446 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3449 *ppdc = domain->conn.netlogon_creds_ctx;
3450 return NT_STATUS_OK;
3453 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3454 void *private_data,
3455 uint32_t msg_type,
3456 struct server_id server_id,
3457 DATA_BLOB *data)
3459 struct winbindd_domain *domain;
3460 char *freeit = NULL;
3461 char *addr;
3463 if ((data == NULL)
3464 || (data->data == NULL)
3465 || (data->length == 0)
3466 || (data->data[data->length-1] != '\0')) {
3467 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3468 "string\n"));
3469 return;
3472 addr = (char *)data->data;
3473 DEBUG(10, ("IP %s dropped\n", addr));
3475 if (!is_ipaddress(addr)) {
3476 char *slash;
3478 * Some code sends us ip addresses with the /netmask
3479 * suffix
3481 slash = strchr(addr, '/');
3482 if (slash == NULL) {
3483 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3484 addr));
3485 return;
3487 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3488 if (freeit == NULL) {
3489 DEBUG(1, ("talloc failed\n"));
3490 return;
3492 addr = freeit;
3493 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3496 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3497 char sockaddr[INET6_ADDRSTRLEN];
3499 if (!cli_state_is_connected(domain->conn.cli)) {
3500 continue;
3503 print_sockaddr(sockaddr, sizeof(sockaddr),
3504 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3506 if (strequal(sockaddr, addr)) {
3507 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3510 TALLOC_FREE(freeit);
3513 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3514 void *private_data,
3515 uint32_t msg_type,
3516 struct server_id server_id,
3517 DATA_BLOB *data)
3519 struct winbindd_domain *domain;
3521 for (domain = domain_list(); domain; domain = domain->next) {
3522 if (domain->internal) {
3523 continue;
3525 invalidate_cm_connection(domain);