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
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
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
63 #include "libsmb/namequery.h"
64 #include "../libcli/auth/libcli_auth.h"
65 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
66 #include "rpc_client/cli_pipe.h"
67 #include "rpc_client/cli_netlogon.h"
68 #include "../librpc/gen_ndr/ndr_samr_c.h"
69 #include "../librpc/gen_ndr/ndr_lsa_c.h"
70 #include "rpc_client/cli_lsarpc.h"
71 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
72 #include "libads/sitename_cache.h"
73 #include "libsmb/libsmb.h"
74 #include "libsmb/clidgram.h"
77 #include "../libcli/security/security.h"
80 #include "auth/gensec/gensec.h"
81 #include "../libcli/smb/smbXcli_base.h"
82 #include "libcli/auth/netlogon_creds_cli.h"
84 #include "rpc_server/rpc_ncacn_np.h"
85 #include "auth/credentials/credentials.h"
86 #include "lib/param/param.h"
87 #include "lib/gencache.h"
90 #define DBGC_CLASS DBGC_WINBIND
94 struct sockaddr_storage ss
;
97 extern struct winbindd_methods reconnect_methods
;
98 extern bool override_logfile
;
100 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
, bool need_rw_dc
);
101 static void set_dc_type_and_flags( struct winbindd_domain
*domain
);
102 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain
*domain
);
103 static bool get_dcs(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
104 struct dc_name_ip
**dcs
, int *num_dcs
,
105 uint32_t request_flags
);
107 /****************************************************************
108 Child failed to find DC's. Reschedule check.
109 ****************************************************************/
111 static void msg_failed_to_go_online(struct messaging_context
*msg
,
114 struct server_id server_id
,
117 struct winbindd_domain
*domain
;
118 const char *domainname
= (const char *)data
->data
;
120 if (data
->data
== NULL
|| data
->length
== 0) {
124 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname
));
126 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
127 if (domain
->internal
) {
131 if (strequal(domain
->name
, domainname
)) {
132 if (domain
->online
) {
133 /* We're already online, ignore. */
134 DEBUG(5,("msg_fail_to_go_online: domain %s "
135 "already online.\n", domainname
));
139 /* Reschedule the online check. */
140 set_domain_offline(domain
);
146 /****************************************************************
147 Actually cause a reconnect from a message.
148 ****************************************************************/
150 static void msg_try_to_go_online(struct messaging_context
*msg
,
153 struct server_id server_id
,
156 struct winbindd_domain
*domain
;
157 const char *domainname
= (const char *)data
->data
;
159 if (data
->data
== NULL
|| data
->length
== 0) {
163 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname
));
165 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
166 if (domain
->internal
) {
170 if (strequal(domain
->name
, domainname
)) {
172 if (domain
->online
) {
173 /* We're already online, ignore. */
174 DEBUG(5,("msg_try_to_go_online: domain %s "
175 "already online.\n", domainname
));
179 /* This call takes care of setting the online
180 flag to true if we connected, or re-adding
181 the offline handler if false. Bypasses online
182 check so always does network calls. */
184 init_dc_connection_network(domain
, true);
190 /****************************************************************
191 Fork a child to try and contact a DC. Do this as contacting a
192 DC requires blocking lookups and we don't want to block our
194 ****************************************************************/
196 static bool fork_child_dc_connect(struct winbindd_domain
*domain
)
198 struct dc_name_ip
*dcs
= NULL
;
200 TALLOC_CTX
*mem_ctx
= NULL
;
201 pid_t parent_pid
= getpid();
206 if (domain
->dc_probe_pid
!= (pid_t
)-1) {
208 * We might already have a DC probe
209 * child working, check.
211 if (process_exists_by_pid(domain
->dc_probe_pid
)) {
212 DEBUG(10,("fork_child_dc_connect: pid %u already "
213 "checking for DC's.\n",
214 (unsigned int)domain
->dc_probe_pid
));
217 domain
->dc_probe_pid
= (pid_t
)-1;
220 domain
->dc_probe_pid
= fork();
222 if (domain
->dc_probe_pid
== (pid_t
)-1) {
223 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno
)));
227 if (domain
->dc_probe_pid
!= (pid_t
)0) {
229 messaging_register(global_messaging_context(), NULL
,
230 MSG_WINBIND_TRY_TO_GO_ONLINE
,
231 msg_try_to_go_online
);
232 messaging_register(global_messaging_context(), NULL
,
233 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
234 msg_failed_to_go_online
);
240 /* Leave messages blocked - we will never process one. */
242 if (!override_logfile
) {
243 if (asprintf(&lfile
, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
244 DBG_ERR("fork_child_dc_connect: "
245 "out of memory in asprintf().\n");
250 status
= winbindd_reinit_after_fork(NULL
, lfile
);
251 if (!NT_STATUS_IS_OK(status
)) {
252 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
254 messaging_send_buf(global_messaging_context(),
255 pid_to_procid(parent_pid
),
256 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
257 (const uint8_t *)domain
->name
,
258 strlen(domain
->name
)+1);
263 setproctitle("dc-connect child");
265 mem_ctx
= talloc_init("fork_child_dc_connect");
267 DEBUG(0,("talloc_init failed.\n"));
268 messaging_send_buf(global_messaging_context(),
269 pid_to_procid(parent_pid
),
270 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
271 (const uint8_t *)domain
->name
,
272 strlen(domain
->name
)+1);
276 ok
= get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
, 0);
277 TALLOC_FREE(mem_ctx
);
278 if (!ok
|| (num_dcs
== 0)) {
279 /* Still offline ? Can't find DC's. */
280 messaging_send_buf(global_messaging_context(),
281 pid_to_procid(parent_pid
),
282 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
283 (const uint8_t *)domain
->name
,
284 strlen(domain
->name
)+1);
288 /* We got a DC. Send a message to our parent to get it to
289 try and do the same. */
291 messaging_send_buf(global_messaging_context(),
292 pid_to_procid(parent_pid
),
293 MSG_WINBIND_TRY_TO_GO_ONLINE
,
294 (const uint8_t *)domain
->name
,
295 strlen(domain
->name
)+1);
299 /****************************************************************
300 Handler triggered if we're offline to try and detect a DC.
301 ****************************************************************/
303 static void check_domain_online_handler(struct tevent_context
*ctx
,
304 struct tevent_timer
*te
,
308 struct winbindd_domain
*domain
=
309 (struct winbindd_domain
*)private_data
;
311 DEBUG(10,("check_domain_online_handler: called for domain "
312 "%s (online = %s)\n", domain
->name
,
313 domain
->online
? "True" : "False" ));
315 TALLOC_FREE(domain
->check_online_event
);
317 /* Are we still in "startup" mode ? */
319 if (domain
->startup
&& (time_mono(NULL
) > domain
->startup_time
+ 30)) {
320 /* No longer in "startup" mode. */
321 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
323 domain
->startup
= False
;
326 /* We've been told to stay offline, so stay
329 if (get_global_winbindd_state_offline()) {
330 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
335 /* Fork a child to test if it can contact a DC.
336 If it can then send ourselves a message to
337 cause a reconnect. */
339 fork_child_dc_connect(domain
);
342 /****************************************************************
343 If we're still offline setup the timeout check.
344 ****************************************************************/
346 static void calc_new_online_timeout_check(struct winbindd_domain
*domain
)
348 int wbr
= lp_winbind_reconnect_delay();
350 if (domain
->startup
) {
351 domain
->check_online_timeout
= 10;
352 } else if (domain
->check_online_timeout
< wbr
) {
353 domain
->check_online_timeout
= wbr
;
357 void winbind_msg_domain_offline(struct messaging_context
*msg_ctx
,
360 struct server_id server_id
,
363 const char *domain_name
= (const char *)data
->data
;
364 struct winbindd_domain
*domain
;
366 domain
= find_domain_from_name_noinit(domain_name
);
367 if (domain
== NULL
) {
371 domain
->online
= false;
373 DEBUG(10, ("Domain %s is marked as offline now.\n",
377 void winbind_msg_domain_online(struct messaging_context
*msg_ctx
,
380 struct server_id server_id
,
383 const char *domain_name
= (const char *)data
->data
;
384 struct winbindd_domain
*domain
;
386 domain
= find_domain_from_name_noinit(domain_name
);
387 if (domain
== NULL
) {
391 domain
->online
= true;
393 DEBUG(10, ("Domain %s is marked as online now.\n",
397 /****************************************************************
398 Set domain offline and also add handler to put us back online
400 ****************************************************************/
402 void set_domain_offline(struct winbindd_domain
*domain
)
404 pid_t parent_pid
= getppid();
406 DEBUG(10,("set_domain_offline: called for domain %s\n",
409 TALLOC_FREE(domain
->check_online_event
);
411 if (domain
->internal
) {
412 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
417 domain
->online
= False
;
419 /* Offline domains are always initialized. They're
420 re-initialized when they go back online. */
422 domain
->initialized
= True
;
424 /* We only add the timeout handler that checks and
425 allows us to go back online when we've not
426 been told to remain offline. */
428 if (get_global_winbindd_state_offline()) {
429 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
434 /* If we're in startup mode, check again in 10 seconds, not in
435 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
437 calc_new_online_timeout_check(domain
);
439 domain
->check_online_event
= tevent_add_timer(global_event_context(),
441 timeval_current_ofs(domain
->check_online_timeout
,0),
442 check_domain_online_handler
,
445 /* The above *has* to succeed for winbindd to work. */
446 if (!domain
->check_online_event
) {
447 smb_panic("set_domain_offline: failed to add online handler");
450 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
453 /* Send a message to the parent that the domain is offline. */
454 if (parent_pid
> 1 && !domain
->internal
) {
455 messaging_send_buf(global_messaging_context(),
456 pid_to_procid(parent_pid
),
457 MSG_WINBIND_DOMAIN_OFFLINE
,
458 (uint8_t *)domain
->name
,
459 strlen(domain
->name
) + 1);
462 /* Send an offline message to the idmap child when our
463 primary domain goes offline */
465 if ( domain
->primary
) {
466 struct winbindd_child
*idmap
= idmap_child();
468 if ( idmap
->pid
!= 0 ) {
469 messaging_send_buf(global_messaging_context(),
470 pid_to_procid(idmap
->pid
),
472 (const uint8_t *)domain
->name
,
473 strlen(domain
->name
)+1);
480 /****************************************************************
481 Set domain online - if allowed.
482 ****************************************************************/
484 static void set_domain_online(struct winbindd_domain
*domain
)
486 pid_t parent_pid
= getppid();
488 DEBUG(10,("set_domain_online: called for domain %s\n",
491 if (domain
->internal
) {
492 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
497 if (get_global_winbindd_state_offline()) {
498 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
503 winbindd_set_locator_kdc_envs(domain
);
505 /* If we are waiting to get a krb5 ticket, trigger immediately. */
506 ccache_regain_all_now();
508 /* Ok, we're out of any startup mode now... */
509 domain
->startup
= False
;
511 if (domain
->online
== False
) {
512 /* We were offline - now we're online. We default to
513 using the MS-RPC backend if we started offline,
514 and if we're going online for the first time we
515 should really re-initialize the backends and the
516 checks to see if we're talking to an AD or NT domain.
519 domain
->initialized
= False
;
521 /* 'reconnect_methods' is the MS-RPC backend. */
522 if (domain
->backend
== &reconnect_methods
) {
523 domain
->backend
= NULL
;
527 /* Ensure we have no online timeout checks. */
528 domain
->check_online_timeout
= 0;
529 TALLOC_FREE(domain
->check_online_event
);
531 /* Ensure we ignore any pending child messages. */
532 messaging_deregister(global_messaging_context(),
533 MSG_WINBIND_TRY_TO_GO_ONLINE
, NULL
);
534 messaging_deregister(global_messaging_context(),
535 MSG_WINBIND_FAILED_TO_GO_ONLINE
, NULL
);
537 domain
->online
= True
;
539 /* Send a message to the parent that the domain is online. */
540 if (parent_pid
> 1 && !domain
->internal
) {
541 messaging_send_buf(global_messaging_context(),
542 pid_to_procid(parent_pid
),
543 MSG_WINBIND_DOMAIN_ONLINE
,
544 (uint8_t *)domain
->name
,
545 strlen(domain
->name
) + 1);
548 /* Send an online message to the idmap child when our
549 primary domain comes online */
551 if ( domain
->primary
) {
552 struct winbindd_child
*idmap
= idmap_child();
554 if ( idmap
->pid
!= 0 ) {
555 messaging_send_buf(global_messaging_context(),
556 pid_to_procid(idmap
->pid
),
558 (const uint8_t *)domain
->name
,
559 strlen(domain
->name
)+1);
566 /****************************************************************
567 Requested to set a domain online.
568 ****************************************************************/
570 void set_domain_online_request(struct winbindd_domain
*domain
)
574 DEBUG(10,("set_domain_online_request: called for domain %s\n",
577 if (get_global_winbindd_state_offline()) {
578 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
583 if (domain
->internal
) {
584 DEBUG(10, ("set_domain_online_request: Internal domains are "
589 /* We've been told it's safe to go online and
590 try and connect to a DC. But I don't believe it
591 because network manager seems to lie.
592 Wait at least 5 seconds. Heuristics suck... */
597 /* Go into "startup" mode again. */
598 domain
->startup_time
= time_mono(NULL
);
599 domain
->startup
= True
;
603 if (!domain
->check_online_event
) {
604 /* If we've come from being globally offline we
605 don't have a check online event handler set.
606 We need to add one now we're trying to go
609 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
613 TALLOC_FREE(domain
->check_online_event
);
615 domain
->check_online_event
= tevent_add_timer(global_event_context(),
618 check_domain_online_handler
,
621 /* The above *has* to succeed for winbindd to work. */
622 if (!domain
->check_online_event
) {
623 smb_panic("set_domain_online_request: failed to add online handler");
627 /****************************************************************
628 Add -ve connection cache entries for domain and realm.
629 ****************************************************************/
631 static void winbind_add_failed_connection_entry(
632 const struct winbindd_domain
*domain
,
636 add_failed_connection_entry(domain
->name
, server
, result
);
637 /* If this was the saf name for the last thing we talked to,
639 saf_delete(domain
->name
);
640 if (domain
->alt_name
!= NULL
) {
641 add_failed_connection_entry(domain
->alt_name
, server
, result
);
642 saf_delete(domain
->alt_name
);
644 winbindd_unset_locator_kdc_env(domain
);
647 /* Choose between anonymous or authenticated connections. We need to use
648 an authenticated connection if DCs have the RestrictAnonymous registry
649 entry set > 0, or the "Additional restrictions for anonymous
650 connections" set in the win2k Local Security Policy.
652 Caller to free() result in domain, username, password
655 static void cm_get_ipc_userpass(char **username
, char **domain
, char **password
)
657 *username
= (char *)secrets_fetch(SECRETS_AUTH_USER
, NULL
);
658 *domain
= (char *)secrets_fetch(SECRETS_AUTH_DOMAIN
, NULL
);
659 *password
= (char *)secrets_fetch(SECRETS_AUTH_PASSWORD
, NULL
);
661 if (*username
&& **username
) {
663 if (!*domain
|| !**domain
)
664 *domain
= smb_xstrdup(lp_workgroup());
666 if (!*password
|| !**password
)
667 *password
= smb_xstrdup("");
669 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
670 *domain
, *username
));
673 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
674 *username
= smb_xstrdup("");
675 *domain
= smb_xstrdup("");
676 *password
= smb_xstrdup("");
680 static NTSTATUS
cm_get_ipc_credentials(TALLOC_CTX
*mem_ctx
,
681 struct cli_credentials
**_creds
)
684 TALLOC_CTX
*frame
= talloc_stackframe();
685 NTSTATUS status
= NT_STATUS_INTERNAL_ERROR
;
686 struct loadparm_context
*lp_ctx
;
687 char *username
= NULL
;
688 char *netbios_domain
= NULL
;
689 char *password
= NULL
;
690 struct cli_credentials
*creds
= NULL
;
693 cm_get_ipc_userpass(&username
, &netbios_domain
, &password
);
695 lp_ctx
= loadparm_init_s3(frame
, loadparm_s3_helpers());
696 if (lp_ctx
== NULL
) {
697 DEBUG(1, ("loadparm_init_s3 failed\n"));
698 status
= NT_STATUS_INTERNAL_ERROR
;
702 creds
= cli_credentials_init(mem_ctx
);
704 status
= NT_STATUS_NO_MEMORY
;
708 cli_credentials_set_conf(creds
, lp_ctx
);
709 cli_credentials_set_kerberos_state(creds
, CRED_DONT_USE_KERBEROS
);
711 ok
= cli_credentials_set_domain(creds
, netbios_domain
, CRED_SPECIFIED
);
713 status
= NT_STATUS_NO_MEMORY
;
717 ok
= cli_credentials_set_username(creds
, username
, CRED_SPECIFIED
);
719 status
= NT_STATUS_NO_MEMORY
;
723 ok
= cli_credentials_set_password(creds
, password
, CRED_SPECIFIED
);
725 status
= NT_STATUS_NO_MEMORY
;
731 status
= NT_STATUS_OK
;
735 SAFE_FREE(netbios_domain
);
741 static bool cm_is_ipc_credentials(struct cli_credentials
*creds
)
743 TALLOC_CTX
*frame
= talloc_stackframe();
744 char *ipc_account
= NULL
;
745 char *ipc_domain
= NULL
;
746 char *ipc_password
= NULL
;
747 const char *creds_account
= NULL
;
748 const char *creds_domain
= NULL
;
749 const char *creds_password
= NULL
;
752 cm_get_ipc_userpass(&ipc_account
, &ipc_domain
, &ipc_password
);
754 creds_account
= cli_credentials_get_username(creds
);
755 creds_domain
= cli_credentials_get_domain(creds
);
756 creds_password
= cli_credentials_get_password(creds
);
758 if (!strequal(ipc_domain
, creds_domain
)) {
762 if (!strequal(ipc_account
, creds_account
)) {
766 if (!strcsequal(ipc_password
, creds_password
)) {
772 SAFE_FREE(ipc_account
);
773 SAFE_FREE(ipc_domain
);
774 SAFE_FREE(ipc_password
);
779 static bool get_dc_name_via_netlogon(struct winbindd_domain
*domain
,
781 struct sockaddr_storage
*dc_ss
,
782 uint32_t request_flags
)
784 struct winbindd_domain
*our_domain
= NULL
;
785 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
789 unsigned int orig_timeout
;
790 const char *tmp
= NULL
;
792 struct dcerpc_binding_handle
*b
;
794 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
801 if (domain
->primary
) {
805 our_domain
= find_our_domain();
807 if ((mem_ctx
= talloc_init("get_dc_name_via_netlogon")) == NULL
) {
811 result
= cm_connect_netlogon(our_domain
, &netlogon_pipe
);
812 if (!NT_STATUS_IS_OK(result
)) {
813 talloc_destroy(mem_ctx
);
817 b
= netlogon_pipe
->binding_handle
;
819 /* This call can take a long time - allow the server to time out.
820 35 seconds should do it. */
822 orig_timeout
= rpccli_set_timeout(netlogon_pipe
, 35000);
824 if (our_domain
->active_directory
) {
825 struct netr_DsRGetDCNameInfo
*domain_info
= NULL
;
828 * TODO request flags are not respected in the server
829 * (and in some cases, like REQUIRE_PDC, causes an error)
831 result
= dcerpc_netr_DsRGetDCName(b
,
837 request_flags
|DS_RETURN_DNS_NAME
,
840 if (NT_STATUS_IS_OK(result
) && W_ERROR_IS_OK(werr
)) {
842 mem_ctx
, domain_info
->dc_unc
);
844 DEBUG(0, ("talloc_strdup failed\n"));
845 talloc_destroy(mem_ctx
);
848 if (domain
->alt_name
== NULL
) {
849 domain
->alt_name
= talloc_strdup(domain
,
850 domain_info
->domain_name
);
851 if (domain
->alt_name
== NULL
) {
852 DEBUG(0, ("talloc_strdup failed\n"));
853 talloc_destroy(mem_ctx
);
857 if (domain
->forest_name
== NULL
) {
858 domain
->forest_name
= talloc_strdup(domain
,
859 domain_info
->forest_name
);
860 if (domain
->forest_name
== NULL
) {
861 DEBUG(0, ("talloc_strdup failed\n"));
862 talloc_destroy(mem_ctx
);
868 result
= dcerpc_netr_GetAnyDCName(b
, mem_ctx
,
875 /* And restore our original timeout. */
876 rpccli_set_timeout(netlogon_pipe
, orig_timeout
);
878 if (!NT_STATUS_IS_OK(result
)) {
879 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
881 talloc_destroy(mem_ctx
);
885 if (!W_ERROR_IS_OK(werr
)) {
886 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
888 talloc_destroy(mem_ctx
);
892 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
893 p
= strip_hostname(tmp
);
897 talloc_destroy(mem_ctx
);
899 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname
));
901 if (!resolve_name(dcname
, dc_ss
, 0x20, true)) {
909 * Helper function to assemble trust password and account name
911 static NTSTATUS
get_trust_credentials(struct winbindd_domain
*domain
,
914 struct cli_credentials
**_creds
)
916 const struct winbindd_domain
*creds_domain
= NULL
;
917 struct cli_credentials
*creds
;
919 bool force_machine_account
= false;
921 /* If we are a DC and this is not our own domain */
923 if (!domain
->active_directory
) {
926 * For non active directory domains
927 * we can only use NTLMSSP for SMB.
929 * But the trust account is not allowed
930 * to use SMB with NTLMSSP.
932 force_machine_account
= true;
936 if (IS_DC
&& !force_machine_account
) {
937 creds_domain
= domain
;
939 creds_domain
= find_our_domain();
940 if (creds_domain
== NULL
) {
941 return NT_STATUS_INVALID_SERVER_STATE
;
945 status
= pdb_get_trust_credentials(creds_domain
->name
,
946 creds_domain
->alt_name
,
949 if (!NT_STATUS_IS_OK(status
)) {
953 if (creds_domain
!= domain
) {
955 * We can only use schannel against a direct trust
957 cli_credentials_set_secure_channel_type(creds
,
966 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
969 status
= cm_get_ipc_credentials(mem_ctx
, &creds
);
970 if (!NT_STATUS_IS_OK(status
)) {
978 /************************************************************************
979 Given a fd with a just-connected TCP connection to a DC, open a connection
981 ************************************************************************/
983 static NTSTATUS
cm_prepare_connection(struct winbindd_domain
*domain
,
985 const char *controller
,
986 struct cli_state
**cli
,
989 bool try_ipc_auth
= false;
990 const char *machine_principal
= NULL
;
991 const char *machine_realm
= NULL
;
992 const char *machine_account
= NULL
;
993 const char *machine_domain
= NULL
;
995 struct cli_credentials
*creds
= NULL
;
997 struct named_mutex
*mutex
;
999 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1000 NTSTATUS tmp_status
;
1001 NTSTATUS tcon_status
= NT_STATUS_NETWORK_NAME_DELETED
;
1003 enum smb_signing_setting smb_sign_client_connections
= lp_client_ipc_signing();
1006 if (domain
->secure_channel_type
== SEC_CHAN_NULL
) {
1008 * Make sure we don't even try to
1009 * connect to a foreign domain
1010 * without a direct outbound trust.
1012 return NT_STATUS_NO_TRUST_LSA_SECRET
;
1016 * As AD DC we only use netlogon and lsa
1017 * using schannel over an anonymous transport
1018 * (ncacn_ip_tcp or ncacn_np).
1020 * Currently we always establish the SMB connection,
1021 * even if we don't use it, because we later use ncacn_ip_tcp.
1023 * As we won't use the SMB connection there's no
1024 * need to try kerberos. And NT4 domains expect
1025 * an anonymous IPC$ connection anyway.
1027 smb_sign_client_connections
= SMB_SIGNING_OFF
;
1030 if (smb_sign_client_connections
== SMB_SIGNING_DEFAULT
) {
1032 * If we are connecting to our own AD domain, require
1033 * smb signing to disrupt MITM attacks
1035 if (domain
->primary
&& lp_security() == SEC_ADS
) {
1036 smb_sign_client_connections
= SMB_SIGNING_REQUIRED
;
1038 * If we are in or are an AD domain and connecting to another
1039 * AD domain in our forest
1040 * then require smb signing to disrupt MITM attacks
1042 } else if ((lp_security() == SEC_ADS
)
1043 && domain
->active_directory
1044 && (domain
->domain_trust_attribs
1045 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
)) {
1046 smb_sign_client_connections
= SMB_SIGNING_REQUIRED
;
1050 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1051 controller
, domain
->name
));
1055 mutex
= grab_named_mutex(talloc_tos(), controller
,
1056 WINBIND_SERVER_MUTEX_WAIT_TIME
);
1057 if (mutex
== NULL
) {
1059 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1061 result
= NT_STATUS_POSSIBLE_DEADLOCK
;
1065 *cli
= cli_state_create(NULL
, sockfd
, controller
,
1066 smb_sign_client_connections
, flags
);
1069 DEBUG(1, ("Could not cli_initialize\n"));
1070 result
= NT_STATUS_NO_MEMORY
;
1074 cli_set_timeout(*cli
, 10000); /* 10 seconds */
1076 set_socket_options(sockfd
, lp_socket_options());
1078 result
= smbXcli_negprot((*cli
)->conn
, (*cli
)->timeout
,
1079 lp_client_ipc_min_protocol(),
1080 lp_client_ipc_max_protocol());
1082 if (!NT_STATUS_IS_OK(result
)) {
1083 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result
)));
1087 if (smbXcli_conn_protocol((*cli
)->conn
) >= PROTOCOL_NT1
&&
1088 smb1cli_conn_capabilities((*cli
)->conn
) & CAP_EXTENDED_SECURITY
) {
1089 try_ipc_auth
= true;
1090 } else if (smbXcli_conn_protocol((*cli
)->conn
) >= PROTOCOL_SMB2_02
) {
1091 try_ipc_auth
= true;
1092 } else if (smb_sign_client_connections
== SMB_SIGNING_REQUIRED
) {
1094 * If we are forcing on SMB signing, then we must
1095 * require authentication unless this is a one-way
1096 * trust, and we have no stored user/password
1098 try_ipc_auth
= true;
1103 * As AD DC we only use netlogon and lsa
1104 * using schannel over an anonymous transport
1105 * (ncacn_ip_tcp or ncacn_np).
1107 * Currently we always establish the SMB connection,
1108 * even if we don't use it, because we later use ncacn_ip_tcp.
1110 * As we won't use the SMB connection there's no
1111 * need to try kerberos. And NT4 domains expect
1112 * an anonymous IPC$ connection anyway.
1114 try_ipc_auth
= false;
1118 result
= get_trust_credentials(domain
, talloc_tos(), false, &creds
);
1119 if (!NT_STATUS_IS_OK(result
)) {
1120 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1121 domain
->name
, nt_errstr(result
)));
1126 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1127 * would try and authentication with our machine
1128 * account password and fail. This is very rare in
1129 * the modern world however
1131 creds
= cli_credentials_init_anon(talloc_tos());
1132 if (creds
== NULL
) {
1133 result
= NT_STATUS_NO_MEMORY
;
1134 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1135 domain
->name
, nt_errstr(result
)));
1140 machine_principal
= cli_credentials_get_principal(creds
,
1142 machine_realm
= cli_credentials_get_realm(creds
);
1143 machine_account
= cli_credentials_get_username(creds
);
1144 machine_domain
= cli_credentials_get_domain(creds
);
1146 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1147 "[%s] and realm [%s]\n",
1148 controller
, domain
->name
, domain
->alt_name
,
1149 machine_domain
, machine_account
,
1150 machine_principal
, machine_realm
));
1152 if (cli_credentials_is_anonymous(creds
)) {
1156 winbindd_set_locator_kdc_envs(domain
);
1158 result
= cli_session_setup_creds(*cli
, creds
);
1159 if (NT_STATUS_IS_OK(result
)) {
1160 goto session_setup_done
;
1163 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1165 cli_credentials_get_unparsed_name(creds
, talloc_tos()),
1166 nt_errstr(result
)));
1169 * If we are not going to validate the connection
1170 * with SMB signing, then allow us to fall back to
1173 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
)
1174 || NT_STATUS_EQUAL(result
, NT_STATUS_TRUSTED_DOMAIN_FAILURE
)
1175 || NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_ACCOUNT_NAME
)
1176 || NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_COMPUTER_NAME
)
1177 || NT_STATUS_EQUAL(result
, NT_STATUS_NO_SUCH_DOMAIN
)
1178 || NT_STATUS_EQUAL(result
, NT_STATUS_NO_LOGON_SERVERS
)
1179 || NT_STATUS_EQUAL(result
, NT_STATUS_LOGON_FAILURE
))
1181 if (!cm_is_ipc_credentials(creds
)) {
1185 if (smb_sign_client_connections
== SMB_SIGNING_REQUIRED
) {
1196 tmp_status
= cm_get_ipc_credentials(talloc_tos(), &creds
);
1197 if (!NT_STATUS_IS_OK(tmp_status
)) {
1198 result
= tmp_status
;
1202 if (cli_credentials_is_anonymous(creds
)) {
1206 machine_account
= cli_credentials_get_username(creds
);
1207 machine_domain
= cli_credentials_get_domain(creds
);
1209 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1210 "[%s]\\[%s]\n", controller
, lp_netbios_name(),
1211 machine_domain
, machine_account
));
1213 result
= cli_session_setup_creds(*cli
, creds
);
1214 if (NT_STATUS_IS_OK(result
)) {
1215 goto session_setup_done
;
1218 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1220 cli_credentials_get_unparsed_name(creds
, talloc_tos()),
1221 nt_errstr(result
)));
1224 * If we are not going to validate the connection
1225 * with SMB signing, then allow us to fall back to
1228 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
)
1229 || NT_STATUS_EQUAL(result
, NT_STATUS_TRUSTED_DOMAIN_FAILURE
)
1230 || NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_ACCOUNT_NAME
)
1231 || NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_COMPUTER_NAME
)
1232 || NT_STATUS_EQUAL(result
, NT_STATUS_NO_SUCH_DOMAIN
)
1233 || NT_STATUS_EQUAL(result
, NT_STATUS_NO_LOGON_SERVERS
)
1234 || NT_STATUS_EQUAL(result
, NT_STATUS_LOGON_FAILURE
))
1244 if (smb_sign_client_connections
== SMB_SIGNING_REQUIRED
) {
1248 /* Fall back to anonymous connection, this might fail later */
1249 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1250 "connection for DC %s\n",
1253 result
= cli_session_setup_anon(*cli
);
1254 if (NT_STATUS_IS_OK(result
)) {
1255 DEBUG(5, ("Connected anonymously\n"));
1256 goto session_setup_done
;
1259 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1260 controller
, nt_errstr(result
)));
1262 /* We can't session setup */
1269 * This should be a short term hack until
1270 * dynamic re-authentication is implemented.
1272 * See Bug 9175 - winbindd doesn't recover from
1273 * NT_STATUS_NETWORK_SESSION_EXPIRED
1275 if (smbXcli_conn_protocol((*cli
)->conn
) >= PROTOCOL_SMB2_02
) {
1276 smbXcli_session_set_disconnect_expired((*cli
)->smb2
.session
);
1279 result
= cli_tree_connect(*cli
, "IPC$", "IPC", NULL
);
1280 if (!NT_STATUS_IS_OK(result
)) {
1281 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result
)));
1284 tcon_status
= result
;
1286 /* cache the server name for later connections */
1288 saf_store(domain
->name
, controller
);
1289 if (domain
->alt_name
) {
1290 saf_store(domain
->alt_name
, controller
);
1293 winbindd_set_locator_kdc_envs(domain
);
1298 result
= NT_STATUS_OK
;
1304 if (NT_STATUS_IS_OK(result
)) {
1305 result
= tcon_status
;
1308 if (!NT_STATUS_IS_OK(result
)) {
1309 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1310 controller
, nt_errstr(result
)));
1311 winbind_add_failed_connection_entry(domain
, controller
, result
);
1312 if ((*cli
) != NULL
) {
1321 /*******************************************************************
1322 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1325 Keeps the list unique by not adding duplicate entries.
1327 @param[in] mem_ctx talloc memory context to allocate from
1328 @param[in] domain_name domain of the DC
1329 @param[in] dcname name of the DC to add to the list
1330 @param[in] pss Internet address and port pair to add to the list
1331 @param[in,out] dcs array of dc_name_ip structures to add to
1332 @param[in,out] num_dcs number of dcs returned in the dcs array
1333 @return true if the list was added to, false otherwise
1334 *******************************************************************/
1336 static bool add_one_dc_unique(TALLOC_CTX
*mem_ctx
, const char *domain_name
,
1337 const char *dcname
, struct sockaddr_storage
*pss
,
1338 struct dc_name_ip
**dcs
, int *num
)
1342 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name
, dcname
))) {
1343 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname
));
1347 /* Make sure there's no duplicates in the list */
1348 for (i
=0; i
<*num
; i
++)
1350 (struct sockaddr
*)(void *)&(*dcs
)[i
].ss
,
1351 (struct sockaddr
*)(void *)pss
))
1354 *dcs
= talloc_realloc(mem_ctx
, *dcs
, struct dc_name_ip
, (*num
)+1);
1359 fstrcpy((*dcs
)[*num
].name
, dcname
);
1360 (*dcs
)[*num
].ss
= *pss
;
1365 static bool add_sockaddr_to_array(TALLOC_CTX
*mem_ctx
,
1366 struct sockaddr_storage
*pss
, uint16_t port
,
1367 struct sockaddr_storage
**addrs
, int *num
)
1369 *addrs
= talloc_realloc(mem_ctx
, *addrs
, struct sockaddr_storage
, (*num
)+1);
1371 if (*addrs
== NULL
) {
1376 (*addrs
)[*num
] = *pss
;
1377 set_sockaddr_port((struct sockaddr
*)&(*addrs
)[*num
], port
);
1383 /*******************************************************************
1384 convert an ip to a name
1385 For an AD Domain, it checks the requirements of the request flags.
1386 *******************************************************************/
1388 static bool dcip_check_name(TALLOC_CTX
*mem_ctx
,
1389 const struct winbindd_domain
*domain
,
1390 struct sockaddr_storage
*pss
,
1391 char **name
, uint32_t request_flags
)
1393 struct ip_service ip_list
;
1394 uint32_t nt_version
= NETLOGON_NT_VERSION_1
;
1396 const char *dc_name
;
1399 bool is_ad_domain
= false;
1405 /* For active directory servers, try to get the ldap server name.
1406 None of these failures should be considered critical for now */
1408 if ((lp_security() == SEC_ADS
) && (domain
->alt_name
!= NULL
)) {
1409 is_ad_domain
= true;
1410 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
1411 is_ad_domain
= domain
->active_directory
;
1416 ADS_STATUS ads_status
;
1417 char addr
[INET6_ADDRSTRLEN
];
1419 print_sockaddr(addr
, sizeof(addr
), pss
);
1421 ads
= ads_init(domain
->alt_name
,
1425 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
1426 ads
->config
.flags
|= request_flags
;
1427 ads
->server
.no_fallback
= true;
1429 ads_status
= ads_connect(ads
);
1430 if (ADS_ERR_OK(ads_status
)) {
1431 /* We got a cldap packet. */
1432 *name
= talloc_strdup(mem_ctx
,
1433 ads
->config
.ldap_server_name
);
1434 if (*name
== NULL
) {
1437 namecache_store(*name
, 0x20, 1, &ip_list
);
1439 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads
->config
.flags
));
1441 if (domain
->primary
&& (ads
->config
.flags
& NBT_SERVER_KDC
)) {
1442 if (ads_closest_dc(ads
)) {
1443 char *sitename
= sitename_fetch(mem_ctx
, ads
->config
.realm
);
1445 /* We're going to use this KDC for this realm/domain.
1446 If we are using sites, then force the krb5 libs
1449 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1454 TALLOC_FREE(sitename
);
1456 /* use an off site KDC */
1457 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1462 winbindd_set_locator_kdc_envs(domain
);
1464 /* Ensure we contact this DC also. */
1465 saf_store(domain
->name
, *name
);
1466 saf_store(domain
->alt_name
, *name
);
1469 ads_destroy( &ads
);
1473 ads_destroy( &ads
);
1479 size_t len
= strlen(lp_netbios_name());
1480 char my_acct_name
[len
+2];
1482 snprintf(my_acct_name
,
1483 sizeof(my_acct_name
),
1487 status
= nbt_getdc(global_messaging_context(), 10, pss
,
1488 domain
->name
, &domain
->sid
,
1489 my_acct_name
, ACB_WSTRUST
,
1490 nt_version
, mem_ctx
, &nt_version
,
1493 if (NT_STATUS_IS_OK(status
)) {
1494 *name
= talloc_strdup(mem_ctx
, dc_name
);
1495 if (*name
== NULL
) {
1498 namecache_store(*name
, 0x20, 1, &ip_list
);
1502 /* try node status request */
1504 if (name_status_find(domain
->name
, 0x1c, 0x20, pss
, nbtname
) ) {
1505 namecache_store(nbtname
, 0x20, 1, &ip_list
);
1508 *name
= talloc_strdup(mem_ctx
, nbtname
);
1509 if (*name
== NULL
) {
1519 /*******************************************************************
1520 Retrieve a list of IP addresses for domain controllers.
1522 The array is sorted in the preferred connection order.
1524 @param[in] mem_ctx talloc memory context to allocate from
1525 @param[in] domain domain to retrieve DCs for
1526 @param[out] dcs array of dcs that will be returned
1527 @param[out] num_dcs number of dcs returned in the dcs array
1529 *******************************************************************/
1531 static bool get_dcs(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
1532 struct dc_name_ip
**dcs
, int *num_dcs
,
1533 uint32_t request_flags
)
1536 struct sockaddr_storage ss
;
1537 struct ip_service
*ip_list
= NULL
;
1538 int iplist_size
= 0;
1541 enum security_types sec
= (enum security_types
)lp_security();
1543 is_our_domain
= strequal(domain
->name
, lp_workgroup());
1545 /* If not our domain, get the preferred DC, by asking our primary DC */
1547 && get_dc_name_via_netlogon(domain
, dcname
, &ss
, request_flags
)
1548 && add_one_dc_unique(mem_ctx
, domain
->name
, dcname
, &ss
, dcs
,
1551 char addr
[INET6_ADDRSTRLEN
];
1552 print_sockaddr(addr
, sizeof(addr
), &ss
);
1553 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1558 if ((sec
== SEC_ADS
) && (domain
->alt_name
!= NULL
)) {
1559 char *sitename
= NULL
;
1561 /* We need to make sure we know the local site before
1562 doing any DNS queries, as this will restrict the
1563 get_sorted_dc_list() call below to only fetching
1564 DNS records for the correct site. */
1566 /* Find any DC to get the site record.
1567 We deliberately don't care about the
1570 get_dc_name(domain
->name
, domain
->alt_name
, dcname
, &ss
);
1572 sitename
= sitename_fetch(mem_ctx
, domain
->alt_name
);
1575 /* Do the site-specific AD dns lookup first. */
1576 get_sorted_dc_list(domain
->alt_name
, sitename
, &ip_list
,
1577 &iplist_size
, True
);
1579 /* Add ips to the DC array. We don't look up the name
1580 of the DC in this function, but we fill in the char*
1581 of the ip now to make the failed connection cache
1583 for ( i
=0; i
<iplist_size
; i
++ ) {
1584 char addr
[INET6_ADDRSTRLEN
];
1585 print_sockaddr(addr
, sizeof(addr
),
1587 add_one_dc_unique(mem_ctx
,
1596 TALLOC_FREE(sitename
);
1600 /* Now we add DCs from the main AD DNS lookup. */
1601 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
,
1602 &iplist_size
, True
);
1604 for ( i
=0; i
<iplist_size
; i
++ ) {
1605 char addr
[INET6_ADDRSTRLEN
];
1606 print_sockaddr(addr
, sizeof(addr
),
1608 add_one_dc_unique(mem_ctx
,
1620 /* Try standard netbios queries if no ADS and fall back to DNS queries
1621 * if alt_name is available */
1622 if (*num_dcs
== 0) {
1623 get_sorted_dc_list(domain
->name
, NULL
, &ip_list
, &iplist_size
,
1625 if (iplist_size
== 0) {
1626 if (domain
->alt_name
!= NULL
) {
1627 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
,
1628 &iplist_size
, true);
1632 for ( i
=0; i
<iplist_size
; i
++ ) {
1633 char addr
[INET6_ADDRSTRLEN
];
1634 print_sockaddr(addr
, sizeof(addr
),
1636 add_one_dc_unique(mem_ctx
,
1651 /*******************************************************************
1652 Find and make a connection to a DC in the given domain.
1654 @param[in] mem_ctx talloc memory context to allocate from
1655 @param[in] domain domain to find a dc in
1656 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1657 @param[out] pss DC Internet address and port
1658 @param[out] fd fd of the open socket connected to the newly found dc
1659 @return true when a DC connection is made, false otherwise
1660 *******************************************************************/
1662 static bool find_new_dc(TALLOC_CTX
*mem_ctx
,
1663 struct winbindd_domain
*domain
,
1664 char **dcname
, struct sockaddr_storage
*pss
, int *fd
,
1665 uint32_t request_flags
)
1667 struct dc_name_ip
*dcs
= NULL
;
1670 const char **dcnames
= NULL
;
1671 size_t num_dcnames
= 0;
1673 struct sockaddr_storage
*addrs
= NULL
;
1684 if (!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
, request_flags
) || (num_dcs
== 0))
1687 for (i
=0; i
<num_dcs
; i
++) {
1689 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1690 &dcnames
, &num_dcnames
)) {
1693 if (!add_sockaddr_to_array(mem_ctx
, &dcs
[i
].ss
, TCP_SMB_PORT
,
1694 &addrs
, &num_addrs
)) {
1699 if ((num_dcnames
== 0) || (num_dcnames
!= num_addrs
))
1702 if ((addrs
== NULL
) || (dcnames
== NULL
))
1705 status
= smbsock_any_connect(addrs
, dcnames
, NULL
, NULL
, NULL
,
1706 num_addrs
, 0, 10, fd
, &fd_index
, NULL
);
1707 if (!NT_STATUS_IS_OK(status
)) {
1708 for (i
=0; i
<num_dcs
; i
++) {
1709 char ab
[INET6_ADDRSTRLEN
];
1710 print_sockaddr(ab
, sizeof(ab
), &dcs
[i
].ss
);
1711 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1712 "domain %s address %s. Error was %s\n",
1713 domain
->name
, ab
, nt_errstr(status
) ));
1714 winbind_add_failed_connection_entry(domain
,
1715 dcs
[i
].name
, NT_STATUS_UNSUCCESSFUL
);
1720 *pss
= addrs
[fd_index
];
1722 if (*dcnames
[fd_index
] != '\0' && !is_ipaddress(dcnames
[fd_index
])) {
1723 /* Ok, we've got a name for the DC */
1724 *dcname
= talloc_strdup(mem_ctx
, dcnames
[fd_index
]);
1725 if (*dcname
== NULL
) {
1731 /* Try to figure out the name */
1732 if (dcip_check_name(mem_ctx
, domain
, pss
, dcname
, request_flags
)) {
1736 /* We can not continue without the DC's name */
1737 winbind_add_failed_connection_entry(domain
, dcs
[fd_index
].name
,
1738 NT_STATUS_UNSUCCESSFUL
);
1740 /* Throw away all arrays as we're doing this again. */
1744 TALLOC_FREE(dcnames
);
1758 static char *current_dc_key(TALLOC_CTX
*mem_ctx
, const char *domain_name
)
1760 return talloc_asprintf_strupper_m(mem_ctx
, "CURRENT_DCNAME/%s",
1764 static void store_current_dc_in_gencache(const char *domain_name
,
1765 const char *dc_name
,
1766 struct cli_state
*cli
)
1768 char addr
[INET6_ADDRSTRLEN
];
1772 if (!cli_state_is_connected(cli
)) {
1776 print_sockaddr(addr
, sizeof(addr
),
1777 smbXcli_conn_remote_sockaddr(cli
->conn
));
1779 key
= current_dc_key(talloc_tos(), domain_name
);
1784 value
= talloc_asprintf(talloc_tos(), "%s %s", addr
, dc_name
);
1785 if (value
== NULL
) {
1789 gencache_set(key
, value
, 0x7fffffff);
1795 bool fetch_current_dc_from_gencache(TALLOC_CTX
*mem_ctx
,
1796 const char *domain_name
,
1797 char **p_dc_name
, char **p_dc_ip
)
1802 char *dc_name
= NULL
;
1805 key
= current_dc_key(talloc_tos(), domain_name
);
1809 if (!gencache_get(key
, mem_ctx
, &value
, NULL
)) {
1812 p
= strchr(value
, ' ');
1816 dc_ip
= talloc_strndup(mem_ctx
, value
, p
- value
);
1817 if (dc_ip
== NULL
) {
1820 dc_name
= talloc_strdup(mem_ctx
, p
+1);
1821 if (dc_name
== NULL
) {
1825 if (p_dc_ip
!= NULL
) {
1829 if (p_dc_name
!= NULL
) {
1830 *p_dc_name
= dc_name
;
1835 TALLOC_FREE(dc_name
);
1842 NTSTATUS
wb_open_internal_pipe(TALLOC_CTX
*mem_ctx
,
1843 const struct ndr_interface_table
*table
,
1844 struct rpc_pipe_client
**ret_pipe
)
1846 struct rpc_pipe_client
*cli
= NULL
;
1847 const struct auth_session_info
*session_info
;
1848 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
1851 session_info
= get_session_info_system();
1852 SMB_ASSERT(session_info
!= NULL
);
1854 /* create a connection to the specified pipe */
1855 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1856 status
= rpc_pipe_open_interface(mem_ctx
,
1861 global_messaging_context(),
1864 status
= rpc_pipe_open_internal(mem_ctx
,
1869 global_messaging_context(),
1872 if (!NT_STATUS_IS_OK(status
)) {
1873 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1874 table
->name
, nt_errstr(status
)));
1882 return NT_STATUS_OK
;
1885 static NTSTATUS
cm_open_connection(struct winbindd_domain
*domain
,
1886 struct winbindd_cm_conn
*new_conn
,
1889 TALLOC_CTX
*mem_ctx
;
1891 char *saf_servername
;
1893 uint32_t request_flags
= need_rw_dc
? DS_WRITABLE_REQUIRED
: 0;
1895 if ((mem_ctx
= talloc_init("cm_open_connection")) == NULL
) {
1896 set_domain_offline(domain
);
1897 return NT_STATUS_NO_MEMORY
;
1900 saf_servername
= saf_fetch(mem_ctx
, domain
->name
);
1902 /* we have to check the server affinity cache here since
1903 later we select a DC based on response time and not preference */
1905 /* Check the negative connection cache
1906 before talking to it. It going down may have
1907 triggered the reconnection. */
1909 if (saf_servername
&& NT_STATUS_IS_OK(check_negative_conn_cache(domain
->name
, saf_servername
))) {
1910 struct sockaddr_storage ss
;
1911 char *dcname
= NULL
;
1912 bool resolved
= true;
1914 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1915 saf_servername
, domain
->name
));
1917 /* convert an ip address to a name */
1918 if (is_ipaddress(saf_servername
)) {
1919 if (!interpret_string_addr(&ss
, saf_servername
,
1921 TALLOC_FREE(mem_ctx
);
1922 return NT_STATUS_UNSUCCESSFUL
;
1925 if (!resolve_name(saf_servername
, &ss
, 0x20, true)) {
1930 if (resolved
&& dcip_check_name(mem_ctx
, domain
, &ss
, &dcname
, request_flags
)) {
1931 domain
->dcname
= talloc_strdup(domain
,
1933 if (domain
->dcname
== NULL
) {
1934 TALLOC_FREE(mem_ctx
);
1935 return NT_STATUS_NO_MEMORY
;
1938 domain
->dcaddr
= ss
;
1940 winbind_add_failed_connection_entry(domain
, saf_servername
,
1941 NT_STATUS_UNSUCCESSFUL
);
1945 for (retries
= 0; retries
< 3; retries
++) {
1948 char *dcname
= NULL
;
1950 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1952 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1953 domain
->dcname
? domain
->dcname
: "", domain
->name
));
1955 if (domain
->dcname
!= NULL
&&
1956 NT_STATUS_IS_OK(check_negative_conn_cache(domain
->name
,
1961 status
= smbsock_connect(&domain
->dcaddr
, 0,
1964 if (!NT_STATUS_IS_OK(status
)) {
1970 !find_new_dc(mem_ctx
, domain
, &dcname
, &domain
->dcaddr
, &fd
, request_flags
))
1972 /* This is the one place where we will
1973 set the global winbindd offline state
1974 to true, if a "WINBINDD_OFFLINE" entry
1975 is found in the winbindd cache. */
1976 set_global_winbindd_state_offline();
1979 if (dcname
!= NULL
) {
1980 talloc_free(domain
->dcname
);
1982 domain
->dcname
= talloc_move(domain
, &dcname
);
1983 if (domain
->dcname
== NULL
) {
1984 result
= NT_STATUS_NO_MEMORY
;
1989 new_conn
->cli
= NULL
;
1991 result
= cm_prepare_connection(domain
, fd
, domain
->dcname
,
1992 &new_conn
->cli
, &retry
);
1993 if (!NT_STATUS_IS_OK(result
)) {
1994 /* Don't leak the smb connection socket */
2005 if (NT_STATUS_IS_OK(result
)) {
2006 bool seal_pipes
= true;
2008 winbindd_set_locator_kdc_envs(domain
);
2010 if (domain
->online
== False
) {
2011 /* We're changing state from offline to online. */
2012 set_global_winbindd_state_online();
2014 set_domain_online(domain
);
2017 * Much as I hate global state, this seems to be the point
2018 * where we can be certain that we have a proper connection to
2019 * a DC. wbinfo --dc-info needs that information, store it in
2020 * gencache with a looong timeout. This will need revisiting
2021 * once we start to connect to multiple DCs, wbcDcInfo is
2022 * already prepared for that.
2024 store_current_dc_in_gencache(domain
->name
, domain
->dcname
,
2027 seal_pipes
= lp_winbind_sealed_pipes();
2028 seal_pipes
= lp_parm_bool(-1, "winbind sealed pipes",
2033 new_conn
->auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
2035 new_conn
->auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
2038 /* Ensure we setup the retry handler. */
2039 set_domain_offline(domain
);
2042 talloc_destroy(mem_ctx
);
2046 /* Close down all open pipes on a connection. */
2048 void invalidate_cm_connection(struct winbindd_domain
*domain
)
2051 struct winbindd_cm_conn
*conn
= &domain
->conn
;
2053 /* We're closing down a possibly dead
2054 connection. Don't have impossibly long (10s) timeouts. */
2057 cli_set_timeout(conn
->cli
, 1000); /* 1 second. */
2060 if (conn
->samr_pipe
!= NULL
) {
2061 if (is_valid_policy_hnd(&conn
->sam_connect_handle
)) {
2062 dcerpc_samr_Close(conn
->samr_pipe
->binding_handle
,
2064 &conn
->sam_connect_handle
,
2067 TALLOC_FREE(conn
->samr_pipe
);
2068 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2070 cli_set_timeout(conn
->cli
, 500);
2074 if (conn
->lsa_pipe
!= NULL
) {
2075 if (is_valid_policy_hnd(&conn
->lsa_policy
)) {
2076 dcerpc_lsa_Close(conn
->lsa_pipe
->binding_handle
,
2081 TALLOC_FREE(conn
->lsa_pipe
);
2082 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2084 cli_set_timeout(conn
->cli
, 500);
2088 if (conn
->lsa_pipe_tcp
!= NULL
) {
2089 if (is_valid_policy_hnd(&conn
->lsa_policy
)) {
2090 dcerpc_lsa_Close(conn
->lsa_pipe_tcp
->binding_handle
,
2095 TALLOC_FREE(conn
->lsa_pipe_tcp
);
2096 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2098 cli_set_timeout(conn
->cli
, 500);
2102 if (conn
->netlogon_pipe
!= NULL
) {
2103 TALLOC_FREE(conn
->netlogon_pipe
);
2104 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2106 cli_set_timeout(conn
->cli
, 500);
2110 conn
->auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
2111 TALLOC_FREE(conn
->netlogon_creds_ctx
);
2114 cli_shutdown(conn
->cli
);
2120 void close_conns_after_fork(void)
2122 struct winbindd_domain
*domain
;
2123 struct winbindd_cli_state
*cli_state
;
2125 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
2127 * first close the low level SMB TCP connection
2128 * so that we don't generate any SMBclose
2129 * requests in invalidate_cm_connection()
2131 if (cli_state_is_connected(domain
->conn
.cli
)) {
2132 smbXcli_conn_disconnect(domain
->conn
.cli
->conn
, NT_STATUS_OK
);
2135 invalidate_cm_connection(domain
);
2138 for (cli_state
= winbindd_client_list();
2140 cli_state
= cli_state
->next
) {
2141 if (cli_state
->sock
>= 0) {
2142 close(cli_state
->sock
);
2143 cli_state
->sock
= -1;
2148 static bool connection_ok(struct winbindd_domain
*domain
)
2152 ok
= cli_state_is_connected(domain
->conn
.cli
);
2154 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2155 domain
->dcname
, domain
->name
));
2159 if (!domain
->online
) {
2160 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain
->name
));
2167 /* Initialize a new connection up to the RPC BIND.
2168 Bypass online status check so always does network calls. */
2170 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
, bool need_rw_dc
)
2173 bool skip_connection
= domain
->internal
;
2174 if (need_rw_dc
&& domain
->rodc
) {
2175 skip_connection
= false;
2178 /* Internal connections never use the network. */
2179 if (dom_sid_equal(&domain
->sid
, &global_sid_Builtin
)) {
2180 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2183 /* Still ask the internal LSA and SAMR server about the local domain */
2184 if (skip_connection
|| connection_ok(domain
)) {
2185 if (!domain
->initialized
) {
2186 set_dc_type_and_flags(domain
);
2188 return NT_STATUS_OK
;
2191 invalidate_cm_connection(domain
);
2193 if (!domain
->primary
&& !domain
->initialized
) {
2195 * Before we connect to a trust, work out if it is an
2196 * AD domain by asking our own domain.
2198 set_dc_type_and_flags_trustinfo(domain
);
2201 result
= cm_open_connection(domain
, &domain
->conn
, need_rw_dc
);
2203 if (NT_STATUS_IS_OK(result
) && !domain
->initialized
) {
2204 set_dc_type_and_flags(domain
);
2210 NTSTATUS
init_dc_connection(struct winbindd_domain
*domain
, bool need_rw_dc
)
2212 if (dom_sid_equal(&domain
->sid
, &global_sid_Builtin
)) {
2213 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2216 if (domain
->initialized
&& !domain
->online
) {
2217 /* We check for online status elsewhere. */
2218 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
2221 return init_dc_connection_network(domain
, need_rw_dc
);
2224 static NTSTATUS
init_dc_connection_rpc(struct winbindd_domain
*domain
, bool need_rw_dc
)
2228 status
= init_dc_connection(domain
, need_rw_dc
);
2229 if (!NT_STATUS_IS_OK(status
)) {
2233 if (!domain
->internal
&& domain
->conn
.cli
== NULL
) {
2234 /* happens for trusted domains without inbound trust */
2235 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
2238 return NT_STATUS_OK
;
2241 /******************************************************************************
2242 Set the trust flags (direction and forest location) for a domain
2243 ******************************************************************************/
2245 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain
*domain
)
2247 struct winbindd_domain
*our_domain
;
2248 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2250 struct netr_DomainTrustList trusts
;
2252 uint32_t flags
= (NETR_TRUST_FLAG_IN_FOREST
|
2253 NETR_TRUST_FLAG_OUTBOUND
|
2254 NETR_TRUST_FLAG_INBOUND
);
2255 struct rpc_pipe_client
*cli
;
2256 TALLOC_CTX
*mem_ctx
= NULL
;
2257 struct dcerpc_binding_handle
*b
;
2261 * On a DC we loaded all trusts
2262 * from configuration and never learn
2268 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain
->name
));
2270 /* Our primary domain doesn't need to worry about trust flags.
2271 Force it to go through the network setup */
2272 if ( domain
->primary
) {
2276 mem_ctx
= talloc_stackframe();
2277 our_domain
= find_our_domain();
2278 if (our_domain
->internal
) {
2279 result
= init_dc_connection(our_domain
, false);
2280 if (!NT_STATUS_IS_OK(result
)) {
2281 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2282 "Not able to make a connection to our domain: %s\n",
2283 nt_errstr(result
)));
2284 TALLOC_FREE(mem_ctx
);
2289 /* This won't work unless our domain is AD */
2290 if ( !our_domain
->active_directory
) {
2291 TALLOC_FREE(mem_ctx
);
2295 if (our_domain
->internal
) {
2296 result
= wb_open_internal_pipe(mem_ctx
, &ndr_table_netlogon
, &cli
);
2297 } else if (!connection_ok(our_domain
)) {
2298 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2299 "No connection to our domain!\n"));
2300 TALLOC_FREE(mem_ctx
);
2303 result
= cm_connect_netlogon(our_domain
, &cli
);
2306 if (!NT_STATUS_IS_OK(result
)) {
2307 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2308 "a connection to %s for PIPE_NETLOGON (%s)\n",
2309 domain
->name
, nt_errstr(result
)));
2310 TALLOC_FREE(mem_ctx
);
2313 b
= cli
->binding_handle
;
2315 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2316 result
= dcerpc_netr_DsrEnumerateDomainTrusts(b
, mem_ctx
,
2321 if (!NT_STATUS_IS_OK(result
)) {
2322 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2323 "failed to query trusted domain list: %s\n",
2324 nt_errstr(result
)));
2325 TALLOC_FREE(mem_ctx
);
2328 if (!W_ERROR_IS_OK(werr
)) {
2329 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2330 "failed to query trusted domain list: %s\n",
2332 TALLOC_FREE(mem_ctx
);
2336 /* Now find the domain name and get the flags */
2338 for ( i
=0; i
<trusts
.count
; i
++ ) {
2339 if ( strequal( domain
->name
, trusts
.array
[i
].netbios_name
) ) {
2340 domain
->domain_flags
= trusts
.array
[i
].trust_flags
;
2341 domain
->domain_type
= trusts
.array
[i
].trust_type
;
2342 domain
->domain_trust_attribs
= trusts
.array
[i
].trust_attributes
;
2344 if ( domain
->domain_type
== LSA_TRUST_TYPE_UPLEVEL
)
2345 domain
->active_directory
= True
;
2347 /* This flag is only set if the domain is *our*
2348 primary domain and the primary domain is in
2351 domain
->native_mode
= (domain
->domain_flags
& NETR_TRUST_FLAG_NATIVE
);
2353 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2354 "native mode.\n", domain
->name
,
2355 domain
->native_mode
? "" : "NOT "));
2357 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2358 "running active directory.\n", domain
->name
,
2359 domain
->active_directory
? "" : "NOT "));
2361 domain
->can_do_ncacn_ip_tcp
= domain
->active_directory
;
2363 domain
->initialized
= True
;
2369 TALLOC_FREE(mem_ctx
);
2371 return domain
->initialized
;
2374 /******************************************************************************
2375 We can 'sense' certain things about the DC by it's replies to certain
2378 This tells us if this particular remote server is Active Directory, and if it
2380 ******************************************************************************/
2382 static void set_dc_type_and_flags_connect( struct winbindd_domain
*domain
)
2384 NTSTATUS status
, result
;
2386 TALLOC_CTX
*mem_ctx
= NULL
;
2387 struct rpc_pipe_client
*cli
= NULL
;
2388 struct policy_handle pol
;
2389 union dssetup_DsRoleInfo info
;
2390 union lsa_PolicyInformation
*lsa_info
= NULL
;
2392 if (!domain
->internal
&& !connection_ok(domain
)) {
2396 mem_ctx
= talloc_init("set_dc_type_and_flags on domain %s\n",
2399 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2403 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain
->name
));
2405 if (domain
->internal
) {
2406 status
= wb_open_internal_pipe(mem_ctx
,
2410 status
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
2415 if (!NT_STATUS_IS_OK(status
)) {
2416 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2417 "PI_DSSETUP on domain %s: (%s)\n",
2418 domain
->name
, nt_errstr(status
)));
2420 /* if this is just a non-AD domain we need to continue
2421 * identifying so that we can in the end return with
2422 * domain->initialized = True - gd */
2427 status
= dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli
->binding_handle
, mem_ctx
,
2428 DS_ROLE_BASIC_INFORMATION
,
2433 if (NT_STATUS_IS_OK(status
)) {
2434 result
= werror_to_ntstatus(werr
);
2436 if (!NT_STATUS_IS_OK(status
)) {
2437 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2438 "on domain %s failed: (%s)\n",
2439 domain
->name
, nt_errstr(status
)));
2441 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2442 * every opcode on the DSSETUP pipe, continue with
2443 * no_dssetup mode here as well to get domain->initialized
2446 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2450 TALLOC_FREE(mem_ctx
);
2454 if ((info
.basic
.flags
& DS_ROLE_PRIMARY_DS_RUNNING
) &&
2455 !(info
.basic
.flags
& DS_ROLE_PRIMARY_DS_MIXED_MODE
)) {
2456 domain
->native_mode
= True
;
2458 domain
->native_mode
= False
;
2462 if (domain
->internal
) {
2463 status
= wb_open_internal_pipe(mem_ctx
,
2467 status
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
2468 &ndr_table_lsarpc
, &cli
);
2470 if (!NT_STATUS_IS_OK(status
)) {
2471 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2472 "PI_LSARPC on domain %s: (%s)\n",
2473 domain
->name
, nt_errstr(status
)));
2475 TALLOC_FREE(mem_ctx
);
2479 status
= rpccli_lsa_open_policy2(cli
, mem_ctx
, True
,
2480 SEC_FLAG_MAXIMUM_ALLOWED
, &pol
);
2482 if (NT_STATUS_IS_OK(status
)) {
2483 /* This particular query is exactly what Win2k clients use
2484 to determine that the DC is active directory */
2485 status
= dcerpc_lsa_QueryInfoPolicy2(cli
->binding_handle
, mem_ctx
,
2487 LSA_POLICY_INFO_DNS
,
2492 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2493 domain
->active_directory
= True
;
2495 if (lsa_info
->dns
.name
.string
) {
2496 if (!strequal(domain
->name
, lsa_info
->dns
.name
.string
))
2498 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2499 "for domain %s claimed it was a DC "
2500 "for domain %s, refusing to "
2503 lsa_info
->dns
.name
.string
));
2505 TALLOC_FREE(mem_ctx
);
2508 talloc_free(domain
->name
);
2509 domain
->name
= talloc_strdup(domain
,
2510 lsa_info
->dns
.name
.string
);
2511 if (domain
->name
== NULL
) {
2516 if (lsa_info
->dns
.dns_domain
.string
) {
2517 if (domain
->alt_name
!= NULL
&&
2518 !strequal(domain
->alt_name
,
2519 lsa_info
->dns
.dns_domain
.string
))
2521 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2522 "for domain %s (%s) claimed it was "
2523 "a DC for domain %s, refusing to "
2525 domain
->alt_name
, domain
->name
,
2526 lsa_info
->dns
.dns_domain
.string
));
2528 TALLOC_FREE(mem_ctx
);
2531 talloc_free(domain
->alt_name
);
2533 talloc_strdup(domain
,
2534 lsa_info
->dns
.dns_domain
.string
);
2535 if (domain
->alt_name
== NULL
) {
2540 /* See if we can set some domain trust flags about
2543 if (lsa_info
->dns
.dns_forest
.string
) {
2544 talloc_free(domain
->forest_name
);
2545 domain
->forest_name
=
2546 talloc_strdup(domain
,
2547 lsa_info
->dns
.dns_forest
.string
);
2548 if (domain
->forest_name
== NULL
) {
2552 if (strequal(domain
->forest_name
, domain
->alt_name
)) {
2553 domain
->domain_flags
|= NETR_TRUST_FLAG_TREEROOT
;
2557 if (lsa_info
->dns
.sid
) {
2558 if (!is_null_sid(&domain
->sid
) &&
2559 !dom_sid_equal(&domain
->sid
,
2562 struct dom_sid_buf buf1
, buf2
;
2563 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2564 "for domain %s (%s) claimed it was "
2565 "a DC for domain %s, refusing to "
2567 dom_sid_str_buf(&domain
->sid
, &buf1
),
2569 dom_sid_str_buf(lsa_info
->dns
.sid
,
2572 TALLOC_FREE(mem_ctx
);
2575 sid_copy(&domain
->sid
, lsa_info
->dns
.sid
);
2578 domain
->active_directory
= False
;
2580 status
= rpccli_lsa_open_policy(cli
, mem_ctx
, True
,
2581 SEC_FLAG_MAXIMUM_ALLOWED
,
2584 if (!NT_STATUS_IS_OK(status
)) {
2588 status
= dcerpc_lsa_QueryInfoPolicy(cli
->binding_handle
, mem_ctx
,
2590 LSA_POLICY_INFO_ACCOUNT_DOMAIN
,
2593 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2595 if (lsa_info
->account_domain
.name
.string
) {
2596 if (!strequal(domain
->name
,
2597 lsa_info
->account_domain
.name
.string
))
2600 ("set_dc_type_and_flags_connect: "
2601 "DC for domain %s claimed it was"
2602 " a DC for domain %s, refusing "
2603 "to initialize\n", domain
->name
,
2605 account_domain
.name
.string
));
2607 TALLOC_FREE(mem_ctx
);
2610 talloc_free(domain
->name
);
2612 talloc_strdup(domain
,
2613 lsa_info
->account_domain
.name
.string
);
2616 if (lsa_info
->account_domain
.sid
) {
2617 if (!is_null_sid(&domain
->sid
) &&
2618 !dom_sid_equal(&domain
->sid
,
2619 lsa_info
->account_domain
.sid
))
2621 struct dom_sid_buf buf1
, buf2
;
2623 ("set_dc_type_and_flags_connect: "
2624 "DC for domain %s (%s) claimed "
2625 "it was a DC for domain %s, "
2626 "refusing to initialize\n",
2628 &domain
->sid
, &buf1
),
2631 lsa_info
->account_domain
.sid
,
2634 TALLOC_FREE(mem_ctx
);
2637 sid_copy(&domain
->sid
, lsa_info
->account_domain
.sid
);
2643 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2644 domain
->name
, domain
->native_mode
? "" : "NOT "));
2646 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2647 domain
->name
, domain
->active_directory
? "" : "NOT "));
2649 domain
->can_do_ncacn_ip_tcp
= domain
->active_directory
;
2653 TALLOC_FREE(mem_ctx
);
2655 domain
->initialized
= True
;
2658 /**********************************************************************
2659 Set the domain_flags (trust attributes, domain operating modes, etc...
2660 ***********************************************************************/
2662 static void set_dc_type_and_flags( struct winbindd_domain
*domain
)
2666 * On a DC we loaded all trusts
2667 * from configuration and never learn
2673 /* we always have to contact our primary domain */
2675 if ( domain
->primary
|| domain
->internal
) {
2676 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2677 "primary or internal domain\n"));
2678 set_dc_type_and_flags_connect( domain
);
2682 /* Use our DC to get the information if possible */
2684 if ( !set_dc_type_and_flags_trustinfo( domain
) ) {
2685 /* Otherwise, fallback to contacting the
2687 set_dc_type_and_flags_connect( domain
);
2695 /**********************************************************************
2696 ***********************************************************************/
2698 static NTSTATUS
cm_get_schannel_creds(struct winbindd_domain
*domain
,
2699 struct netlogon_creds_cli_context
**ppdc
)
2701 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2702 struct rpc_pipe_client
*netlogon_pipe
;
2706 if ((!IS_DC
) && (!domain
->primary
)) {
2707 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
2710 if (domain
->conn
.netlogon_creds_ctx
!= NULL
) {
2711 *ppdc
= domain
->conn
.netlogon_creds_ctx
;
2712 return NT_STATUS_OK
;
2715 result
= cm_connect_netlogon_secure(domain
, &netlogon_pipe
, ppdc
);
2716 if (!NT_STATUS_IS_OK(result
)) {
2720 return NT_STATUS_OK
;
2723 NTSTATUS
cm_connect_sam(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
2725 struct rpc_pipe_client
**cli
, struct policy_handle
*sam_handle
)
2727 struct winbindd_cm_conn
*conn
;
2728 NTSTATUS status
, result
;
2729 struct netlogon_creds_cli_context
*p_creds
;
2730 struct cli_credentials
*creds
= NULL
;
2731 bool retry
= false; /* allow one retry attempt for expired session */
2733 if (sid_check_is_our_sam(&domain
->sid
)) {
2734 if (domain
->rodc
== false || need_rw_dc
== false) {
2735 return open_internal_samr_conn(mem_ctx
, domain
, cli
, sam_handle
);
2741 * In theory we should not use SAMR within
2742 * winbindd at all, but that's a larger task to
2743 * remove this and avoid breaking existing
2746 * At least as AD DC we have the restriction
2747 * to avoid SAMR against trusted domains,
2748 * as there're no existing setups.
2750 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
2754 status
= init_dc_connection_rpc(domain
, need_rw_dc
);
2755 if (!NT_STATUS_IS_OK(status
)) {
2759 conn
= &domain
->conn
;
2761 if (rpccli_is_connected(conn
->samr_pipe
)) {
2765 TALLOC_FREE(conn
->samr_pipe
);
2768 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2769 * sign and sealed pipe using the machine account password by
2770 * preference. If we can't - try schannel, if that fails, try
2774 result
= get_trust_credentials(domain
, talloc_tos(), false, &creds
);
2775 if (!NT_STATUS_IS_OK(result
)) {
2776 DEBUG(10, ("cm_connect_sam: No user available for "
2777 "domain %s, trying schannel\n", domain
->name
));
2781 if (cli_credentials_is_anonymous(creds
)) {
2786 * We have an authenticated connection. Use a SPNEGO
2787 * authenticated SAMR pipe with sign & seal.
2789 status
= cli_rpc_pipe_open_with_creds(conn
->cli
,
2792 DCERPC_AUTH_TYPE_SPNEGO
,
2794 smbXcli_conn_remote_name(conn
->cli
->conn
),
2798 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
2800 invalidate_cm_connection(domain
);
2805 if (!NT_STATUS_IS_OK(status
)) {
2806 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2807 "pipe for domain %s using NTLMSSP "
2808 "authenticated pipe: user %s. Error was "
2809 "%s\n", domain
->name
,
2810 cli_credentials_get_unparsed_name(creds
, talloc_tos()),
2811 nt_errstr(status
)));
2815 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2816 "domain %s using NTLMSSP authenticated "
2817 "pipe: user %s\n", domain
->name
,
2818 cli_credentials_get_unparsed_name(creds
, talloc_tos())));
2820 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2821 conn
->samr_pipe
->desthost
,
2822 SEC_FLAG_MAXIMUM_ALLOWED
,
2823 &conn
->sam_connect_handle
,
2826 if (NT_STATUS_EQUAL(status
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
2827 invalidate_cm_connection(domain
);
2828 TALLOC_FREE(conn
->samr_pipe
);
2833 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2836 if (NT_STATUS_IS_OK(status
)) {
2840 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2841 "failed for domain %s, error was %s. Trying schannel\n",
2842 domain
->name
, nt_errstr(status
) ));
2843 TALLOC_FREE(conn
->samr_pipe
);
2847 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2849 status
= cm_get_schannel_creds(domain
, &p_creds
);
2850 if (!NT_STATUS_IS_OK(status
)) {
2851 /* If this call fails - conn->cli can now be NULL ! */
2852 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2853 "for domain %s (error %s), trying anon\n",
2855 nt_errstr(status
) ));
2859 status
= cli_rpc_pipe_open_schannel_with_creds(
2860 conn
->cli
, &ndr_table_samr
, NCACN_NP
, p_creds
,
2863 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
2865 invalidate_cm_connection(domain
);
2870 if (!NT_STATUS_IS_OK(status
)) {
2871 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2872 "domain %s using schannel. Error was %s\n",
2873 domain
->name
, nt_errstr(status
) ));
2876 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2877 "schannel.\n", domain
->name
));
2879 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2880 conn
->samr_pipe
->desthost
,
2881 SEC_FLAG_MAXIMUM_ALLOWED
,
2882 &conn
->sam_connect_handle
,
2885 if (NT_STATUS_EQUAL(status
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
2886 invalidate_cm_connection(domain
);
2887 TALLOC_FREE(conn
->samr_pipe
);
2892 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2895 if (NT_STATUS_IS_OK(status
)) {
2898 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2899 "for domain %s, error was %s. Trying anonymous\n",
2900 domain
->name
, nt_errstr(status
) ));
2901 TALLOC_FREE(conn
->samr_pipe
);
2905 /* Finally fall back to anonymous. */
2906 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2907 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2908 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2909 "without connection level security, "
2910 "must set 'winbind sealed pipes = false' and "
2911 "'require strong key = false' to proceed: %s\n",
2912 domain
->name
, nt_errstr(status
)));
2915 status
= cli_rpc_pipe_open_noauth(conn
->cli
, &ndr_table_samr
,
2918 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
2920 invalidate_cm_connection(domain
);
2925 if (!NT_STATUS_IS_OK(status
)) {
2929 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2930 conn
->samr_pipe
->desthost
,
2931 SEC_FLAG_MAXIMUM_ALLOWED
,
2932 &conn
->sam_connect_handle
,
2935 if (NT_STATUS_EQUAL(status
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
2936 invalidate_cm_connection(domain
);
2937 TALLOC_FREE(conn
->samr_pipe
);
2942 if (!NT_STATUS_IS_OK(status
)) {
2943 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2944 "for domain %s Error was %s\n",
2945 domain
->name
, nt_errstr(status
) ));
2948 if (!NT_STATUS_IS_OK(result
)) {
2950 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2951 "for domain %s Error was %s\n",
2952 domain
->name
, nt_errstr(result
)));
2957 status
= dcerpc_samr_OpenDomain(conn
->samr_pipe
->binding_handle
,
2959 &conn
->sam_connect_handle
,
2960 SEC_FLAG_MAXIMUM_ALLOWED
,
2962 &conn
->sam_domain_handle
,
2964 if (!NT_STATUS_IS_OK(status
)) {
2971 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
2973 * if we got access denied, we might just have no access rights
2974 * to talk to the remote samr server server (e.g. when we are a
2975 * PDC and we are connecting a w2k8 pdc via an interdomain
2976 * trust). In that case do not invalidate the whole connection
2979 TALLOC_FREE(conn
->samr_pipe
);
2980 ZERO_STRUCT(conn
->sam_domain_handle
);
2982 } else if (!NT_STATUS_IS_OK(status
)) {
2983 invalidate_cm_connection(domain
);
2987 *cli
= conn
->samr_pipe
;
2988 *sam_handle
= conn
->sam_domain_handle
;
2992 /**********************************************************************
2993 open an schanneld ncacn_ip_tcp connection to LSA
2994 ***********************************************************************/
2996 static NTSTATUS
cm_connect_lsa_tcp(struct winbindd_domain
*domain
,
2997 TALLOC_CTX
*mem_ctx
,
2998 struct rpc_pipe_client
**cli
)
3000 struct winbindd_cm_conn
*conn
;
3001 struct netlogon_creds_cli_context
*p_creds
= NULL
;
3004 DEBUG(10,("cm_connect_lsa_tcp\n"));
3006 status
= init_dc_connection_rpc(domain
, false);
3007 if (!NT_STATUS_IS_OK(status
)) {
3011 conn
= &domain
->conn
;
3014 * rpccli_is_connected handles more error cases
3016 if (rpccli_is_connected(conn
->lsa_pipe_tcp
) &&
3017 conn
->lsa_pipe_tcp
->transport
->transport
== NCACN_IP_TCP
&&
3018 conn
->lsa_pipe_tcp
->auth
->auth_level
>= DCERPC_AUTH_LEVEL_INTEGRITY
) {
3022 TALLOC_FREE(conn
->lsa_pipe_tcp
);
3024 status
= cm_get_schannel_creds(domain
, &p_creds
);
3025 if (!NT_STATUS_IS_OK(status
)) {
3029 status
= cli_rpc_pipe_open_schannel_with_creds(conn
->cli
,
3033 &conn
->lsa_pipe_tcp
);
3034 if (!NT_STATUS_IS_OK(status
)) {
3035 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
3036 nt_errstr(status
)));
3041 if (!NT_STATUS_IS_OK(status
)) {
3042 TALLOC_FREE(conn
->lsa_pipe_tcp
);
3046 *cli
= conn
->lsa_pipe_tcp
;
3051 NTSTATUS
cm_connect_lsa(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
3052 struct rpc_pipe_client
**cli
, struct policy_handle
*lsa_policy
)
3054 struct winbindd_cm_conn
*conn
;
3055 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
3056 struct netlogon_creds_cli_context
*p_creds
;
3057 struct cli_credentials
*creds
= NULL
;
3058 bool retry
= false; /* allow one retry attempt for expired session */
3061 result
= init_dc_connection_rpc(domain
, false);
3062 if (!NT_STATUS_IS_OK(result
))
3065 conn
= &domain
->conn
;
3067 if (rpccli_is_connected(conn
->lsa_pipe
)) {
3071 TALLOC_FREE(conn
->lsa_pipe
);
3075 * Make sure we only use schannel as AD DC.
3080 result
= get_trust_credentials(domain
, talloc_tos(), false, &creds
);
3081 if (!NT_STATUS_IS_OK(result
)) {
3082 DEBUG(10, ("cm_connect_lsa: No user available for "
3083 "domain %s, trying schannel\n", domain
->name
));
3087 if (cli_credentials_is_anonymous(creds
)) {
3092 * We have an authenticated connection. Use a SPNEGO
3093 * authenticated LSA pipe with sign & seal.
3095 result
= cli_rpc_pipe_open_with_creds
3096 (conn
->cli
, &ndr_table_lsarpc
, NCACN_NP
,
3097 DCERPC_AUTH_TYPE_SPNEGO
,
3099 smbXcli_conn_remote_name(conn
->cli
->conn
),
3103 if (NT_STATUS_EQUAL(result
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
3105 invalidate_cm_connection(domain
);
3110 if (!NT_STATUS_IS_OK(result
)) {
3111 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3112 "domain %s using NTLMSSP authenticated pipe: user "
3113 "%s. Error was %s. Trying schannel.\n",
3115 cli_credentials_get_unparsed_name(creds
, talloc_tos()),
3116 nt_errstr(result
)));
3120 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3121 "NTLMSSP authenticated pipe: user %s\n",
3122 domain
->name
, cli_credentials_get_unparsed_name(creds
, talloc_tos())));
3124 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
3125 SEC_FLAG_MAXIMUM_ALLOWED
,
3127 if (NT_STATUS_EQUAL(result
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
3128 invalidate_cm_connection(domain
);
3129 TALLOC_FREE(conn
->lsa_pipe
);
3134 if (NT_STATUS_IS_OK(result
)) {
3138 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3141 TALLOC_FREE(conn
->lsa_pipe
);
3145 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3147 result
= cm_get_schannel_creds(domain
, &p_creds
);
3148 if (!NT_STATUS_IS_OK(result
)) {
3149 /* If this call fails - conn->cli can now be NULL ! */
3150 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3151 "for domain %s (error %s), trying anon\n",
3153 nt_errstr(result
) ));
3158 result
= cli_rpc_pipe_open_schannel_with_creds(
3159 conn
->cli
, &ndr_table_lsarpc
, NCACN_NP
, p_creds
,
3162 if (NT_STATUS_EQUAL(result
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
3164 invalidate_cm_connection(domain
);
3169 if (!NT_STATUS_IS_OK(result
)) {
3170 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3171 "domain %s using schannel. Error was %s\n",
3172 domain
->name
, nt_errstr(result
) ));
3175 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3176 "schannel.\n", domain
->name
));
3178 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
3179 SEC_FLAG_MAXIMUM_ALLOWED
,
3182 if (NT_STATUS_EQUAL(result
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
3183 invalidate_cm_connection(domain
);
3184 TALLOC_FREE(conn
->lsa_pipe
);
3189 if (NT_STATUS_IS_OK(result
)) {
3195 * Make sure we only use schannel as AD DC.
3200 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3203 TALLOC_FREE(conn
->lsa_pipe
);
3209 * Make sure we only use schannel as AD DC.
3214 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3215 result
= NT_STATUS_DOWNGRADE_DETECTED
;
3216 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3217 "without connection level security, "
3218 "must set 'winbind sealed pipes = false' and "
3219 "'require strong key = false' to proceed: %s\n",
3220 domain
->name
, nt_errstr(result
)));
3224 result
= cli_rpc_pipe_open_noauth(conn
->cli
,
3228 if (NT_STATUS_EQUAL(result
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
3230 invalidate_cm_connection(domain
);
3235 if (!NT_STATUS_IS_OK(result
)) {
3239 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
3240 SEC_FLAG_MAXIMUM_ALLOWED
,
3243 if (NT_STATUS_EQUAL(result
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
3244 invalidate_cm_connection(domain
);
3245 TALLOC_FREE(conn
->lsa_pipe
);
3251 if (!NT_STATUS_IS_OK(result
)) {
3252 invalidate_cm_connection(domain
);
3256 *cli
= conn
->lsa_pipe
;
3257 *lsa_policy
= conn
->lsa_policy
;
3261 /****************************************************************************
3262 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3263 ****************************************************************************/
3265 NTSTATUS
cm_connect_lsat(struct winbindd_domain
*domain
,
3266 TALLOC_CTX
*mem_ctx
,
3267 struct rpc_pipe_client
**cli
,
3268 struct policy_handle
*lsa_policy
)
3272 if (domain
->can_do_ncacn_ip_tcp
) {
3273 status
= cm_connect_lsa_tcp(domain
, mem_ctx
, cli
);
3274 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) ||
3275 NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
) ||
3276 NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
)) {
3277 invalidate_cm_connection(domain
);
3278 status
= cm_connect_lsa_tcp(domain
, mem_ctx
, cli
);
3280 if (NT_STATUS_IS_OK(status
)) {
3285 * we tried twice to connect via ncan_ip_tcp and schannel and
3286 * failed - maybe it is a trusted domain we can't connect to ?
3287 * do not try tcp next time - gd
3289 * This also prevents NETLOGON over TCP
3291 domain
->can_do_ncacn_ip_tcp
= false;
3294 status
= cm_connect_lsa(domain
, mem_ctx
, cli
, lsa_policy
);
3299 /****************************************************************************
3300 Open the netlogon pipe to this DC.
3301 ****************************************************************************/
3303 static NTSTATUS
cm_connect_netlogon_transport(struct winbindd_domain
*domain
,
3304 enum dcerpc_transport_t transport
,
3305 struct rpc_pipe_client
**cli
)
3307 struct messaging_context
*msg_ctx
= global_messaging_context();
3308 struct winbindd_cm_conn
*conn
;
3310 enum netr_SchannelType sec_chan_type
;
3311 struct cli_credentials
*creds
= NULL
;
3316 if (domain
->secure_channel_type
== SEC_CHAN_NULL
) {
3318 * Make sure we don't even try to
3319 * connect to a foreign domain
3320 * without a direct outbound trust.
3322 return NT_STATUS_NO_TRUST_LSA_SECRET
;
3326 result
= init_dc_connection_rpc(domain
, domain
->rodc
);
3327 if (!NT_STATUS_IS_OK(result
)) {
3331 conn
= &domain
->conn
;
3333 if (rpccli_is_connected(conn
->netlogon_pipe
)) {
3334 *cli
= conn
->netlogon_pipe
;
3335 return NT_STATUS_OK
;
3338 TALLOC_FREE(conn
->netlogon_pipe
);
3339 TALLOC_FREE(conn
->netlogon_creds_ctx
);
3341 result
= get_trust_credentials(domain
, talloc_tos(), true, &creds
);
3342 if (!NT_STATUS_IS_OK(result
)) {
3343 DBG_DEBUG("No user available for domain %s when trying "
3344 "schannel\n", domain
->name
);
3345 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
3348 if (cli_credentials_is_anonymous(creds
)) {
3349 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3350 "unable to make get NETLOGON credentials\n",
3352 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
3355 sec_chan_type
= cli_credentials_get_secure_channel_type(creds
);
3356 if (sec_chan_type
== SEC_CHAN_NULL
) {
3357 if (transport
== NCACN_IP_TCP
) {
3358 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3359 "for %s, deny NCACN_IP_TCP and let the "
3360 "caller fallback to NCACN_NP.\n",
3362 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
3365 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3366 "fallback to noauth on NCACN_NP.\n",
3369 result
= cli_rpc_pipe_open_noauth_transport(
3372 &ndr_table_netlogon
,
3373 &conn
->netlogon_pipe
);
3374 if (!NT_STATUS_IS_OK(result
)) {
3375 invalidate_cm_connection(domain
);
3379 *cli
= conn
->netlogon_pipe
;
3380 return NT_STATUS_OK
;
3383 result
= rpccli_create_netlogon_creds_ctx(creds
,
3387 &conn
->netlogon_creds_ctx
);
3388 if (!NT_STATUS_IS_OK(result
)) {
3389 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3390 "unable to create NETLOGON credentials: %s\n",
3391 domain
->name
, nt_errstr(result
)));
3395 result
= rpccli_connect_netlogon(
3396 conn
->cli
, transport
,
3397 conn
->netlogon_creds_ctx
, conn
->netlogon_force_reauth
, creds
,
3398 &conn
->netlogon_pipe
);
3399 conn
->netlogon_force_reauth
= false;
3400 if (!NT_STATUS_IS_OK(result
)) {
3401 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3406 *cli
= conn
->netlogon_pipe
;
3407 return NT_STATUS_OK
;
3410 /****************************************************************************
3411 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3412 ****************************************************************************/
3414 NTSTATUS
cm_connect_netlogon(struct winbindd_domain
*domain
,
3415 struct rpc_pipe_client
**cli
)
3419 status
= init_dc_connection_rpc(domain
, domain
->rodc
);
3420 if (!NT_STATUS_IS_OK(status
)) {
3424 if (domain
->active_directory
&& domain
->can_do_ncacn_ip_tcp
) {
3425 status
= cm_connect_netlogon_transport(domain
, NCACN_IP_TCP
, cli
);
3426 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) ||
3427 NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
) ||
3428 NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
)) {
3429 invalidate_cm_connection(domain
);
3430 status
= cm_connect_netlogon_transport(domain
, NCACN_IP_TCP
, cli
);
3432 if (NT_STATUS_IS_OK(status
)) {
3437 * we tried twice to connect via ncan_ip_tcp and schannel and
3438 * failed - maybe it is a trusted domain we can't connect to ?
3439 * do not try tcp next time - gd
3441 * This also prevents LSA over TCP
3443 domain
->can_do_ncacn_ip_tcp
= false;
3446 status
= cm_connect_netlogon_transport(domain
, NCACN_NP
, cli
);
3447 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
3449 * SMB2 session expired, needs reauthentication. Drop
3450 * connection and retry.
3452 invalidate_cm_connection(domain
);
3453 status
= cm_connect_netlogon_transport(domain
, NCACN_NP
, cli
);
3459 NTSTATUS
cm_connect_netlogon_secure(struct winbindd_domain
*domain
,
3460 struct rpc_pipe_client
**cli
,
3461 struct netlogon_creds_cli_context
**ppdc
)
3465 if (domain
->secure_channel_type
== SEC_CHAN_NULL
) {
3466 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
3469 status
= cm_connect_netlogon(domain
, cli
);
3470 if (!NT_STATUS_IS_OK(status
)) {
3474 if (domain
->conn
.netlogon_creds_ctx
== NULL
) {
3475 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
3478 *ppdc
= domain
->conn
.netlogon_creds_ctx
;
3479 return NT_STATUS_OK
;
3482 void winbind_msg_ip_dropped(struct messaging_context
*msg_ctx
,
3485 struct server_id server_id
,
3488 struct winbindd_domain
*domain
;
3489 char *freeit
= NULL
;
3493 || (data
->data
== NULL
)
3494 || (data
->length
== 0)
3495 || (data
->data
[data
->length
-1] != '\0')) {
3496 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3501 addr
= (char *)data
->data
;
3502 DEBUG(10, ("IP %s dropped\n", addr
));
3504 if (!is_ipaddress(addr
)) {
3507 * Some code sends us ip addresses with the /netmask
3510 slash
= strchr(addr
, '/');
3511 if (slash
== NULL
) {
3512 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3516 freeit
= talloc_strndup(talloc_tos(), addr
, slash
-addr
);
3517 if (freeit
== NULL
) {
3518 DEBUG(1, ("talloc failed\n"));
3522 DEBUG(10, ("Stripped /netmask to IP %s\n", addr
));
3525 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
3526 char sockaddr
[INET6_ADDRSTRLEN
];
3528 if (!cli_state_is_connected(domain
->conn
.cli
)) {
3532 print_sockaddr(sockaddr
, sizeof(sockaddr
),
3533 smbXcli_conn_local_sockaddr(domain
->conn
.cli
->conn
));
3535 if (strequal(sockaddr
, addr
)) {
3536 smbXcli_conn_disconnect(domain
->conn
.cli
->conn
, NT_STATUS_OK
);
3539 TALLOC_FREE(freeit
);
3542 void winbind_msg_disconnect_dc(struct messaging_context
*msg_ctx
,
3545 struct server_id server_id
,
3548 struct winbindd_domain
*domain
;
3550 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
3551 if (domain
->internal
) {
3554 invalidate_cm_connection(domain
);