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 "../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"
76 #include "../libcli/security/security.h"
79 #include "auth/gensec/gensec.h"
80 #include "../libcli/smb/smbXcli_base.h"
81 #include "libcli/auth/netlogon_creds_cli.h"
83 #include "rpc_server/rpc_ncacn_np.h"
84 #include "auth/credentials/credentials.h"
85 #include "lib/param/param.h"
88 #define DBGC_CLASS DBGC_WINBIND
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
,
112 struct server_id server_id
,
115 struct winbindd_domain
*domain
;
116 const char *domainname
= (const char *)data
->data
;
118 if (data
->data
== NULL
|| data
->length
== 0) {
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
) {
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
));
137 /* Reschedule the online check. */
138 set_domain_offline(domain
);
144 /****************************************************************
145 Actually cause a reconnect from a message.
146 ****************************************************************/
148 static void msg_try_to_go_online(struct messaging_context
*msg
,
151 struct server_id server_id
,
154 struct winbindd_domain
*domain
;
155 const char *domainname
= (const char *)data
->data
;
157 if (data
->data
== NULL
|| data
->length
== 0) {
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
) {
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
));
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);
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
192 ****************************************************************/
194 static bool fork_child_dc_connect(struct winbindd_domain
*domain
)
196 struct dc_name_ip
*dcs
= NULL
;
198 TALLOC_CTX
*mem_ctx
= NULL
;
199 pid_t parent_pid
= getpid();
203 if (domain
->dc_probe_pid
!= (pid_t
)-1) {
205 * We might already have a DC probe
206 * child working, check.
208 if (process_exists_by_pid(domain
->dc_probe_pid
)) {
209 DEBUG(10,("fork_child_dc_connect: pid %u already "
210 "checking for DC's.\n",
211 (unsigned int)domain
->dc_probe_pid
));
214 domain
->dc_probe_pid
= (pid_t
)-1;
217 domain
->dc_probe_pid
= fork();
219 if (domain
->dc_probe_pid
== (pid_t
)-1) {
220 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno
)));
224 if (domain
->dc_probe_pid
!= (pid_t
)0) {
226 messaging_register(winbind_messaging_context(), NULL
,
227 MSG_WINBIND_TRY_TO_GO_ONLINE
,
228 msg_try_to_go_online
);
229 messaging_register(winbind_messaging_context(), NULL
,
230 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
231 msg_failed_to_go_online
);
237 /* Leave messages blocked - we will never process one. */
239 if (!override_logfile
) {
240 if (asprintf(&lfile
, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
241 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
246 status
= winbindd_reinit_after_fork(NULL
, lfile
);
247 if (!NT_STATUS_IS_OK(status
)) {
248 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
250 messaging_send_buf(winbind_messaging_context(),
251 pid_to_procid(parent_pid
),
252 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
253 (const uint8_t *)domain
->name
,
254 strlen(domain
->name
)+1);
259 mem_ctx
= talloc_init("fork_child_dc_connect");
261 DEBUG(0,("talloc_init failed.\n"));
262 messaging_send_buf(winbind_messaging_context(),
263 pid_to_procid(parent_pid
),
264 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
265 (const uint8_t *)domain
->name
,
266 strlen(domain
->name
)+1);
270 if ((!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
, 0)) || (num_dcs
== 0)) {
271 /* Still offline ? Can't find DC's. */
272 messaging_send_buf(winbind_messaging_context(),
273 pid_to_procid(parent_pid
),
274 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
275 (const uint8_t *)domain
->name
,
276 strlen(domain
->name
)+1);
280 /* We got a DC. Send a message to our parent to get it to
281 try and do the same. */
283 messaging_send_buf(winbind_messaging_context(),
284 pid_to_procid(parent_pid
),
285 MSG_WINBIND_TRY_TO_GO_ONLINE
,
286 (const uint8_t *)domain
->name
,
287 strlen(domain
->name
)+1);
291 /****************************************************************
292 Handler triggered if we're offline to try and detect a DC.
293 ****************************************************************/
295 static void check_domain_online_handler(struct tevent_context
*ctx
,
296 struct tevent_timer
*te
,
300 struct winbindd_domain
*domain
=
301 (struct winbindd_domain
*)private_data
;
303 DEBUG(10,("check_domain_online_handler: called for domain "
304 "%s (online = %s)\n", domain
->name
,
305 domain
->online
? "True" : "False" ));
307 TALLOC_FREE(domain
->check_online_event
);
309 /* Are we still in "startup" mode ? */
311 if (domain
->startup
&& (time_mono(NULL
) > domain
->startup_time
+ 30)) {
312 /* No longer in "startup" mode. */
313 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
315 domain
->startup
= False
;
318 /* We've been told to stay offline, so stay
321 if (get_global_winbindd_state_offline()) {
322 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
327 /* Fork a child to test if it can contact a DC.
328 If it can then send ourselves a message to
329 cause a reconnect. */
331 fork_child_dc_connect(domain
);
334 /****************************************************************
335 If we're still offline setup the timeout check.
336 ****************************************************************/
338 static void calc_new_online_timeout_check(struct winbindd_domain
*domain
)
340 int wbr
= lp_winbind_reconnect_delay();
342 if (domain
->startup
) {
343 domain
->check_online_timeout
= 10;
344 } else if (domain
->check_online_timeout
< wbr
) {
345 domain
->check_online_timeout
= wbr
;
349 void winbind_msg_domain_offline(struct messaging_context
*msg_ctx
,
352 struct server_id server_id
,
355 const char *domain_name
= (const char *)data
->data
;
356 struct winbindd_domain
*domain
;
358 domain
= find_domain_from_name_noinit(domain_name
);
359 if (domain
== NULL
) {
363 domain
->online
= false;
365 DEBUG(10, ("Domain %s is marked as offline now.\n",
369 void winbind_msg_domain_online(struct messaging_context
*msg_ctx
,
372 struct server_id server_id
,
375 const char *domain_name
= (const char *)data
->data
;
376 struct winbindd_domain
*domain
;
378 domain
= find_domain_from_name_noinit(domain_name
);
379 if (domain
== NULL
) {
383 domain
->online
= true;
385 DEBUG(10, ("Domain %s is marked as online now.\n",
389 /****************************************************************
390 Set domain offline and also add handler to put us back online
392 ****************************************************************/
394 void set_domain_offline(struct winbindd_domain
*domain
)
396 pid_t parent_pid
= getppid();
398 DEBUG(10,("set_domain_offline: called for domain %s\n",
401 TALLOC_FREE(domain
->check_online_event
);
403 if (domain
->internal
) {
404 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
409 domain
->online
= False
;
411 /* Offline domains are always initialized. They're
412 re-initialized when they go back online. */
414 domain
->initialized
= True
;
416 /* We only add the timeout handler that checks and
417 allows us to go back online when we've not
418 been told to remain offline. */
420 if (get_global_winbindd_state_offline()) {
421 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
426 /* If we're in startup mode, check again in 10 seconds, not in
427 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
429 calc_new_online_timeout_check(domain
);
431 domain
->check_online_event
= tevent_add_timer(winbind_event_context(),
433 timeval_current_ofs(domain
->check_online_timeout
,0),
434 check_domain_online_handler
,
437 /* The above *has* to succeed for winbindd to work. */
438 if (!domain
->check_online_event
) {
439 smb_panic("set_domain_offline: failed to add online handler");
442 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
445 /* Send a message to the parent that the domain is offline. */
446 if (parent_pid
> 1 && !domain
->internal
) {
447 messaging_send_buf(winbind_messaging_context(),
448 pid_to_procid(parent_pid
),
449 MSG_WINBIND_DOMAIN_OFFLINE
,
450 (uint8_t *)domain
->name
,
451 strlen(domain
->name
) + 1);
454 /* Send an offline message to the idmap child when our
455 primary domain goes offline */
457 if ( domain
->primary
) {
458 struct winbindd_child
*idmap
= idmap_child();
460 if ( idmap
->pid
!= 0 ) {
461 messaging_send_buf(winbind_messaging_context(),
462 pid_to_procid(idmap
->pid
),
464 (const uint8_t *)domain
->name
,
465 strlen(domain
->name
)+1);
472 /****************************************************************
473 Set domain online - if allowed.
474 ****************************************************************/
476 static void set_domain_online(struct winbindd_domain
*domain
)
478 pid_t parent_pid
= getppid();
480 DEBUG(10,("set_domain_online: called for domain %s\n",
483 if (domain
->internal
) {
484 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
489 if (get_global_winbindd_state_offline()) {
490 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
495 winbindd_set_locator_kdc_envs(domain
);
497 /* If we are waiting to get a krb5 ticket, trigger immediately. */
498 ccache_regain_all_now();
500 /* Ok, we're out of any startup mode now... */
501 domain
->startup
= False
;
503 if (domain
->online
== False
) {
504 /* We were offline - now we're online. We default to
505 using the MS-RPC backend if we started offline,
506 and if we're going online for the first time we
507 should really re-initialize the backends and the
508 checks to see if we're talking to an AD or NT domain.
511 domain
->initialized
= False
;
513 /* 'reconnect_methods' is the MS-RPC backend. */
514 if (domain
->backend
== &reconnect_methods
) {
515 domain
->backend
= NULL
;
519 /* Ensure we have no online timeout checks. */
520 domain
->check_online_timeout
= 0;
521 TALLOC_FREE(domain
->check_online_event
);
523 /* Ensure we ignore any pending child messages. */
524 messaging_deregister(winbind_messaging_context(),
525 MSG_WINBIND_TRY_TO_GO_ONLINE
, NULL
);
526 messaging_deregister(winbind_messaging_context(),
527 MSG_WINBIND_FAILED_TO_GO_ONLINE
, NULL
);
529 domain
->online
= True
;
531 /* Send a message to the parent that the domain is online. */
532 if (parent_pid
> 1 && !domain
->internal
) {
533 messaging_send_buf(winbind_messaging_context(),
534 pid_to_procid(parent_pid
),
535 MSG_WINBIND_DOMAIN_ONLINE
,
536 (uint8_t *)domain
->name
,
537 strlen(domain
->name
) + 1);
540 /* Send an online message to the idmap child when our
541 primary domain comes online */
543 if ( domain
->primary
) {
544 struct winbindd_child
*idmap
= idmap_child();
546 if ( idmap
->pid
!= 0 ) {
547 messaging_send_buf(winbind_messaging_context(),
548 pid_to_procid(idmap
->pid
),
550 (const uint8_t *)domain
->name
,
551 strlen(domain
->name
)+1);
558 /****************************************************************
559 Requested to set a domain online.
560 ****************************************************************/
562 void set_domain_online_request(struct winbindd_domain
*domain
)
566 DEBUG(10,("set_domain_online_request: called for domain %s\n",
569 if (get_global_winbindd_state_offline()) {
570 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
575 if (domain
->internal
) {
576 DEBUG(10, ("set_domain_online_request: Internal domains are "
581 /* We've been told it's safe to go online and
582 try and connect to a DC. But I don't believe it
583 because network manager seems to lie.
584 Wait at least 5 seconds. Heuristics suck... */
589 /* Go into "startup" mode again. */
590 domain
->startup_time
= time_mono(NULL
);
591 domain
->startup
= True
;
595 if (!domain
->check_online_event
) {
596 /* If we've come from being globally offline we
597 don't have a check online event handler set.
598 We need to add one now we're trying to go
601 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
605 TALLOC_FREE(domain
->check_online_event
);
607 domain
->check_online_event
= tevent_add_timer(winbind_event_context(),
610 check_domain_online_handler
,
613 /* The above *has* to succeed for winbindd to work. */
614 if (!domain
->check_online_event
) {
615 smb_panic("set_domain_online_request: failed to add online handler");
619 /****************************************************************
620 Add -ve connection cache entries for domain and realm.
621 ****************************************************************/
623 static void winbind_add_failed_connection_entry(
624 const struct winbindd_domain
*domain
,
628 add_failed_connection_entry(domain
->name
, server
, result
);
629 /* If this was the saf name for the last thing we talked to,
631 saf_delete(domain
->name
);
632 if (domain
->alt_name
!= NULL
) {
633 add_failed_connection_entry(domain
->alt_name
, server
, result
);
634 saf_delete(domain
->alt_name
);
636 winbindd_unset_locator_kdc_env(domain
);
639 /* Choose between anonymous or authenticated connections. We need to use
640 an authenticated connection if DCs have the RestrictAnonymous registry
641 entry set > 0, or the "Additional restrictions for anonymous
642 connections" set in the win2k Local Security Policy.
644 Caller to free() result in domain, username, password
647 static void cm_get_ipc_userpass(char **username
, char **domain
, char **password
)
649 *username
= (char *)secrets_fetch(SECRETS_AUTH_USER
, NULL
);
650 *domain
= (char *)secrets_fetch(SECRETS_AUTH_DOMAIN
, NULL
);
651 *password
= (char *)secrets_fetch(SECRETS_AUTH_PASSWORD
, NULL
);
653 if (*username
&& **username
) {
655 if (!*domain
|| !**domain
)
656 *domain
= smb_xstrdup(lp_workgroup());
658 if (!*password
|| !**password
)
659 *password
= smb_xstrdup("");
661 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
662 *domain
, *username
));
665 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
666 *username
= smb_xstrdup("");
667 *domain
= smb_xstrdup("");
668 *password
= smb_xstrdup("");
672 static NTSTATUS
cm_get_ipc_credentials(TALLOC_CTX
*mem_ctx
,
673 struct cli_credentials
**_creds
)
676 TALLOC_CTX
*frame
= talloc_stackframe();
677 NTSTATUS status
= NT_STATUS_INTERNAL_ERROR
;
678 struct loadparm_context
*lp_ctx
;
679 char *username
= NULL
;
680 char *netbios_domain
= NULL
;
681 char *password
= NULL
;
682 struct cli_credentials
*creds
= NULL
;
685 cm_get_ipc_userpass(&username
, &netbios_domain
, &password
);
687 lp_ctx
= loadparm_init_s3(frame
, loadparm_s3_helpers());
688 if (lp_ctx
== NULL
) {
689 DEBUG(1, ("loadparm_init_s3 failed\n"));
690 status
= NT_STATUS_INTERNAL_ERROR
;
694 creds
= cli_credentials_init(mem_ctx
);
696 status
= NT_STATUS_NO_MEMORY
;
700 cli_credentials_set_conf(creds
, lp_ctx
);
701 cli_credentials_set_kerberos_state(creds
, CRED_DONT_USE_KERBEROS
);
703 ok
= cli_credentials_set_domain(creds
, netbios_domain
, CRED_SPECIFIED
);
705 status
= NT_STATUS_NO_MEMORY
;
709 ok
= cli_credentials_set_username(creds
, username
, CRED_SPECIFIED
);
711 status
= NT_STATUS_NO_MEMORY
;
715 ok
= cli_credentials_set_password(creds
, password
, CRED_SPECIFIED
);
717 status
= NT_STATUS_NO_MEMORY
;
723 status
= NT_STATUS_OK
;
727 SAFE_FREE(netbios_domain
);
733 static bool cm_is_ipc_credentials(struct cli_credentials
*creds
)
735 TALLOC_CTX
*frame
= talloc_stackframe();
736 char *ipc_account
= NULL
;
737 char *ipc_domain
= NULL
;
738 char *ipc_password
= NULL
;
739 const char *creds_account
= NULL
;
740 const char *creds_domain
= NULL
;
741 const char *creds_password
= NULL
;
744 cm_get_ipc_userpass(&ipc_account
, &ipc_domain
, &ipc_password
);
746 creds_account
= cli_credentials_get_username(creds
);
747 creds_domain
= cli_credentials_get_domain(creds
);
748 creds_password
= cli_credentials_get_password(creds
);
750 if (!strequal(ipc_domain
, creds_domain
)) {
754 if (!strequal(ipc_account
, creds_account
)) {
758 if (!strcsequal(ipc_password
, creds_password
)) {
764 SAFE_FREE(ipc_account
);
765 SAFE_FREE(ipc_domain
);
766 SAFE_FREE(ipc_password
);
771 static bool get_dc_name_via_netlogon(struct winbindd_domain
*domain
,
773 struct sockaddr_storage
*dc_ss
,
774 uint32_t request_flags
)
776 struct winbindd_domain
*our_domain
= NULL
;
777 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
781 unsigned int orig_timeout
;
782 const char *tmp
= NULL
;
784 struct dcerpc_binding_handle
*b
;
786 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
793 if (domain
->primary
) {
797 our_domain
= find_our_domain();
799 if ((mem_ctx
= talloc_init("get_dc_name_via_netlogon")) == NULL
) {
803 result
= cm_connect_netlogon(our_domain
, &netlogon_pipe
);
804 if (!NT_STATUS_IS_OK(result
)) {
805 talloc_destroy(mem_ctx
);
809 b
= netlogon_pipe
->binding_handle
;
811 /* This call can take a long time - allow the server to time out.
812 35 seconds should do it. */
814 orig_timeout
= rpccli_set_timeout(netlogon_pipe
, 35000);
816 if (our_domain
->active_directory
) {
817 struct netr_DsRGetDCNameInfo
*domain_info
= NULL
;
820 * TODO request flags are not respected in the server
821 * (and in some cases, like REQUIRE_PDC, causes an error)
823 result
= dcerpc_netr_DsRGetDCName(b
,
829 request_flags
|DS_RETURN_DNS_NAME
,
832 if (NT_STATUS_IS_OK(result
) && W_ERROR_IS_OK(werr
)) {
834 mem_ctx
, domain_info
->dc_unc
);
836 DEBUG(0, ("talloc_strdup failed\n"));
837 talloc_destroy(mem_ctx
);
840 if (domain
->alt_name
== NULL
) {
841 domain
->alt_name
= talloc_strdup(domain
,
842 domain_info
->domain_name
);
843 if (domain
->alt_name
== NULL
) {
844 DEBUG(0, ("talloc_strdup failed\n"));
845 talloc_destroy(mem_ctx
);
849 if (domain
->forest_name
== NULL
) {
850 domain
->forest_name
= talloc_strdup(domain
,
851 domain_info
->forest_name
);
852 if (domain
->forest_name
== NULL
) {
853 DEBUG(0, ("talloc_strdup failed\n"));
854 talloc_destroy(mem_ctx
);
860 result
= dcerpc_netr_GetAnyDCName(b
, mem_ctx
,
867 /* And restore our original timeout. */
868 rpccli_set_timeout(netlogon_pipe
, orig_timeout
);
870 if (!NT_STATUS_IS_OK(result
)) {
871 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
873 talloc_destroy(mem_ctx
);
877 if (!W_ERROR_IS_OK(werr
)) {
878 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
880 talloc_destroy(mem_ctx
);
884 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
885 p
= strip_hostname(tmp
);
889 talloc_destroy(mem_ctx
);
891 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname
));
893 if (!resolve_name(dcname
, dc_ss
, 0x20, true)) {
901 * Helper function to assemble trust password and account name
903 static NTSTATUS
get_trust_credentials(struct winbindd_domain
*domain
,
906 struct cli_credentials
**_creds
)
908 const struct winbindd_domain
*creds_domain
= NULL
;
909 struct cli_credentials
*creds
;
911 bool force_machine_account
= false;
913 /* If we are a DC and this is not our own domain */
915 if (!domain
->active_directory
) {
918 * For non active directory domains
919 * we can only use NTLMSSP for SMB.
921 * But the trust account is not allowed
922 * to use SMB with NTLMSSP.
924 force_machine_account
= true;
928 if (IS_DC
&& !force_machine_account
) {
929 creds_domain
= domain
;
931 creds_domain
= find_our_domain();
932 if (creds_domain
== NULL
) {
933 return NT_STATUS_INVALID_SERVER_STATE
;
937 status
= pdb_get_trust_credentials(creds_domain
->name
,
938 creds_domain
->alt_name
,
941 if (!NT_STATUS_IS_OK(status
)) {
945 if (creds_domain
!= domain
) {
947 * We can only use schannel against a direct trust
949 cli_credentials_set_secure_channel_type(creds
,
958 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
961 status
= cm_get_ipc_credentials(mem_ctx
, &creds
);
962 if (!NT_STATUS_IS_OK(status
)) {
970 /************************************************************************
971 Given a fd with a just-connected TCP connection to a DC, open a connection
973 ************************************************************************/
975 static NTSTATUS
cm_prepare_connection(struct winbindd_domain
*domain
,
977 const char *controller
,
978 struct cli_state
**cli
,
981 bool try_ipc_auth
= false;
982 const char *machine_principal
= NULL
;
983 const char *machine_realm
= NULL
;
984 const char *machine_account
= NULL
;
985 const char *machine_domain
= NULL
;
987 struct cli_credentials
*creds
= NULL
;
989 struct named_mutex
*mutex
;
991 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
993 NTSTATUS tcon_status
= NT_STATUS_NETWORK_NAME_DELETED
;
995 enum smb_signing_setting smb_sign_client_connections
= lp_client_ipc_signing();
997 if (smb_sign_client_connections
== SMB_SIGNING_DEFAULT
) {
999 * If we are connecting to our own AD domain, require
1000 * smb signing to disrupt MITM attacks
1002 if (domain
->primary
&& lp_security() == SEC_ADS
) {
1003 smb_sign_client_connections
= SMB_SIGNING_REQUIRED
;
1005 * If we are in or are an AD domain and connecting to another
1006 * AD domain in our forest
1007 * then require smb signing to disrupt MITM attacks
1009 } else if ((lp_security() == SEC_ADS
||
1010 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
)
1011 && domain
->active_directory
1012 && (domain
->domain_trust_attribs
1013 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
)) {
1014 smb_sign_client_connections
= SMB_SIGNING_REQUIRED
;
1018 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1019 controller
, domain
->name
));
1023 mutex
= grab_named_mutex(talloc_tos(), controller
,
1024 WINBIND_SERVER_MUTEX_WAIT_TIME
);
1025 if (mutex
== NULL
) {
1027 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1029 result
= NT_STATUS_POSSIBLE_DEADLOCK
;
1033 *cli
= cli_state_create(NULL
, sockfd
, controller
,
1034 smb_sign_client_connections
, flags
);
1037 DEBUG(1, ("Could not cli_initialize\n"));
1038 result
= NT_STATUS_NO_MEMORY
;
1042 cli_set_timeout(*cli
, 10000); /* 10 seconds */
1044 set_socket_options(sockfd
, lp_socket_options());
1046 result
= smbXcli_negprot((*cli
)->conn
, (*cli
)->timeout
,
1047 lp_client_ipc_min_protocol(),
1048 lp_client_ipc_max_protocol());
1050 if (!NT_STATUS_IS_OK(result
)) {
1051 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result
)));
1055 if (smbXcli_conn_protocol((*cli
)->conn
) >= PROTOCOL_NT1
&&
1056 smb1cli_conn_capabilities((*cli
)->conn
) & CAP_EXTENDED_SECURITY
) {
1057 try_ipc_auth
= true;
1058 } else if (smbXcli_conn_protocol((*cli
)->conn
) >= PROTOCOL_SMB2_02
) {
1059 try_ipc_auth
= true;
1060 } else if (smb_sign_client_connections
== SMB_SIGNING_REQUIRED
) {
1062 * If we are forcing on SMB signing, then we must
1063 * require authentication unless this is a one-way
1064 * trust, and we have no stored user/password
1066 try_ipc_auth
= true;
1070 result
= get_trust_credentials(domain
, talloc_tos(), false, &creds
);
1071 if (!NT_STATUS_IS_OK(result
)) {
1072 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1073 domain
->name
, nt_errstr(result
)));
1078 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1079 * would try and authentication with our machine
1080 * account password and fail. This is very rare in
1081 * the modern world however
1083 creds
= cli_credentials_init_anon(talloc_tos());
1084 if (creds
== NULL
) {
1085 result
= NT_STATUS_NO_MEMORY
;
1086 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1087 domain
->name
, nt_errstr(result
)));
1092 machine_principal
= cli_credentials_get_principal(creds
,
1094 machine_realm
= cli_credentials_get_realm(creds
);
1095 machine_account
= cli_credentials_get_username(creds
);
1096 machine_domain
= cli_credentials_get_domain(creds
);
1098 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1099 "[%s] and realm [%s]\n",
1100 controller
, domain
->name
, domain
->alt_name
,
1101 machine_domain
, machine_account
,
1102 machine_principal
, machine_realm
));
1104 if (cli_credentials_is_anonymous(creds
)) {
1108 winbindd_set_locator_kdc_envs(domain
);
1110 result
= cli_session_setup_creds(*cli
, creds
);
1111 if (NT_STATUS_IS_OK(result
)) {
1112 goto session_setup_done
;
1115 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1117 cli_credentials_get_unparsed_name(creds
, talloc_tos()),
1118 nt_errstr(result
)));
1121 * If we are not going to validiate the conneciton
1122 * with SMB signing, then allow us to fall back to
1125 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
)
1126 || NT_STATUS_EQUAL(result
, NT_STATUS_TRUSTED_DOMAIN_FAILURE
)
1127 || NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_ACCOUNT_NAME
)
1128 || NT_STATUS_EQUAL(result
, NT_STATUS_NO_LOGON_SERVERS
)
1129 || NT_STATUS_EQUAL(result
, NT_STATUS_LOGON_FAILURE
))
1131 if (!cm_is_ipc_credentials(creds
)) {
1135 if (smb_sign_client_connections
== SMB_SIGNING_REQUIRED
) {
1146 tmp_status
= cm_get_ipc_credentials(talloc_tos(), &creds
);
1147 if (!NT_STATUS_IS_OK(tmp_status
)) {
1148 result
= tmp_status
;
1152 if (cli_credentials_is_anonymous(creds
)) {
1156 machine_account
= cli_credentials_get_username(creds
);
1157 machine_domain
= cli_credentials_get_domain(creds
);
1159 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1160 "[%s]\\[%s]\n", controller
, lp_netbios_name(),
1161 machine_domain
, machine_account
));
1163 result
= cli_session_setup_creds(*cli
, creds
);
1164 if (NT_STATUS_IS_OK(result
)) {
1165 goto session_setup_done
;
1168 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1170 cli_credentials_get_unparsed_name(creds
, talloc_tos()),
1171 nt_errstr(result
)));
1174 * If we are not going to validiate the conneciton
1175 * with SMB signing, then allow us to fall back to
1178 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
)
1179 || NT_STATUS_EQUAL(result
, NT_STATUS_TRUSTED_DOMAIN_FAILURE
)
1180 || NT_STATUS_EQUAL(result
, NT_STATUS_INVALID_ACCOUNT_NAME
)
1181 || NT_STATUS_EQUAL(result
, NT_STATUS_NO_LOGON_SERVERS
)
1182 || NT_STATUS_EQUAL(result
, NT_STATUS_LOGON_FAILURE
))
1192 if (smb_sign_client_connections
== SMB_SIGNING_REQUIRED
) {
1196 /* Fall back to anonymous connection, this might fail later */
1197 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1198 "connection for DC %s\n",
1201 result
= cli_session_setup_anon(*cli
);
1202 if (NT_STATUS_IS_OK(result
)) {
1203 DEBUG(5, ("Connected anonymously\n"));
1204 goto session_setup_done
;
1207 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1208 controller
, nt_errstr(result
)));
1210 /* We can't session setup */
1217 * This should be a short term hack until
1218 * dynamic re-authentication is implemented.
1220 * See Bug 9175 - winbindd doesn't recover from
1221 * NT_STATUS_NETWORK_SESSION_EXPIRED
1223 if (smbXcli_conn_protocol((*cli
)->conn
) >= PROTOCOL_SMB2_02
) {
1224 smbXcli_session_set_disconnect_expired((*cli
)->smb2
.session
);
1227 result
= cli_tree_connect(*cli
, "IPC$", "IPC", NULL
);
1228 if (!NT_STATUS_IS_OK(result
)) {
1229 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result
)));
1232 tcon_status
= result
;
1234 /* cache the server name for later connections */
1236 saf_store(domain
->name
, controller
);
1237 if (domain
->alt_name
) {
1238 saf_store(domain
->alt_name
, controller
);
1241 winbindd_set_locator_kdc_envs(domain
);
1246 result
= NT_STATUS_OK
;
1252 if (NT_STATUS_IS_OK(result
)) {
1253 result
= tcon_status
;
1256 if (!NT_STATUS_IS_OK(result
)) {
1257 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1258 controller
, nt_errstr(result
)));
1259 winbind_add_failed_connection_entry(domain
, controller
, result
);
1260 if ((*cli
) != NULL
) {
1269 /*******************************************************************
1270 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1273 Keeps the list unique by not adding duplicate entries.
1275 @param[in] mem_ctx talloc memory context to allocate from
1276 @param[in] domain_name domain of the DC
1277 @param[in] dcname name of the DC to add to the list
1278 @param[in] pss Internet address and port pair to add to the list
1279 @param[in,out] dcs array of dc_name_ip structures to add to
1280 @param[in,out] num_dcs number of dcs returned in the dcs array
1281 @return true if the list was added to, false otherwise
1282 *******************************************************************/
1284 static bool add_one_dc_unique(TALLOC_CTX
*mem_ctx
, const char *domain_name
,
1285 const char *dcname
, struct sockaddr_storage
*pss
,
1286 struct dc_name_ip
**dcs
, int *num
)
1290 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name
, dcname
))) {
1291 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname
));
1295 /* Make sure there's no duplicates in the list */
1296 for (i
=0; i
<*num
; i
++)
1298 (struct sockaddr
*)(void *)&(*dcs
)[i
].ss
,
1299 (struct sockaddr
*)(void *)pss
))
1302 *dcs
= talloc_realloc(mem_ctx
, *dcs
, struct dc_name_ip
, (*num
)+1);
1307 fstrcpy((*dcs
)[*num
].name
, dcname
);
1308 (*dcs
)[*num
].ss
= *pss
;
1313 static bool add_sockaddr_to_array(TALLOC_CTX
*mem_ctx
,
1314 struct sockaddr_storage
*pss
, uint16_t port
,
1315 struct sockaddr_storage
**addrs
, int *num
)
1317 *addrs
= talloc_realloc(mem_ctx
, *addrs
, struct sockaddr_storage
, (*num
)+1);
1319 if (*addrs
== NULL
) {
1324 (*addrs
)[*num
] = *pss
;
1325 set_sockaddr_port((struct sockaddr
*)&(*addrs
)[*num
], port
);
1331 /*******************************************************************
1332 convert an ip to a name
1333 For an AD Domain, it checks the requirements of the request flags.
1334 *******************************************************************/
1336 static bool dcip_check_name(TALLOC_CTX
*mem_ctx
,
1337 const struct winbindd_domain
*domain
,
1338 struct sockaddr_storage
*pss
,
1339 char **name
, uint32_t request_flags
)
1341 struct ip_service ip_list
;
1342 uint32_t nt_version
= NETLOGON_NT_VERSION_1
;
1344 const char *dc_name
;
1347 bool is_ad_domain
= false;
1353 /* For active directory servers, try to get the ldap server name.
1354 None of these failures should be considered critical for now */
1356 if ((lp_security() == SEC_ADS
) && (domain
->alt_name
!= NULL
)) {
1357 is_ad_domain
= true;
1358 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
1359 is_ad_domain
= domain
->active_directory
;
1364 ADS_STATUS ads_status
;
1365 char addr
[INET6_ADDRSTRLEN
];
1367 print_sockaddr(addr
, sizeof(addr
), pss
);
1369 ads
= ads_init(domain
->alt_name
, domain
->name
, addr
);
1370 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
1371 ads
->config
.flags
|= request_flags
;
1372 ads
->server
.no_fallback
= true;
1374 ads_status
= ads_connect(ads
);
1375 if (ADS_ERR_OK(ads_status
)) {
1376 /* We got a cldap packet. */
1377 *name
= talloc_strdup(mem_ctx
,
1378 ads
->config
.ldap_server_name
);
1379 if (*name
== NULL
) {
1382 namecache_store(*name
, 0x20, 1, &ip_list
);
1384 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads
->config
.flags
));
1386 if (domain
->primary
&& (ads
->config
.flags
& NBT_SERVER_KDC
)) {
1387 if (ads_closest_dc(ads
)) {
1388 char *sitename
= sitename_fetch(mem_ctx
, ads
->config
.realm
);
1390 /* We're going to use this KDC for this realm/domain.
1391 If we are using sites, then force the krb5 libs
1394 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1399 TALLOC_FREE(sitename
);
1401 /* use an off site KDC */
1402 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1407 winbindd_set_locator_kdc_envs(domain
);
1409 /* Ensure we contact this DC also. */
1410 saf_store(domain
->name
, *name
);
1411 saf_store(domain
->alt_name
, *name
);
1414 ads_destroy( &ads
);
1418 ads_destroy( &ads
);
1423 status
= nbt_getdc(winbind_messaging_context(), 10, pss
, domain
->name
,
1424 &domain
->sid
, nt_version
, mem_ctx
, &nt_version
,
1426 if (NT_STATUS_IS_OK(status
)) {
1427 *name
= talloc_strdup(mem_ctx
, dc_name
);
1428 if (*name
== NULL
) {
1431 namecache_store(*name
, 0x20, 1, &ip_list
);
1435 /* try node status request */
1437 if (name_status_find(domain
->name
, 0x1c, 0x20, pss
, nbtname
) ) {
1438 namecache_store(nbtname
, 0x20, 1, &ip_list
);
1441 *name
= talloc_strdup(mem_ctx
, nbtname
);
1442 if (*name
== NULL
) {
1452 /*******************************************************************
1453 Retrieve a list of IP addresses for domain controllers.
1455 The array is sorted in the preferred connection order.
1457 @param[in] mem_ctx talloc memory context to allocate from
1458 @param[in] domain domain to retrieve DCs for
1459 @param[out] dcs array of dcs that will be returned
1460 @param[out] num_dcs number of dcs returned in the dcs array
1462 *******************************************************************/
1464 static bool get_dcs(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
1465 struct dc_name_ip
**dcs
, int *num_dcs
,
1466 uint32_t request_flags
)
1469 struct sockaddr_storage ss
;
1470 struct ip_service
*ip_list
= NULL
;
1471 int iplist_size
= 0;
1474 enum security_types sec
= (enum security_types
)lp_security();
1476 is_our_domain
= strequal(domain
->name
, lp_workgroup());
1478 /* If not our domain, get the preferred DC, by asking our primary DC */
1480 && get_dc_name_via_netlogon(domain
, dcname
, &ss
, request_flags
)
1481 && add_one_dc_unique(mem_ctx
, domain
->name
, dcname
, &ss
, dcs
,
1484 char addr
[INET6_ADDRSTRLEN
];
1485 print_sockaddr(addr
, sizeof(addr
), &ss
);
1486 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1491 if ((sec
== SEC_ADS
) && (domain
->alt_name
!= NULL
)) {
1492 char *sitename
= NULL
;
1494 /* We need to make sure we know the local site before
1495 doing any DNS queries, as this will restrict the
1496 get_sorted_dc_list() call below to only fetching
1497 DNS records for the correct site. */
1499 /* Find any DC to get the site record.
1500 We deliberately don't care about the
1503 get_dc_name(domain
->name
, domain
->alt_name
, dcname
, &ss
);
1505 sitename
= sitename_fetch(mem_ctx
, domain
->alt_name
);
1508 /* Do the site-specific AD dns lookup first. */
1509 get_sorted_dc_list(domain
->alt_name
, sitename
, &ip_list
,
1510 &iplist_size
, True
);
1512 /* Add ips to the DC array. We don't look up the name
1513 of the DC in this function, but we fill in the char*
1514 of the ip now to make the failed connection cache
1516 for ( i
=0; i
<iplist_size
; i
++ ) {
1517 char addr
[INET6_ADDRSTRLEN
];
1518 print_sockaddr(addr
, sizeof(addr
),
1520 add_one_dc_unique(mem_ctx
,
1529 TALLOC_FREE(sitename
);
1533 /* Now we add DCs from the main AD DNS lookup. */
1534 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
,
1535 &iplist_size
, True
);
1537 for ( i
=0; i
<iplist_size
; i
++ ) {
1538 char addr
[INET6_ADDRSTRLEN
];
1539 print_sockaddr(addr
, sizeof(addr
),
1541 add_one_dc_unique(mem_ctx
,
1553 /* Try standard netbios queries if no ADS and fall back to DNS queries
1554 * if alt_name is available */
1555 if (*num_dcs
== 0) {
1556 get_sorted_dc_list(domain
->name
, NULL
, &ip_list
, &iplist_size
,
1558 if (iplist_size
== 0) {
1559 if (domain
->alt_name
!= NULL
) {
1560 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
,
1561 &iplist_size
, true);
1565 for ( i
=0; i
<iplist_size
; i
++ ) {
1566 char addr
[INET6_ADDRSTRLEN
];
1567 print_sockaddr(addr
, sizeof(addr
),
1569 add_one_dc_unique(mem_ctx
,
1584 /*******************************************************************
1585 Find and make a connection to a DC in the given domain.
1587 @param[in] mem_ctx talloc memory context to allocate from
1588 @param[in] domain domain to find a dc in
1589 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1590 @param[out] pss DC Internet address and port
1591 @param[out] fd fd of the open socket connected to the newly found dc
1592 @return true when a DC connection is made, false otherwise
1593 *******************************************************************/
1595 static bool find_new_dc(TALLOC_CTX
*mem_ctx
,
1596 struct winbindd_domain
*domain
,
1597 char **dcname
, struct sockaddr_storage
*pss
, int *fd
,
1598 uint32_t request_flags
)
1600 struct dc_name_ip
*dcs
= NULL
;
1603 const char **dcnames
= NULL
;
1604 size_t num_dcnames
= 0;
1606 struct sockaddr_storage
*addrs
= NULL
;
1617 if (!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
, request_flags
) || (num_dcs
== 0))
1620 for (i
=0; i
<num_dcs
; i
++) {
1622 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1623 &dcnames
, &num_dcnames
)) {
1626 if (!add_sockaddr_to_array(mem_ctx
, &dcs
[i
].ss
, TCP_SMB_PORT
,
1627 &addrs
, &num_addrs
)) {
1632 if ((num_dcnames
== 0) || (num_dcnames
!= num_addrs
))
1635 if ((addrs
== NULL
) || (dcnames
== NULL
))
1638 status
= smbsock_any_connect(addrs
, dcnames
, NULL
, NULL
, NULL
,
1639 num_addrs
, 0, 10, fd
, &fd_index
, NULL
);
1640 if (!NT_STATUS_IS_OK(status
)) {
1641 for (i
=0; i
<num_dcs
; i
++) {
1642 char ab
[INET6_ADDRSTRLEN
];
1643 print_sockaddr(ab
, sizeof(ab
), &dcs
[i
].ss
);
1644 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1645 "domain %s address %s. Error was %s\n",
1646 domain
->name
, ab
, nt_errstr(status
) ));
1647 winbind_add_failed_connection_entry(domain
,
1648 dcs
[i
].name
, NT_STATUS_UNSUCCESSFUL
);
1653 *pss
= addrs
[fd_index
];
1655 if (*dcnames
[fd_index
] != '\0' && !is_ipaddress(dcnames
[fd_index
])) {
1656 /* Ok, we've got a name for the DC */
1657 *dcname
= talloc_strdup(mem_ctx
, dcnames
[fd_index
]);
1658 if (*dcname
== NULL
) {
1664 /* Try to figure out the name */
1665 if (dcip_check_name(mem_ctx
, domain
, pss
, dcname
, request_flags
)) {
1669 /* We can not continue without the DC's name */
1670 winbind_add_failed_connection_entry(domain
, dcs
[fd_index
].name
,
1671 NT_STATUS_UNSUCCESSFUL
);
1673 /* Throw away all arrays as we're doing this again. */
1677 TALLOC_FREE(dcnames
);
1689 static char *current_dc_key(TALLOC_CTX
*mem_ctx
, const char *domain_name
)
1691 return talloc_asprintf_strupper_m(mem_ctx
, "CURRENT_DCNAME/%s",
1695 static void store_current_dc_in_gencache(const char *domain_name
,
1696 const char *dc_name
,
1697 struct cli_state
*cli
)
1699 char addr
[INET6_ADDRSTRLEN
];
1703 if (!cli_state_is_connected(cli
)) {
1707 print_sockaddr(addr
, sizeof(addr
),
1708 smbXcli_conn_remote_sockaddr(cli
->conn
));
1710 key
= current_dc_key(talloc_tos(), domain_name
);
1715 value
= talloc_asprintf(talloc_tos(), "%s %s", addr
, dc_name
);
1716 if (value
== NULL
) {
1720 gencache_set(key
, value
, 0x7fffffff);
1726 bool fetch_current_dc_from_gencache(TALLOC_CTX
*mem_ctx
,
1727 const char *domain_name
,
1728 char **p_dc_name
, char **p_dc_ip
)
1733 char *dc_name
= NULL
;
1736 key
= current_dc_key(talloc_tos(), domain_name
);
1740 if (!gencache_get(key
, mem_ctx
, &value
, NULL
)) {
1743 p
= strchr(value
, ' ');
1747 dc_ip
= talloc_strndup(mem_ctx
, value
, p
- value
);
1748 if (dc_ip
== NULL
) {
1751 dc_name
= talloc_strdup(mem_ctx
, p
+1);
1752 if (dc_name
== NULL
) {
1756 if (p_dc_ip
!= NULL
) {
1760 if (p_dc_name
!= NULL
) {
1761 *p_dc_name
= dc_name
;
1766 TALLOC_FREE(dc_name
);
1773 NTSTATUS
wb_open_internal_pipe(TALLOC_CTX
*mem_ctx
,
1774 const struct ndr_interface_table
*table
,
1775 struct rpc_pipe_client
**ret_pipe
)
1777 struct rpc_pipe_client
*cli
= NULL
;
1778 const struct auth_session_info
*session_info
;
1779 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
1782 session_info
= get_session_info_system();
1783 SMB_ASSERT(session_info
!= NULL
);
1785 /* create a connection to the specified pipe */
1786 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1787 status
= rpc_pipe_open_interface(mem_ctx
,
1792 winbind_messaging_context(),
1795 status
= rpc_pipe_open_internal(mem_ctx
,
1800 winbind_messaging_context(),
1803 if (!NT_STATUS_IS_OK(status
)) {
1804 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1805 table
->name
, nt_errstr(status
)));
1813 return NT_STATUS_OK
;
1816 static NTSTATUS
cm_open_connection(struct winbindd_domain
*domain
,
1817 struct winbindd_cm_conn
*new_conn
,
1820 TALLOC_CTX
*mem_ctx
;
1822 char *saf_servername
;
1824 uint32_t request_flags
= need_rw_dc
? DS_WRITABLE_REQUIRED
: 0;
1826 if ((mem_ctx
= talloc_init("cm_open_connection")) == NULL
) {
1827 set_domain_offline(domain
);
1828 return NT_STATUS_NO_MEMORY
;
1831 saf_servername
= saf_fetch(mem_ctx
, domain
->name
);
1833 /* we have to check the server affinity cache here since
1834 later we select a DC based on response time and not preference */
1836 /* Check the negative connection cache
1837 before talking to it. It going down may have
1838 triggered the reconnection. */
1840 if (saf_servername
&& NT_STATUS_IS_OK(check_negative_conn_cache(domain
->name
, saf_servername
))) {
1841 struct sockaddr_storage ss
;
1842 char *dcname
= NULL
;
1843 bool resolved
= true;
1845 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1846 saf_servername
, domain
->name
));
1848 /* convert an ip address to a name */
1849 if (is_ipaddress(saf_servername
)) {
1850 if (!interpret_string_addr(&ss
, saf_servername
,
1852 TALLOC_FREE(mem_ctx
);
1853 return NT_STATUS_UNSUCCESSFUL
;
1856 if (!resolve_name(saf_servername
, &ss
, 0x20, true)) {
1861 if (resolved
&& dcip_check_name(mem_ctx
, domain
, &ss
, &dcname
, request_flags
)) {
1862 domain
->dcname
= talloc_strdup(domain
,
1864 if (domain
->dcname
== NULL
) {
1865 TALLOC_FREE(mem_ctx
);
1866 return NT_STATUS_NO_MEMORY
;
1869 domain
->dcaddr
= ss
;
1871 winbind_add_failed_connection_entry(domain
, saf_servername
,
1872 NT_STATUS_UNSUCCESSFUL
);
1876 for (retries
= 0; retries
< 3; retries
++) {
1879 char *dcname
= NULL
;
1881 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1883 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1884 domain
->dcname
? domain
->dcname
: "", domain
->name
));
1886 if (domain
->dcname
!= NULL
&&
1887 NT_STATUS_IS_OK(check_negative_conn_cache(domain
->name
,
1892 status
= smbsock_connect(&domain
->dcaddr
, 0,
1895 if (!NT_STATUS_IS_OK(status
)) {
1901 !find_new_dc(mem_ctx
, domain
, &dcname
, &domain
->dcaddr
, &fd
, request_flags
))
1903 /* This is the one place where we will
1904 set the global winbindd offline state
1905 to true, if a "WINBINDD_OFFLINE" entry
1906 is found in the winbindd cache. */
1907 set_global_winbindd_state_offline();
1910 if (dcname
!= NULL
) {
1911 talloc_free(domain
->dcname
);
1913 domain
->dcname
= talloc_move(domain
, &dcname
);
1914 if (domain
->dcname
== NULL
) {
1915 result
= NT_STATUS_NO_MEMORY
;
1920 new_conn
->cli
= NULL
;
1922 result
= cm_prepare_connection(domain
, fd
, domain
->dcname
,
1923 &new_conn
->cli
, &retry
);
1924 if (!NT_STATUS_IS_OK(result
)) {
1925 /* Don't leak the smb connection socket */
1933 if (NT_STATUS_IS_OK(result
)) {
1934 bool seal_pipes
= true;
1936 winbindd_set_locator_kdc_envs(domain
);
1938 if (domain
->online
== False
) {
1939 /* We're changing state from offline to online. */
1940 set_global_winbindd_state_online();
1942 set_domain_online(domain
);
1945 * Much as I hate global state, this seems to be the point
1946 * where we can be certain that we have a proper connection to
1947 * a DC. wbinfo --dc-info needs that information, store it in
1948 * gencache with a looong timeout. This will need revisiting
1949 * once we start to connect to multiple DCs, wbcDcInfo is
1950 * already prepared for that.
1952 store_current_dc_in_gencache(domain
->name
, domain
->dcname
,
1955 seal_pipes
= lp_winbind_sealed_pipes();
1956 seal_pipes
= lp_parm_bool(-1, "winbind sealed pipes",
1961 new_conn
->auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
1963 new_conn
->auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
1966 /* Ensure we setup the retry handler. */
1967 set_domain_offline(domain
);
1970 talloc_destroy(mem_ctx
);
1974 /* Close down all open pipes on a connection. */
1976 void invalidate_cm_connection(struct winbindd_domain
*domain
)
1979 struct winbindd_cm_conn
*conn
= &domain
->conn
;
1981 /* We're closing down a possibly dead
1982 connection. Don't have impossibly long (10s) timeouts. */
1985 cli_set_timeout(conn
->cli
, 1000); /* 1 second. */
1988 if (conn
->samr_pipe
!= NULL
) {
1989 if (is_valid_policy_hnd(&conn
->sam_connect_handle
)) {
1990 dcerpc_samr_Close(conn
->samr_pipe
->binding_handle
,
1992 &conn
->sam_connect_handle
,
1995 TALLOC_FREE(conn
->samr_pipe
);
1996 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1998 cli_set_timeout(conn
->cli
, 500);
2002 if (conn
->lsa_pipe
!= NULL
) {
2003 if (is_valid_policy_hnd(&conn
->lsa_policy
)) {
2004 dcerpc_lsa_Close(conn
->lsa_pipe
->binding_handle
,
2009 TALLOC_FREE(conn
->lsa_pipe
);
2010 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2012 cli_set_timeout(conn
->cli
, 500);
2016 if (conn
->lsa_pipe_tcp
!= NULL
) {
2017 if (is_valid_policy_hnd(&conn
->lsa_policy
)) {
2018 dcerpc_lsa_Close(conn
->lsa_pipe_tcp
->binding_handle
,
2023 TALLOC_FREE(conn
->lsa_pipe_tcp
);
2024 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2026 cli_set_timeout(conn
->cli
, 500);
2030 if (conn
->netlogon_pipe
!= NULL
) {
2031 TALLOC_FREE(conn
->netlogon_pipe
);
2032 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2034 cli_set_timeout(conn
->cli
, 500);
2038 conn
->auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
2039 conn
->netlogon_force_reauth
= false;
2040 conn
->netlogon_flags
= 0;
2041 TALLOC_FREE(conn
->netlogon_creds
);
2044 cli_shutdown(conn
->cli
);
2050 void close_conns_after_fork(void)
2052 struct winbindd_domain
*domain
;
2053 struct winbindd_cli_state
*cli_state
;
2055 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
2057 * first close the low level SMB TCP connection
2058 * so that we don't generate any SMBclose
2059 * requests in invalidate_cm_connection()
2061 if (cli_state_is_connected(domain
->conn
.cli
)) {
2062 smbXcli_conn_disconnect(domain
->conn
.cli
->conn
, NT_STATUS_OK
);
2065 invalidate_cm_connection(domain
);
2068 for (cli_state
= winbindd_client_list();
2070 cli_state
= cli_state
->next
) {
2071 if (cli_state
->sock
>= 0) {
2072 close(cli_state
->sock
);
2073 cli_state
->sock
= -1;
2078 static bool connection_ok(struct winbindd_domain
*domain
)
2082 ok
= cli_state_is_connected(domain
->conn
.cli
);
2084 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2085 domain
->dcname
, domain
->name
));
2089 if (domain
->online
== False
) {
2090 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain
->name
));
2097 /* Initialize a new connection up to the RPC BIND.
2098 Bypass online status check so always does network calls. */
2100 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
, bool need_rw_dc
)
2103 bool skip_connection
= domain
->internal
;
2104 if (need_rw_dc
&& domain
->rodc
) {
2105 skip_connection
= false;
2108 /* Internal connections never use the network. */
2109 if (dom_sid_equal(&domain
->sid
, &global_sid_Builtin
)) {
2110 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2113 /* Still ask the internal LSA and SAMR server about the local domain */
2114 if (skip_connection
|| connection_ok(domain
)) {
2115 if (!domain
->initialized
) {
2116 set_dc_type_and_flags(domain
);
2118 return NT_STATUS_OK
;
2121 invalidate_cm_connection(domain
);
2123 if (!domain
->primary
&& !domain
->initialized
) {
2125 * Before we connect to a trust, work out if it is an
2126 * AD domain by asking our own domain.
2128 set_dc_type_and_flags_trustinfo(domain
);
2131 result
= cm_open_connection(domain
, &domain
->conn
, need_rw_dc
);
2133 if (NT_STATUS_IS_OK(result
) && !domain
->initialized
) {
2134 set_dc_type_and_flags(domain
);
2140 NTSTATUS
init_dc_connection(struct winbindd_domain
*domain
, bool need_rw_dc
)
2142 if (dom_sid_equal(&domain
->sid
, &global_sid_Builtin
)) {
2143 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2146 if (domain
->initialized
&& !domain
->online
) {
2147 /* We check for online status elsewhere. */
2148 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
2151 return init_dc_connection_network(domain
, need_rw_dc
);
2154 static NTSTATUS
init_dc_connection_rpc(struct winbindd_domain
*domain
, bool need_rw_dc
)
2158 status
= init_dc_connection(domain
, need_rw_dc
);
2159 if (!NT_STATUS_IS_OK(status
)) {
2163 if (!domain
->internal
&& domain
->conn
.cli
== NULL
) {
2164 /* happens for trusted domains without inbound trust */
2165 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
2168 return NT_STATUS_OK
;
2171 /******************************************************************************
2172 Set the trust flags (direction and forest location) for a domain
2173 ******************************************************************************/
2175 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain
*domain
)
2177 struct winbindd_domain
*our_domain
;
2178 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2180 struct netr_DomainTrustList trusts
;
2182 uint32_t flags
= (NETR_TRUST_FLAG_IN_FOREST
|
2183 NETR_TRUST_FLAG_OUTBOUND
|
2184 NETR_TRUST_FLAG_INBOUND
);
2185 struct rpc_pipe_client
*cli
;
2186 TALLOC_CTX
*mem_ctx
= NULL
;
2187 struct dcerpc_binding_handle
*b
;
2189 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain
->name
));
2191 /* Our primary domain doesn't need to worry about trust flags.
2192 Force it to go through the network setup */
2193 if ( domain
->primary
) {
2197 mem_ctx
= talloc_stackframe();
2198 our_domain
= find_our_domain();
2199 if (our_domain
->internal
) {
2200 result
= init_dc_connection(our_domain
, false);
2201 if (!NT_STATUS_IS_OK(result
)) {
2202 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2203 "Not able to make a connection to our domain: %s\n",
2204 nt_errstr(result
)));
2205 TALLOC_FREE(mem_ctx
);
2210 /* This won't work unless our domain is AD */
2211 if ( !our_domain
->active_directory
) {
2212 TALLOC_FREE(mem_ctx
);
2216 if (our_domain
->internal
) {
2217 result
= wb_open_internal_pipe(mem_ctx
, &ndr_table_netlogon
, &cli
);
2218 } else if (!connection_ok(our_domain
)) {
2219 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2220 "No connection to our domain!\n"));
2221 TALLOC_FREE(mem_ctx
);
2224 result
= cm_connect_netlogon(our_domain
, &cli
);
2227 if (!NT_STATUS_IS_OK(result
)) {
2228 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2229 "a connection to %s for PIPE_NETLOGON (%s)\n",
2230 domain
->name
, nt_errstr(result
)));
2231 TALLOC_FREE(mem_ctx
);
2234 b
= cli
->binding_handle
;
2236 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2237 result
= dcerpc_netr_DsrEnumerateDomainTrusts(b
, mem_ctx
,
2242 if (!NT_STATUS_IS_OK(result
)) {
2243 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2244 "failed to query trusted domain list: %s\n",
2245 nt_errstr(result
)));
2246 TALLOC_FREE(mem_ctx
);
2249 if (!W_ERROR_IS_OK(werr
)) {
2250 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2251 "failed to query trusted domain list: %s\n",
2253 TALLOC_FREE(mem_ctx
);
2257 /* Now find the domain name and get the flags */
2259 for ( i
=0; i
<trusts
.count
; i
++ ) {
2260 if ( strequal( domain
->name
, trusts
.array
[i
].netbios_name
) ) {
2261 domain
->domain_flags
= trusts
.array
[i
].trust_flags
;
2262 domain
->domain_type
= trusts
.array
[i
].trust_type
;
2263 domain
->domain_trust_attribs
= trusts
.array
[i
].trust_attributes
;
2265 if ( domain
->domain_type
== LSA_TRUST_TYPE_UPLEVEL
)
2266 domain
->active_directory
= True
;
2268 /* This flag is only set if the domain is *our*
2269 primary domain and the primary domain is in
2272 domain
->native_mode
= (domain
->domain_flags
& NETR_TRUST_FLAG_NATIVE
);
2274 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2275 "native mode.\n", domain
->name
,
2276 domain
->native_mode
? "" : "NOT "));
2278 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2279 "running active directory.\n", domain
->name
,
2280 domain
->active_directory
? "" : "NOT "));
2282 domain
->can_do_ncacn_ip_tcp
= domain
->active_directory
;
2284 domain
->initialized
= True
;
2290 TALLOC_FREE(mem_ctx
);
2292 return domain
->initialized
;
2295 /******************************************************************************
2296 We can 'sense' certain things about the DC by it's replies to certain
2299 This tells us if this particular remote server is Active Directory, and if it
2301 ******************************************************************************/
2303 static void set_dc_type_and_flags_connect( struct winbindd_domain
*domain
)
2305 NTSTATUS status
, result
;
2307 TALLOC_CTX
*mem_ctx
= NULL
;
2308 struct rpc_pipe_client
*cli
= NULL
;
2309 struct policy_handle pol
;
2310 union dssetup_DsRoleInfo info
;
2311 union lsa_PolicyInformation
*lsa_info
= NULL
;
2313 if (!domain
->internal
&& !connection_ok(domain
)) {
2317 mem_ctx
= talloc_init("set_dc_type_and_flags on domain %s\n",
2320 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2324 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain
->name
));
2326 if (domain
->internal
) {
2327 status
= wb_open_internal_pipe(mem_ctx
,
2331 status
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
2336 if (!NT_STATUS_IS_OK(status
)) {
2337 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2338 "PI_DSSETUP on domain %s: (%s)\n",
2339 domain
->name
, nt_errstr(status
)));
2341 /* if this is just a non-AD domain we need to continue
2342 * identifying so that we can in the end return with
2343 * domain->initialized = True - gd */
2348 status
= dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli
->binding_handle
, mem_ctx
,
2349 DS_ROLE_BASIC_INFORMATION
,
2354 if (NT_STATUS_IS_OK(status
)) {
2355 result
= werror_to_ntstatus(werr
);
2357 if (!NT_STATUS_IS_OK(status
)) {
2358 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2359 "on domain %s failed: (%s)\n",
2360 domain
->name
, nt_errstr(status
)));
2362 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2363 * every opcode on the DSSETUP pipe, continue with
2364 * no_dssetup mode here as well to get domain->initialized
2367 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2371 TALLOC_FREE(mem_ctx
);
2375 if ((info
.basic
.flags
& DS_ROLE_PRIMARY_DS_RUNNING
) &&
2376 !(info
.basic
.flags
& DS_ROLE_PRIMARY_DS_MIXED_MODE
)) {
2377 domain
->native_mode
= True
;
2379 domain
->native_mode
= False
;
2383 if (domain
->internal
) {
2384 status
= wb_open_internal_pipe(mem_ctx
,
2388 status
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
2389 &ndr_table_lsarpc
, &cli
);
2391 if (!NT_STATUS_IS_OK(status
)) {
2392 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2393 "PI_LSARPC on domain %s: (%s)\n",
2394 domain
->name
, nt_errstr(status
)));
2396 TALLOC_FREE(mem_ctx
);
2400 status
= rpccli_lsa_open_policy2(cli
, mem_ctx
, True
,
2401 SEC_FLAG_MAXIMUM_ALLOWED
, &pol
);
2403 if (NT_STATUS_IS_OK(status
)) {
2404 /* This particular query is exactly what Win2k clients use
2405 to determine that the DC is active directory */
2406 status
= dcerpc_lsa_QueryInfoPolicy2(cli
->binding_handle
, mem_ctx
,
2408 LSA_POLICY_INFO_DNS
,
2413 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2414 domain
->active_directory
= True
;
2416 if (lsa_info
->dns
.name
.string
) {
2417 if (!strequal(domain
->name
, lsa_info
->dns
.name
.string
))
2419 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2420 "for domain %s claimed it was a DC "
2421 "for domain %s, refusing to "
2424 lsa_info
->dns
.name
.string
));
2426 TALLOC_FREE(mem_ctx
);
2429 talloc_free(domain
->name
);
2430 domain
->name
= talloc_strdup(domain
,
2431 lsa_info
->dns
.name
.string
);
2432 if (domain
->name
== NULL
) {
2437 if (lsa_info
->dns
.dns_domain
.string
) {
2438 if (domain
->alt_name
!= NULL
&&
2439 !strequal(domain
->alt_name
,
2440 lsa_info
->dns
.dns_domain
.string
))
2442 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2443 "for domain %s (%s) claimed it was "
2444 "a DC for domain %s, refusing to "
2446 domain
->alt_name
, domain
->name
,
2447 lsa_info
->dns
.dns_domain
.string
));
2449 TALLOC_FREE(mem_ctx
);
2452 talloc_free(domain
->alt_name
);
2454 talloc_strdup(domain
,
2455 lsa_info
->dns
.dns_domain
.string
);
2456 if (domain
->alt_name
== NULL
) {
2461 /* See if we can set some domain trust flags about
2464 if (lsa_info
->dns
.dns_forest
.string
) {
2465 talloc_free(domain
->forest_name
);
2466 domain
->forest_name
=
2467 talloc_strdup(domain
,
2468 lsa_info
->dns
.dns_forest
.string
);
2469 if (domain
->forest_name
== NULL
) {
2473 if (strequal(domain
->forest_name
, domain
->alt_name
)) {
2474 domain
->domain_flags
|= NETR_TRUST_FLAG_TREEROOT
;
2478 if (lsa_info
->dns
.sid
) {
2479 if (!is_null_sid(&domain
->sid
) &&
2480 !dom_sid_equal(&domain
->sid
,
2483 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2484 "for domain %s (%s) claimed it was "
2485 "a DC for domain %s, refusing to "
2487 dom_sid_string(talloc_tos(),
2490 dom_sid_string(talloc_tos(),
2491 lsa_info
->dns
.sid
)));
2493 TALLOC_FREE(mem_ctx
);
2496 sid_copy(&domain
->sid
, lsa_info
->dns
.sid
);
2499 domain
->active_directory
= False
;
2501 status
= rpccli_lsa_open_policy(cli
, mem_ctx
, True
,
2502 SEC_FLAG_MAXIMUM_ALLOWED
,
2505 if (!NT_STATUS_IS_OK(status
)) {
2509 status
= dcerpc_lsa_QueryInfoPolicy(cli
->binding_handle
, mem_ctx
,
2511 LSA_POLICY_INFO_ACCOUNT_DOMAIN
,
2514 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2516 if (lsa_info
->account_domain
.name
.string
) {
2517 if (!strequal(domain
->name
,
2518 lsa_info
->account_domain
.name
.string
))
2521 ("set_dc_type_and_flags_connect: "
2522 "DC for domain %s claimed it was"
2523 " a DC for domain %s, refusing "
2524 "to initialize\n", domain
->name
,
2526 account_domain
.name
.string
));
2528 TALLOC_FREE(mem_ctx
);
2531 talloc_free(domain
->name
);
2533 talloc_strdup(domain
,
2534 lsa_info
->account_domain
.name
.string
);
2537 if (lsa_info
->account_domain
.sid
) {
2538 if (!is_null_sid(&domain
->sid
) &&
2539 !dom_sid_equal(&domain
->sid
,
2540 lsa_info
->account_domain
.sid
))
2543 ("set_dc_type_and_flags_connect: "
2544 "DC for domain %s (%s) claimed "
2545 "it was a DC for domain %s, "
2546 "refusing to initialize\n",
2547 dom_sid_string(talloc_tos(),
2550 dom_sid_string(talloc_tos(),
2551 lsa_info
->account_domain
.sid
)));
2553 TALLOC_FREE(mem_ctx
);
2556 sid_copy(&domain
->sid
, lsa_info
->account_domain
.sid
);
2562 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2563 domain
->name
, domain
->native_mode
? "" : "NOT "));
2565 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2566 domain
->name
, domain
->active_directory
? "" : "NOT "));
2568 domain
->can_do_ncacn_ip_tcp
= domain
->active_directory
;
2572 TALLOC_FREE(mem_ctx
);
2574 domain
->initialized
= True
;
2577 /**********************************************************************
2578 Set the domain_flags (trust attributes, domain operating modes, etc...
2579 ***********************************************************************/
2581 static void set_dc_type_and_flags( struct winbindd_domain
*domain
)
2583 /* we always have to contact our primary domain */
2585 if ( domain
->primary
|| domain
->internal
) {
2586 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2587 "primary or internal domain\n"));
2588 set_dc_type_and_flags_connect( domain
);
2592 /* Use our DC to get the information if possible */
2594 if ( !set_dc_type_and_flags_trustinfo( domain
) ) {
2595 /* Otherwise, fallback to contacting the
2597 set_dc_type_and_flags_connect( domain
);
2605 /**********************************************************************
2606 ***********************************************************************/
2608 static NTSTATUS
cm_get_schannel_creds(struct winbindd_domain
*domain
,
2609 struct netlogon_creds_cli_context
**ppdc
)
2611 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2612 struct rpc_pipe_client
*netlogon_pipe
;
2616 if ((!IS_DC
) && (!domain
->primary
)) {
2617 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
2620 if (domain
->conn
.netlogon_creds
!= NULL
) {
2621 if (!(domain
->conn
.netlogon_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
2622 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
2624 *ppdc
= domain
->conn
.netlogon_creds
;
2625 return NT_STATUS_OK
;
2628 result
= cm_connect_netlogon(domain
, &netlogon_pipe
);
2629 if (!NT_STATUS_IS_OK(result
)) {
2633 if (domain
->conn
.netlogon_creds
== NULL
) {
2634 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
2637 if (!(domain
->conn
.netlogon_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
2638 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
2641 *ppdc
= domain
->conn
.netlogon_creds
;
2642 return NT_STATUS_OK
;
2645 NTSTATUS
cm_connect_sam(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
2647 struct rpc_pipe_client
**cli
, struct policy_handle
*sam_handle
)
2649 struct winbindd_cm_conn
*conn
;
2650 NTSTATUS status
, result
;
2651 struct netlogon_creds_cli_context
*p_creds
;
2652 struct cli_credentials
*creds
= NULL
;
2653 bool retry
= false; /* allow one retry attempt for expired session */
2655 if (sid_check_is_our_sam(&domain
->sid
)) {
2656 if (domain
->rodc
== false || need_rw_dc
== false) {
2657 return open_internal_samr_conn(mem_ctx
, domain
, cli
, sam_handle
);
2662 status
= init_dc_connection_rpc(domain
, need_rw_dc
);
2663 if (!NT_STATUS_IS_OK(status
)) {
2667 conn
= &domain
->conn
;
2669 if (rpccli_is_connected(conn
->samr_pipe
)) {
2673 TALLOC_FREE(conn
->samr_pipe
);
2676 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2677 * sign and sealed pipe using the machine account password by
2678 * preference. If we can't - try schannel, if that fails, try
2682 result
= get_trust_credentials(domain
, talloc_tos(), false, &creds
);
2683 if (!NT_STATUS_IS_OK(result
)) {
2684 DEBUG(10, ("cm_connect_sam: No user available for "
2685 "domain %s, trying schannel\n", domain
->name
));
2689 if (cli_credentials_is_anonymous(creds
)) {
2694 * We have an authenticated connection. Use a SPNEGO
2695 * authenticated SAMR pipe with sign & seal.
2697 status
= cli_rpc_pipe_open_with_creds(conn
->cli
,
2700 DCERPC_AUTH_TYPE_SPNEGO
,
2702 smbXcli_conn_remote_name(conn
->cli
->conn
),
2706 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
2708 invalidate_cm_connection(domain
);
2713 if (!NT_STATUS_IS_OK(status
)) {
2714 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2715 "pipe for domain %s using NTLMSSP "
2716 "authenticated pipe: user %s. Error was "
2717 "%s\n", domain
->name
,
2718 cli_credentials_get_unparsed_name(creds
, talloc_tos()),
2719 nt_errstr(status
)));
2723 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2724 "domain %s using NTLMSSP authenticated "
2725 "pipe: user %s\n", domain
->name
,
2726 cli_credentials_get_unparsed_name(creds
, talloc_tos())));
2728 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2729 conn
->samr_pipe
->desthost
,
2730 SEC_FLAG_MAXIMUM_ALLOWED
,
2731 &conn
->sam_connect_handle
,
2734 if (NT_STATUS_EQUAL(status
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
2735 invalidate_cm_connection(domain
);
2736 TALLOC_FREE(conn
->samr_pipe
);
2741 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2744 if (NT_STATUS_IS_OK(status
)) {
2748 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2749 "failed for domain %s, error was %s. Trying schannel\n",
2750 domain
->name
, nt_errstr(status
) ));
2751 TALLOC_FREE(conn
->samr_pipe
);
2755 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2757 status
= cm_get_schannel_creds(domain
, &p_creds
);
2758 if (!NT_STATUS_IS_OK(status
)) {
2759 /* If this call fails - conn->cli can now be NULL ! */
2760 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2761 "for domain %s (error %s), trying anon\n",
2763 nt_errstr(status
) ));
2767 result
= get_trust_credentials(domain
, talloc_tos(), true, &creds
);
2768 if (!NT_STATUS_IS_OK(result
)) {
2769 DEBUG(10, ("cm_connect_sam: No user available for "
2770 "domain %s (error %s), trying anon\n", domain
->name
,
2771 nt_errstr(result
)));
2774 status
= cli_rpc_pipe_open_schannel_with_creds
2775 (conn
->cli
, &ndr_table_samr
, NCACN_NP
,
2776 creds
, p_creds
, &conn
->samr_pipe
);
2778 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
2780 invalidate_cm_connection(domain
);
2785 if (!NT_STATUS_IS_OK(status
)) {
2786 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2787 "domain %s using schannel. Error was %s\n",
2788 domain
->name
, nt_errstr(status
) ));
2791 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2792 "schannel.\n", domain
->name
));
2794 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2795 conn
->samr_pipe
->desthost
,
2796 SEC_FLAG_MAXIMUM_ALLOWED
,
2797 &conn
->sam_connect_handle
,
2800 if (NT_STATUS_EQUAL(status
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
2801 invalidate_cm_connection(domain
);
2802 TALLOC_FREE(conn
->samr_pipe
);
2807 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2810 if (NT_STATUS_IS_OK(status
)) {
2813 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2814 "for domain %s, error was %s. Trying anonymous\n",
2815 domain
->name
, nt_errstr(status
) ));
2816 TALLOC_FREE(conn
->samr_pipe
);
2820 /* Finally fall back to anonymous. */
2821 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2822 status
= NT_STATUS_DOWNGRADE_DETECTED
;
2823 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2824 "without connection level security, "
2825 "must set 'winbind sealed pipes = false' and "
2826 "'require strong key = false' to proceed: %s\n",
2827 domain
->name
, nt_errstr(status
)));
2830 status
= cli_rpc_pipe_open_noauth(conn
->cli
, &ndr_table_samr
,
2833 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
2835 invalidate_cm_connection(domain
);
2840 if (!NT_STATUS_IS_OK(status
)) {
2844 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2845 conn
->samr_pipe
->desthost
,
2846 SEC_FLAG_MAXIMUM_ALLOWED
,
2847 &conn
->sam_connect_handle
,
2850 if (NT_STATUS_EQUAL(status
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
2851 invalidate_cm_connection(domain
);
2852 TALLOC_FREE(conn
->samr_pipe
);
2857 if (!NT_STATUS_IS_OK(status
)) {
2858 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2859 "for domain %s Error was %s\n",
2860 domain
->name
, nt_errstr(status
) ));
2863 if (!NT_STATUS_IS_OK(result
)) {
2865 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2866 "for domain %s Error was %s\n",
2867 domain
->name
, nt_errstr(result
)));
2872 status
= dcerpc_samr_OpenDomain(conn
->samr_pipe
->binding_handle
,
2874 &conn
->sam_connect_handle
,
2875 SEC_FLAG_MAXIMUM_ALLOWED
,
2877 &conn
->sam_domain_handle
,
2879 if (!NT_STATUS_IS_OK(status
)) {
2886 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
2888 * if we got access denied, we might just have no access rights
2889 * to talk to the remote samr server server (e.g. when we are a
2890 * PDC and we are connecting a w2k8 pdc via an interdomain
2891 * trust). In that case do not invalidate the whole connection
2894 TALLOC_FREE(conn
->samr_pipe
);
2895 ZERO_STRUCT(conn
->sam_domain_handle
);
2897 } else if (!NT_STATUS_IS_OK(status
)) {
2898 invalidate_cm_connection(domain
);
2902 *cli
= conn
->samr_pipe
;
2903 *sam_handle
= conn
->sam_domain_handle
;
2907 /**********************************************************************
2908 open an schanneld ncacn_ip_tcp connection to LSA
2909 ***********************************************************************/
2911 static NTSTATUS
cm_connect_lsa_tcp(struct winbindd_domain
*domain
,
2912 TALLOC_CTX
*mem_ctx
,
2913 struct rpc_pipe_client
**cli
)
2915 struct winbindd_cm_conn
*conn
;
2916 struct netlogon_creds_cli_context
*p_creds
= NULL
;
2917 struct cli_credentials
*creds
= NULL
;
2920 DEBUG(10,("cm_connect_lsa_tcp\n"));
2922 status
= init_dc_connection_rpc(domain
, false);
2923 if (!NT_STATUS_IS_OK(status
)) {
2927 conn
= &domain
->conn
;
2930 * rpccli_is_connected handles more error cases
2932 if (rpccli_is_connected(conn
->lsa_pipe_tcp
) &&
2933 conn
->lsa_pipe_tcp
->transport
->transport
== NCACN_IP_TCP
&&
2934 conn
->lsa_pipe_tcp
->auth
->auth_level
>= DCERPC_AUTH_LEVEL_INTEGRITY
) {
2938 TALLOC_FREE(conn
->lsa_pipe_tcp
);
2940 status
= cm_get_schannel_creds(domain
, &p_creds
);
2941 if (!NT_STATUS_IS_OK(status
)) {
2945 status
= get_trust_credentials(domain
, talloc_tos(), true, &creds
);
2946 if (!NT_STATUS_IS_OK(status
)) {
2950 status
= cli_rpc_pipe_open_schannel_with_creds(conn
->cli
,
2955 &conn
->lsa_pipe_tcp
);
2956 if (!NT_STATUS_IS_OK(status
)) {
2957 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2958 nt_errstr(status
)));
2963 if (!NT_STATUS_IS_OK(status
)) {
2964 TALLOC_FREE(conn
->lsa_pipe_tcp
);
2968 *cli
= conn
->lsa_pipe_tcp
;
2973 NTSTATUS
cm_connect_lsa(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
2974 struct rpc_pipe_client
**cli
, struct policy_handle
*lsa_policy
)
2976 struct winbindd_cm_conn
*conn
;
2977 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2978 struct netlogon_creds_cli_context
*p_creds
;
2979 struct cli_credentials
*creds
= NULL
;
2980 bool retry
= false; /* allow one retry attempt for expired session */
2983 result
= init_dc_connection_rpc(domain
, false);
2984 if (!NT_STATUS_IS_OK(result
))
2987 conn
= &domain
->conn
;
2989 if (rpccli_is_connected(conn
->lsa_pipe
)) {
2993 TALLOC_FREE(conn
->lsa_pipe
);
2995 result
= get_trust_credentials(domain
, talloc_tos(), false, &creds
);
2996 if (!NT_STATUS_IS_OK(result
)) {
2997 DEBUG(10, ("cm_connect_lsa: No user available for "
2998 "domain %s, trying schannel\n", domain
->name
));
3002 if (cli_credentials_is_anonymous(creds
)) {
3007 * We have an authenticated connection. Use a SPNEGO
3008 * authenticated LSA pipe with sign & seal.
3010 result
= cli_rpc_pipe_open_with_creds
3011 (conn
->cli
, &ndr_table_lsarpc
, NCACN_NP
,
3012 DCERPC_AUTH_TYPE_SPNEGO
,
3014 smbXcli_conn_remote_name(conn
->cli
->conn
),
3018 if (NT_STATUS_EQUAL(result
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
3020 invalidate_cm_connection(domain
);
3025 if (!NT_STATUS_IS_OK(result
)) {
3026 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3027 "domain %s using NTLMSSP authenticated pipe: user "
3028 "%s. Error was %s. Trying schannel.\n",
3030 cli_credentials_get_unparsed_name(creds
, talloc_tos()),
3031 nt_errstr(result
)));
3035 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3036 "NTLMSSP authenticated pipe: user %s\n",
3037 domain
->name
, cli_credentials_get_unparsed_name(creds
, talloc_tos())));
3039 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
3040 SEC_FLAG_MAXIMUM_ALLOWED
,
3042 if (NT_STATUS_EQUAL(result
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
3043 invalidate_cm_connection(domain
);
3044 TALLOC_FREE(conn
->lsa_pipe
);
3049 if (NT_STATUS_IS_OK(result
)) {
3053 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3056 TALLOC_FREE(conn
->lsa_pipe
);
3060 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3062 result
= cm_get_schannel_creds(domain
, &p_creds
);
3063 if (!NT_STATUS_IS_OK(result
)) {
3064 /* If this call fails - conn->cli can now be NULL ! */
3065 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3066 "for domain %s (error %s), trying anon\n",
3068 nt_errstr(result
) ));
3073 result
= get_trust_credentials(domain
, talloc_tos(), true, &creds
);
3074 if (!NT_STATUS_IS_OK(result
)) {
3075 DEBUG(10, ("cm_connect_lsa: No user available for "
3076 "domain %s (error %s), trying anon\n", domain
->name
,
3077 nt_errstr(result
)));
3080 result
= cli_rpc_pipe_open_schannel_with_creds
3081 (conn
->cli
, &ndr_table_lsarpc
, NCACN_NP
,
3082 creds
, p_creds
, &conn
->lsa_pipe
);
3084 if (NT_STATUS_EQUAL(result
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
3086 invalidate_cm_connection(domain
);
3091 if (!NT_STATUS_IS_OK(result
)) {
3092 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3093 "domain %s using schannel. Error was %s\n",
3094 domain
->name
, nt_errstr(result
) ));
3097 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3098 "schannel.\n", domain
->name
));
3100 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
3101 SEC_FLAG_MAXIMUM_ALLOWED
,
3104 if (NT_STATUS_EQUAL(result
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
3105 invalidate_cm_connection(domain
);
3106 TALLOC_FREE(conn
->lsa_pipe
);
3111 if (NT_STATUS_IS_OK(result
)) {
3115 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3118 TALLOC_FREE(conn
->lsa_pipe
);
3122 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3123 result
= NT_STATUS_DOWNGRADE_DETECTED
;
3124 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3125 "without connection level security, "
3126 "must set 'winbind sealed pipes = false' and "
3127 "'require strong key = false' to proceed: %s\n",
3128 domain
->name
, nt_errstr(result
)));
3132 result
= cli_rpc_pipe_open_noauth(conn
->cli
,
3136 if (NT_STATUS_EQUAL(result
, NT_STATUS_NETWORK_SESSION_EXPIRED
)
3138 invalidate_cm_connection(domain
);
3143 if (!NT_STATUS_IS_OK(result
)) {
3147 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
3148 SEC_FLAG_MAXIMUM_ALLOWED
,
3151 if (NT_STATUS_EQUAL(result
, NT_STATUS_IO_DEVICE_ERROR
) && !retry
) {
3152 invalidate_cm_connection(domain
);
3153 TALLOC_FREE(conn
->lsa_pipe
);
3159 if (!NT_STATUS_IS_OK(result
)) {
3160 invalidate_cm_connection(domain
);
3164 *cli
= conn
->lsa_pipe
;
3165 *lsa_policy
= conn
->lsa_policy
;
3169 /****************************************************************************
3170 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3171 ****************************************************************************/
3173 NTSTATUS
cm_connect_lsat(struct winbindd_domain
*domain
,
3174 TALLOC_CTX
*mem_ctx
,
3175 struct rpc_pipe_client
**cli
,
3176 struct policy_handle
*lsa_policy
)
3180 if (domain
->can_do_ncacn_ip_tcp
) {
3181 status
= cm_connect_lsa_tcp(domain
, mem_ctx
, cli
);
3182 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) ||
3183 NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
) ||
3184 NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
)) {
3185 invalidate_cm_connection(domain
);
3186 status
= cm_connect_lsa_tcp(domain
, mem_ctx
, cli
);
3188 if (NT_STATUS_IS_OK(status
)) {
3193 * we tried twice to connect via ncan_ip_tcp and schannel and
3194 * failed - maybe it is a trusted domain we can't connect to ?
3195 * do not try tcp next time - gd
3197 * This also prevents NETLOGON over TCP
3199 domain
->can_do_ncacn_ip_tcp
= false;
3202 status
= cm_connect_lsa(domain
, mem_ctx
, cli
, lsa_policy
);
3207 /****************************************************************************
3208 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
3209 session key stored in conn->netlogon_pipe->dc->sess_key.
3210 ****************************************************************************/
3212 static NTSTATUS
cm_connect_netlogon_transport(struct winbindd_domain
*domain
,
3213 enum dcerpc_transport_t transport
,
3214 struct rpc_pipe_client
**cli
)
3216 struct messaging_context
*msg_ctx
= winbind_messaging_context();
3217 struct winbindd_cm_conn
*conn
;
3219 enum netr_SchannelType sec_chan_type
;
3220 struct netlogon_creds_CredentialState
*netlogon_creds
= NULL
;
3221 struct cli_credentials
*creds
= NULL
;
3225 result
= init_dc_connection_rpc(domain
, domain
->rodc
);
3226 if (!NT_STATUS_IS_OK(result
)) {
3230 conn
= &domain
->conn
;
3232 if (rpccli_is_connected(conn
->netlogon_pipe
)) {
3233 *cli
= conn
->netlogon_pipe
;
3234 return NT_STATUS_OK
;
3237 TALLOC_FREE(conn
->netlogon_pipe
);
3238 conn
->netlogon_flags
= 0;
3239 TALLOC_FREE(conn
->netlogon_creds
);
3241 result
= get_trust_credentials(domain
, talloc_tos(), true, &creds
);
3242 if (!NT_STATUS_IS_OK(result
)) {
3243 DBG_DEBUG("No user available for domain %s when trying "
3244 "schannel\n", domain
->name
);
3245 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
3248 if (cli_credentials_is_anonymous(creds
)) {
3249 DEBUG(1, ("get_trust_credential only gave anonymous for %s, unable to make get NETLOGON credentials\n",
3251 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
3254 sec_chan_type
= cli_credentials_get_secure_channel_type(creds
);
3255 if (sec_chan_type
== SEC_CHAN_NULL
) {
3256 if (transport
== NCACN_IP_TCP
) {
3257 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3258 " deny NCACN_IP_TCP and let the caller fallback to NCACN_NP.\n",
3260 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
3263 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3264 "fallback to noauth on NCACN_NP.\n",
3267 result
= cli_rpc_pipe_open_noauth_transport(conn
->cli
,
3269 &ndr_table_netlogon
,
3270 &conn
->netlogon_pipe
);
3271 if (!NT_STATUS_IS_OK(result
)) {
3272 invalidate_cm_connection(domain
);
3276 *cli
= conn
->netlogon_pipe
;
3277 return NT_STATUS_OK
;
3280 result
= rpccli_create_netlogon_creds_with_creds(creds
,
3284 &conn
->netlogon_creds
);
3285 if (!NT_STATUS_IS_OK(result
)) {
3286 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3287 "unable to create NETLOGON credentials: %s\n",
3288 domain
->name
, nt_errstr(result
)));
3292 result
= rpccli_setup_netlogon_creds_with_creds(conn
->cli
, transport
,
3293 conn
->netlogon_creds
,
3294 conn
->netlogon_force_reauth
,
3296 conn
->netlogon_force_reauth
= false;
3297 if (!NT_STATUS_IS_OK(result
)) {
3298 DEBUG(1, ("rpccli_setup_netlogon_creds failed for %s, "
3299 "unable to setup NETLOGON credentials: %s\n",
3300 domain
->name
, nt_errstr(result
)));
3304 result
= netlogon_creds_cli_get(conn
->netlogon_creds
,
3307 if (!NT_STATUS_IS_OK(result
)) {
3308 DEBUG(1, ("netlogon_creds_cli_get failed for %s, "
3309 "unable to get NETLOGON credentials: %s\n",
3310 domain
->name
, nt_errstr(result
)));
3313 conn
->netlogon_flags
= netlogon_creds
->negotiate_flags
;
3314 TALLOC_FREE(netlogon_creds
);
3316 if (!(conn
->netlogon_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
3317 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3318 result
= NT_STATUS_DOWNGRADE_DETECTED
;
3319 DEBUG(1, ("Unwilling to make connection to domain %s"
3320 "without connection level security, "
3321 "must set 'winbind sealed pipes = false' and "
3322 "'require strong key = false' to proceed: %s\n",
3323 domain
->name
, nt_errstr(result
)));
3324 invalidate_cm_connection(domain
);
3327 result
= cli_rpc_pipe_open_noauth_transport(conn
->cli
,
3329 &ndr_table_netlogon
,
3330 &conn
->netlogon_pipe
);
3331 if (!NT_STATUS_IS_OK(result
)) {
3332 invalidate_cm_connection(domain
);
3336 *cli
= conn
->netlogon_pipe
;
3337 return NT_STATUS_OK
;
3340 /* Using the credentials from the first pipe, open a signed and sealed
3341 second netlogon pipe. The session key is stored in the schannel
3342 part of the new pipe auth struct.
3345 result
= cli_rpc_pipe_open_schannel_with_creds(
3346 conn
->cli
, &ndr_table_netlogon
, transport
,
3348 conn
->netlogon_creds
,
3349 &conn
->netlogon_pipe
);
3350 if (!NT_STATUS_IS_OK(result
)) {
3351 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
3352 "was %s\n", nt_errstr(result
)));
3354 invalidate_cm_connection(domain
);
3358 *cli
= conn
->netlogon_pipe
;
3359 return NT_STATUS_OK
;
3362 /****************************************************************************
3363 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3364 ****************************************************************************/
3366 NTSTATUS
cm_connect_netlogon(struct winbindd_domain
*domain
,
3367 struct rpc_pipe_client
**cli
)
3371 status
= init_dc_connection_rpc(domain
, domain
->rodc
);
3372 if (!NT_STATUS_IS_OK(status
)) {
3376 if (domain
->active_directory
&& domain
->can_do_ncacn_ip_tcp
) {
3377 status
= cm_connect_netlogon_transport(domain
, NCACN_IP_TCP
, cli
);
3378 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) ||
3379 NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
) ||
3380 NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
)) {
3381 invalidate_cm_connection(domain
);
3382 status
= cm_connect_netlogon_transport(domain
, NCACN_IP_TCP
, cli
);
3384 if (NT_STATUS_IS_OK(status
)) {
3389 * we tried twice to connect via ncan_ip_tcp and schannel and
3390 * failed - maybe it is a trusted domain we can't connect to ?
3391 * do not try tcp next time - gd
3393 * This also prevents LSA over TCP
3395 domain
->can_do_ncacn_ip_tcp
= false;
3398 status
= cm_connect_netlogon_transport(domain
, NCACN_NP
, cli
);
3399 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
3401 * SMB2 session expired, needs reauthentication. Drop
3402 * connection and retry.
3404 invalidate_cm_connection(domain
);
3405 status
= cm_connect_netlogon_transport(domain
, NCACN_NP
, cli
);
3411 void winbind_msg_ip_dropped(struct messaging_context
*msg_ctx
,
3414 struct server_id server_id
,
3417 struct winbindd_domain
*domain
;
3418 char *freeit
= NULL
;
3422 || (data
->data
== NULL
)
3423 || (data
->length
== 0)
3424 || (data
->data
[data
->length
-1] != '\0')) {
3425 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3430 addr
= (char *)data
->data
;
3431 DEBUG(10, ("IP %s dropped\n", addr
));
3433 if (!is_ipaddress(addr
)) {
3436 * Some code sends us ip addresses with the /netmask
3439 slash
= strchr(addr
, '/');
3440 if (slash
== NULL
) {
3441 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3445 freeit
= talloc_strndup(talloc_tos(), addr
, slash
-addr
);
3446 if (freeit
== NULL
) {
3447 DEBUG(1, ("talloc failed\n"));
3451 DEBUG(10, ("Stripped /netmask to IP %s\n", addr
));
3454 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
3455 char sockaddr
[INET6_ADDRSTRLEN
];
3457 if (!cli_state_is_connected(domain
->conn
.cli
)) {
3461 print_sockaddr(sockaddr
, sizeof(sockaddr
),
3462 smbXcli_conn_local_sockaddr(domain
->conn
.cli
->conn
));
3464 if (strequal(sockaddr
, addr
)) {
3465 smbXcli_conn_disconnect(domain
->conn
.cli
->conn
, NT_STATUS_OK
);
3468 TALLOC_FREE(freeit
);