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"
81 #define DBGC_CLASS DBGC_WINBIND
85 struct sockaddr_storage ss
;
88 extern struct winbindd_methods reconnect_methods
;
89 extern bool override_logfile
;
91 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
);
92 static void set_dc_type_and_flags( struct winbindd_domain
*domain
);
93 static bool get_dcs(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
94 struct dc_name_ip
**dcs
, int *num_dcs
);
96 /****************************************************************
97 Child failed to find DC's. Reschedule check.
98 ****************************************************************/
100 static void msg_failed_to_go_online(struct messaging_context
*msg
,
103 struct server_id server_id
,
106 struct winbindd_domain
*domain
;
107 const char *domainname
= (const char *)data
->data
;
109 if (data
->data
== NULL
|| data
->length
== 0) {
113 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname
));
115 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
116 if (domain
->internal
) {
120 if (strequal(domain
->name
, domainname
)) {
121 if (domain
->online
) {
122 /* We're already online, ignore. */
123 DEBUG(5,("msg_fail_to_go_online: domain %s "
124 "already online.\n", domainname
));
128 /* Reschedule the online check. */
129 set_domain_offline(domain
);
135 /****************************************************************
136 Actually cause a reconnect from a message.
137 ****************************************************************/
139 static void msg_try_to_go_online(struct messaging_context
*msg
,
142 struct server_id server_id
,
145 struct winbindd_domain
*domain
;
146 const char *domainname
= (const char *)data
->data
;
148 if (data
->data
== NULL
|| data
->length
== 0) {
152 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname
));
154 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
155 if (domain
->internal
) {
159 if (strequal(domain
->name
, domainname
)) {
161 if (domain
->online
) {
162 /* We're already online, ignore. */
163 DEBUG(5,("msg_try_to_go_online: domain %s "
164 "already online.\n", domainname
));
168 /* This call takes care of setting the online
169 flag to true if we connected, or re-adding
170 the offline handler if false. Bypasses online
171 check so always does network calls. */
173 init_dc_connection_network(domain
);
179 /****************************************************************
180 Fork a child to try and contact a DC. Do this as contacting a
181 DC requires blocking lookups and we don't want to block our
183 ****************************************************************/
185 static bool fork_child_dc_connect(struct winbindd_domain
*domain
)
187 struct dc_name_ip
*dcs
= NULL
;
189 TALLOC_CTX
*mem_ctx
= NULL
;
190 pid_t parent_pid
= sys_getpid();
194 if (domain
->dc_probe_pid
!= (pid_t
)-1) {
196 * We might already have a DC probe
197 * child working, check.
199 if (process_exists_by_pid(domain
->dc_probe_pid
)) {
200 DEBUG(10,("fork_child_dc_connect: pid %u already "
201 "checking for DC's.\n",
202 (unsigned int)domain
->dc_probe_pid
));
205 domain
->dc_probe_pid
= (pid_t
)-1;
208 domain
->dc_probe_pid
= sys_fork();
210 if (domain
->dc_probe_pid
== (pid_t
)-1) {
211 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno
)));
215 if (domain
->dc_probe_pid
!= (pid_t
)0) {
217 messaging_register(winbind_messaging_context(), NULL
,
218 MSG_WINBIND_TRY_TO_GO_ONLINE
,
219 msg_try_to_go_online
);
220 messaging_register(winbind_messaging_context(), NULL
,
221 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
222 msg_failed_to_go_online
);
228 /* Leave messages blocked - we will never process one. */
230 if (!override_logfile
) {
231 if (asprintf(&lfile
, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
232 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
237 status
= winbindd_reinit_after_fork(NULL
, lfile
);
238 if (!NT_STATUS_IS_OK(status
)) {
239 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
241 messaging_send_buf(winbind_messaging_context(),
242 pid_to_procid(parent_pid
),
243 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
244 (uint8
*)domain
->name
,
245 strlen(domain
->name
)+1);
250 mem_ctx
= talloc_init("fork_child_dc_connect");
252 DEBUG(0,("talloc_init failed.\n"));
253 messaging_send_buf(winbind_messaging_context(),
254 pid_to_procid(parent_pid
),
255 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
256 (uint8
*)domain
->name
,
257 strlen(domain
->name
)+1);
261 if ((!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
)) || (num_dcs
== 0)) {
262 /* Still offline ? Can't find DC's. */
263 messaging_send_buf(winbind_messaging_context(),
264 pid_to_procid(parent_pid
),
265 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
266 (uint8
*)domain
->name
,
267 strlen(domain
->name
)+1);
271 /* We got a DC. Send a message to our parent to get it to
272 try and do the same. */
274 messaging_send_buf(winbind_messaging_context(),
275 pid_to_procid(parent_pid
),
276 MSG_WINBIND_TRY_TO_GO_ONLINE
,
277 (uint8
*)domain
->name
,
278 strlen(domain
->name
)+1);
282 /****************************************************************
283 Handler triggered if we're offline to try and detect a DC.
284 ****************************************************************/
286 static void check_domain_online_handler(struct event_context
*ctx
,
287 struct timed_event
*te
,
291 struct winbindd_domain
*domain
=
292 (struct winbindd_domain
*)private_data
;
294 DEBUG(10,("check_domain_online_handler: called for domain "
295 "%s (online = %s)\n", domain
->name
,
296 domain
->online
? "True" : "False" ));
298 TALLOC_FREE(domain
->check_online_event
);
300 /* Are we still in "startup" mode ? */
302 if (domain
->startup
&& (time_mono(NULL
) > domain
->startup_time
+ 30)) {
303 /* No longer in "startup" mode. */
304 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
306 domain
->startup
= False
;
309 /* We've been told to stay offline, so stay
312 if (get_global_winbindd_state_offline()) {
313 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
318 /* Fork a child to test if it can contact a DC.
319 If it can then send ourselves a message to
320 cause a reconnect. */
322 fork_child_dc_connect(domain
);
325 /****************************************************************
326 If we're still offline setup the timeout check.
327 ****************************************************************/
329 static void calc_new_online_timeout_check(struct winbindd_domain
*domain
)
331 int wbr
= lp_winbind_reconnect_delay();
333 if (domain
->startup
) {
334 domain
->check_online_timeout
= 10;
335 } else if (domain
->check_online_timeout
< wbr
) {
336 domain
->check_online_timeout
= wbr
;
340 /****************************************************************
341 Set domain offline and also add handler to put us back online
343 ****************************************************************/
345 void set_domain_offline(struct winbindd_domain
*domain
)
347 DEBUG(10,("set_domain_offline: called for domain %s\n",
350 TALLOC_FREE(domain
->check_online_event
);
352 if (domain
->internal
) {
353 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
358 domain
->online
= False
;
360 /* Offline domains are always initialized. They're
361 re-initialized when they go back online. */
363 domain
->initialized
= True
;
365 /* We only add the timeout handler that checks and
366 allows us to go back online when we've not
367 been told to remain offline. */
369 if (get_global_winbindd_state_offline()) {
370 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
375 /* If we're in startup mode, check again in 10 seconds, not in
376 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
378 calc_new_online_timeout_check(domain
);
380 domain
->check_online_event
= event_add_timed(winbind_event_context(),
382 timeval_current_ofs(domain
->check_online_timeout
,0),
383 check_domain_online_handler
,
386 /* The above *has* to succeed for winbindd to work. */
387 if (!domain
->check_online_event
) {
388 smb_panic("set_domain_offline: failed to add online handler");
391 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
394 /* Send an offline message to the idmap child when our
395 primary domain goes offline */
397 if ( domain
->primary
) {
398 struct winbindd_child
*idmap
= idmap_child();
400 if ( idmap
->pid
!= 0 ) {
401 messaging_send_buf(winbind_messaging_context(),
402 pid_to_procid(idmap
->pid
),
404 (uint8
*)domain
->name
,
405 strlen(domain
->name
)+1);
412 /****************************************************************
413 Set domain online - if allowed.
414 ****************************************************************/
416 static void set_domain_online(struct winbindd_domain
*domain
)
418 DEBUG(10,("set_domain_online: called for domain %s\n",
421 if (domain
->internal
) {
422 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
427 if (get_global_winbindd_state_offline()) {
428 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
433 winbindd_set_locator_kdc_envs(domain
);
435 /* If we are waiting to get a krb5 ticket, trigger immediately. */
436 ccache_regain_all_now();
438 /* Ok, we're out of any startup mode now... */
439 domain
->startup
= False
;
441 if (domain
->online
== False
) {
442 /* We were offline - now we're online. We default to
443 using the MS-RPC backend if we started offline,
444 and if we're going online for the first time we
445 should really re-initialize the backends and the
446 checks to see if we're talking to an AD or NT domain.
449 domain
->initialized
= False
;
451 /* 'reconnect_methods' is the MS-RPC backend. */
452 if (domain
->backend
== &reconnect_methods
) {
453 domain
->backend
= NULL
;
457 /* Ensure we have no online timeout checks. */
458 domain
->check_online_timeout
= 0;
459 TALLOC_FREE(domain
->check_online_event
);
461 /* Ensure we ignore any pending child messages. */
462 messaging_deregister(winbind_messaging_context(),
463 MSG_WINBIND_TRY_TO_GO_ONLINE
, NULL
);
464 messaging_deregister(winbind_messaging_context(),
465 MSG_WINBIND_FAILED_TO_GO_ONLINE
, NULL
);
467 domain
->online
= True
;
469 /* Send an online message to the idmap child when our
470 primary domain comes online */
472 if ( domain
->primary
) {
473 struct winbindd_child
*idmap
= idmap_child();
475 if ( idmap
->pid
!= 0 ) {
476 messaging_send_buf(winbind_messaging_context(),
477 pid_to_procid(idmap
->pid
),
479 (uint8
*)domain
->name
,
480 strlen(domain
->name
)+1);
487 /****************************************************************
488 Requested to set a domain online.
489 ****************************************************************/
491 void set_domain_online_request(struct winbindd_domain
*domain
)
495 DEBUG(10,("set_domain_online_request: called for domain %s\n",
498 if (get_global_winbindd_state_offline()) {
499 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
504 if (domain
->internal
) {
505 DEBUG(10, ("set_domain_online_request: Internal domains are "
510 /* We've been told it's safe to go online and
511 try and connect to a DC. But I don't believe it
512 because network manager seems to lie.
513 Wait at least 5 seconds. Heuristics suck... */
518 /* Go into "startup" mode again. */
519 domain
->startup_time
= time_mono(NULL
);
520 domain
->startup
= True
;
524 if (!domain
->check_online_event
) {
525 /* If we've come from being globally offline we
526 don't have a check online event handler set.
527 We need to add one now we're trying to go
530 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
534 TALLOC_FREE(domain
->check_online_event
);
536 domain
->check_online_event
= event_add_timed(winbind_event_context(),
539 check_domain_online_handler
,
542 /* The above *has* to succeed for winbindd to work. */
543 if (!domain
->check_online_event
) {
544 smb_panic("set_domain_online_request: failed to add online handler");
548 /****************************************************************
549 Add -ve connection cache entries for domain and realm.
550 ****************************************************************/
552 static void winbind_add_failed_connection_entry(
553 const struct winbindd_domain
*domain
,
557 add_failed_connection_entry(domain
->name
, server
, result
);
558 /* If this was the saf name for the last thing we talked to,
560 saf_delete(domain
->name
);
561 if (*domain
->alt_name
) {
562 add_failed_connection_entry(domain
->alt_name
, server
, result
);
563 saf_delete(domain
->alt_name
);
565 winbindd_unset_locator_kdc_env(domain
);
568 /* Choose between anonymous or authenticated connections. We need to use
569 an authenticated connection if DCs have the RestrictAnonymous registry
570 entry set > 0, or the "Additional restrictions for anonymous
571 connections" set in the win2k Local Security Policy.
573 Caller to free() result in domain, username, password
576 static void cm_get_ipc_userpass(char **username
, char **domain
, char **password
)
578 *username
= (char *)secrets_fetch(SECRETS_AUTH_USER
, NULL
);
579 *domain
= (char *)secrets_fetch(SECRETS_AUTH_DOMAIN
, NULL
);
580 *password
= (char *)secrets_fetch(SECRETS_AUTH_PASSWORD
, NULL
);
582 if (*username
&& **username
) {
584 if (!*domain
|| !**domain
)
585 *domain
= smb_xstrdup(lp_workgroup());
587 if (!*password
|| !**password
)
588 *password
= smb_xstrdup("");
590 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
591 *domain
, *username
));
594 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
595 *username
= smb_xstrdup("");
596 *domain
= smb_xstrdup("");
597 *password
= smb_xstrdup("");
601 static bool get_dc_name_via_netlogon(struct winbindd_domain
*domain
,
603 struct sockaddr_storage
*dc_ss
)
605 struct winbindd_domain
*our_domain
= NULL
;
606 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
610 unsigned int orig_timeout
;
611 const char *tmp
= NULL
;
613 struct dcerpc_binding_handle
*b
;
615 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
622 if (domain
->primary
) {
626 our_domain
= find_our_domain();
628 if ((mem_ctx
= talloc_init("get_dc_name_via_netlogon")) == NULL
) {
632 result
= cm_connect_netlogon(our_domain
, &netlogon_pipe
);
633 if (!NT_STATUS_IS_OK(result
)) {
634 talloc_destroy(mem_ctx
);
638 b
= netlogon_pipe
->binding_handle
;
640 /* This call can take a long time - allow the server to time out.
641 35 seconds should do it. */
643 orig_timeout
= rpccli_set_timeout(netlogon_pipe
, 35000);
645 if (our_domain
->active_directory
) {
646 struct netr_DsRGetDCNameInfo
*domain_info
= NULL
;
648 result
= dcerpc_netr_DsRGetDCName(b
,
657 if (NT_STATUS_IS_OK(result
) && W_ERROR_IS_OK(werr
)) {
659 mem_ctx
, domain_info
->dc_unc
);
661 DEBUG(0, ("talloc_strdup failed\n"));
662 talloc_destroy(mem_ctx
);
665 if (strlen(domain
->alt_name
) == 0) {
666 fstrcpy(domain
->alt_name
,
667 domain_info
->domain_name
);
669 if (strlen(domain
->forest_name
) == 0) {
670 fstrcpy(domain
->forest_name
,
671 domain_info
->forest_name
);
675 result
= dcerpc_netr_GetAnyDCName(b
, mem_ctx
,
682 /* And restore our original timeout. */
683 rpccli_set_timeout(netlogon_pipe
, orig_timeout
);
685 if (!NT_STATUS_IS_OK(result
)) {
686 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
688 talloc_destroy(mem_ctx
);
692 if (!W_ERROR_IS_OK(werr
)) {
693 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
695 talloc_destroy(mem_ctx
);
699 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
700 p
= strip_hostname(tmp
);
704 talloc_destroy(mem_ctx
);
706 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname
));
708 if (!resolve_name(dcname
, dc_ss
, 0x20, true)) {
716 * Helper function to assemble trust password and account name
718 static NTSTATUS
get_trust_creds(const struct winbindd_domain
*domain
,
719 char **machine_password
,
720 char **machine_account
,
721 char **machine_krb5_principal
)
723 const char *account_name
;
724 const char *name
= NULL
;
726 /* If we are a DC and this is not our own domain */
731 struct winbindd_domain
*our_domain
= find_our_domain();
734 return NT_STATUS_INVALID_SERVER_STATE
;
736 name
= our_domain
->name
;
739 if (!get_trust_pw_clear(name
, machine_password
,
740 &account_name
, NULL
))
742 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
745 if ((machine_account
!= NULL
) &&
746 (asprintf(machine_account
, "%s$", account_name
) == -1))
748 return NT_STATUS_NO_MEMORY
;
751 /* For now assume our machine account only exists in our domain */
753 if (machine_krb5_principal
!= NULL
)
755 struct winbindd_domain
*our_domain
= find_our_domain();
758 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
761 if (asprintf(machine_krb5_principal
, "%s$@%s",
762 account_name
, our_domain
->alt_name
) == -1)
764 return NT_STATUS_NO_MEMORY
;
767 strupper_m(*machine_krb5_principal
);
773 /************************************************************************
774 Given a fd with a just-connected TCP connection to a DC, open a connection
776 ************************************************************************/
778 static NTSTATUS
cm_prepare_connection(const struct winbindd_domain
*domain
,
780 const char *controller
,
781 struct cli_state
**cli
,
784 char *machine_password
= NULL
;
785 char *machine_krb5_principal
= NULL
;
786 char *machine_account
= NULL
;
787 char *ipc_username
= NULL
;
788 char *ipc_domain
= NULL
;
789 char *ipc_password
= NULL
;
791 uint16_t sec_mode
= 0;
793 struct named_mutex
*mutex
;
795 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
797 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
798 controller
, domain
->name
));
802 mutex
= grab_named_mutex(talloc_tos(), controller
,
803 WINBIND_SERVER_MUTEX_WAIT_TIME
);
805 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
807 result
= NT_STATUS_POSSIBLE_DEADLOCK
;
811 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
813 *cli
= cli_state_create(NULL
, sockfd
,
814 controller
, domain
->alt_name
,
815 SMB_SIGNING_DEFAULT
, flags
);
817 DEBUG(1, ("Could not cli_initialize\n"));
818 result
= NT_STATUS_NO_MEMORY
;
822 cli_set_timeout(*cli
, 10000); /* 10 seconds */
824 result
= cli_negprot(*cli
, PROTOCOL_NT1
);
826 if (!NT_STATUS_IS_OK(result
)) {
827 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result
)));
831 if (!is_dc_trusted_domain_situation(domain
->name
) &&
832 cli_state_protocol(*cli
) >= PROTOCOL_NT1
&&
833 cli_state_capabilities(*cli
) & CAP_EXTENDED_SECURITY
)
835 ADS_STATUS ads_status
;
837 result
= get_trust_creds(domain
, &machine_password
,
839 &machine_krb5_principal
);
840 if (!NT_STATUS_IS_OK(result
)) {
844 if (lp_security() == SEC_ADS
) {
846 /* Try a krb5 session */
848 (*cli
)->use_kerberos
= True
;
849 DEBUG(5, ("connecting to %s from %s with kerberos principal "
850 "[%s] and realm [%s]\n", controller
, lp_netbios_name(),
851 machine_krb5_principal
, domain
->alt_name
));
853 winbindd_set_locator_kdc_envs(domain
);
855 result
= cli_session_setup(*cli
,
856 machine_krb5_principal
,
858 strlen(machine_password
)+1,
860 strlen(machine_password
)+1,
863 if (!NT_STATUS_IS_OK(result
)) {
864 DEBUG(4,("failed kerberos session setup with %s\n",
868 if (NT_STATUS_IS_OK(result
)) {
869 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
870 result
= cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
871 if (!NT_STATUS_IS_OK(result
)) {
874 goto session_setup_done
;
878 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
879 (*cli
)->use_kerberos
= False
;
881 DEBUG(5, ("connecting to %s from %s with username "
882 "[%s]\\[%s]\n", controller
, lp_netbios_name(),
883 lp_workgroup(), machine_account
));
885 result
= cli_session_setup(*cli
,
888 strlen(machine_password
)+1,
890 strlen(machine_password
)+1,
892 if (!NT_STATUS_IS_OK(result
)) {
893 DEBUG(4, ("authenticated session setup failed with %s\n",
897 result
= ads_ntstatus(ads_status
);
898 if (NT_STATUS_IS_OK(result
)) {
899 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
900 result
= cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
901 if (!NT_STATUS_IS_OK(result
)) {
904 goto session_setup_done
;
908 /* Fall back to non-kerberos session setup with auth_user */
910 (*cli
)->use_kerberos
= False
;
912 cm_get_ipc_userpass(&ipc_username
, &ipc_domain
, &ipc_password
);
914 sec_mode
= cli_state_security_mode(*cli
);
915 if (((sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) != 0) &&
916 (strlen(ipc_username
) > 0)) {
918 /* Only try authenticated if we have a username */
920 DEBUG(5, ("connecting to %s from %s with username "
921 "[%s]\\[%s]\n", controller
, lp_netbios_name(),
922 ipc_domain
, ipc_username
));
924 if (NT_STATUS_IS_OK(cli_session_setup(
926 ipc_password
, strlen(ipc_password
)+1,
927 ipc_password
, strlen(ipc_password
)+1,
929 /* Successful logon with given username. */
930 result
= cli_init_creds(*cli
, ipc_username
, ipc_domain
, ipc_password
);
931 if (!NT_STATUS_IS_OK(result
)) {
934 goto session_setup_done
;
936 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
937 ipc_domain
, ipc_username
));
943 /* Fall back to anonymous connection, this might fail later */
944 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
945 "connection for DC %s\n",
948 if (NT_STATUS_IS_OK(cli_session_setup(*cli
, "", NULL
, 0,
950 DEBUG(5, ("Connected anonymously\n"));
951 result
= cli_init_creds(*cli
, "", "", "");
952 if (!NT_STATUS_IS_OK(result
)) {
955 goto session_setup_done
;
958 result
= cli_nt_error(*cli
);
960 if (NT_STATUS_IS_OK(result
))
961 result
= NT_STATUS_UNSUCCESSFUL
;
963 /* We can't session setup */
969 /* cache the server name for later connections */
971 saf_store(domain
->name
, controller
);
972 if (domain
->alt_name
&& (*cli
)->use_kerberos
) {
973 saf_store(domain
->alt_name
, controller
);
976 winbindd_set_locator_kdc_envs(domain
);
978 result
= cli_tcon_andx(*cli
, "IPC$", "IPC", "", 0);
980 if (!NT_STATUS_IS_OK(result
)) {
981 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result
)));
988 /* set the domain if empty; needed for schannel connections */
989 if ( !(*cli
)->domain
[0] ) {
990 result
= cli_set_domain((*cli
), domain
->name
);
991 if (!NT_STATUS_IS_OK(result
)) {
996 result
= NT_STATUS_OK
;
1000 SAFE_FREE(machine_account
);
1001 SAFE_FREE(machine_password
);
1002 SAFE_FREE(machine_krb5_principal
);
1003 SAFE_FREE(ipc_username
);
1004 SAFE_FREE(ipc_domain
);
1005 SAFE_FREE(ipc_password
);
1007 if (!NT_STATUS_IS_OK(result
)) {
1008 winbind_add_failed_connection_entry(domain
, controller
, result
);
1009 if ((*cli
) != NULL
) {
1018 /*******************************************************************
1019 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1022 Keeps the list unique by not adding duplicate entries.
1024 @param[in] mem_ctx talloc memory context to allocate from
1025 @param[in] domain_name domain of the DC
1026 @param[in] dcname name of the DC to add to the list
1027 @param[in] pss Internet address and port pair to add to the list
1028 @param[in,out] dcs array of dc_name_ip structures to add to
1029 @param[in,out] num_dcs number of dcs returned in the dcs array
1030 @return true if the list was added to, false otherwise
1031 *******************************************************************/
1033 static bool add_one_dc_unique(TALLOC_CTX
*mem_ctx
, const char *domain_name
,
1034 const char *dcname
, struct sockaddr_storage
*pss
,
1035 struct dc_name_ip
**dcs
, int *num
)
1039 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name
, dcname
))) {
1040 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname
));
1044 /* Make sure there's no duplicates in the list */
1045 for (i
=0; i
<*num
; i
++)
1047 (struct sockaddr
*)(void *)&(*dcs
)[i
].ss
,
1048 (struct sockaddr
*)(void *)pss
))
1051 *dcs
= talloc_realloc(mem_ctx
, *dcs
, struct dc_name_ip
, (*num
)+1);
1056 fstrcpy((*dcs
)[*num
].name
, dcname
);
1057 (*dcs
)[*num
].ss
= *pss
;
1062 static bool add_sockaddr_to_array(TALLOC_CTX
*mem_ctx
,
1063 struct sockaddr_storage
*pss
, uint16 port
,
1064 struct sockaddr_storage
**addrs
, int *num
)
1066 *addrs
= talloc_realloc(mem_ctx
, *addrs
, struct sockaddr_storage
, (*num
)+1);
1068 if (*addrs
== NULL
) {
1073 (*addrs
)[*num
] = *pss
;
1074 set_sockaddr_port((struct sockaddr
*)&(*addrs
)[*num
], port
);
1080 /*******************************************************************
1081 convert an ip to a name
1082 *******************************************************************/
1084 static bool dcip_to_name(TALLOC_CTX
*mem_ctx
,
1085 const struct winbindd_domain
*domain
,
1086 struct sockaddr_storage
*pss
,
1089 struct ip_service ip_list
;
1090 uint32_t nt_version
= NETLOGON_NT_VERSION_1
;
1092 const char *dc_name
;
1098 /* For active directory servers, try to get the ldap server name.
1099 None of these failures should be considered critical for now */
1101 if (lp_security() == SEC_ADS
) {
1103 ADS_STATUS ads_status
;
1104 char addr
[INET6_ADDRSTRLEN
];
1106 print_sockaddr(addr
, sizeof(addr
), pss
);
1108 ads
= ads_init(domain
->alt_name
, domain
->name
, addr
);
1109 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
1111 ads_status
= ads_connect(ads
);
1112 if (ADS_ERR_OK(ads_status
)) {
1113 /* We got a cldap packet. */
1114 fstrcpy(name
, ads
->config
.ldap_server_name
);
1115 namecache_store(name
, 0x20, 1, &ip_list
);
1117 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads
->config
.flags
));
1119 if (domain
->primary
&& (ads
->config
.flags
& NBT_SERVER_KDC
)) {
1120 if (ads_closest_dc(ads
)) {
1121 char *sitename
= sitename_fetch(ads
->config
.realm
);
1123 /* We're going to use this KDC for this realm/domain.
1124 If we are using sites, then force the krb5 libs
1127 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1133 SAFE_FREE(sitename
);
1135 /* use an off site KDC */
1136 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1142 winbindd_set_locator_kdc_envs(domain
);
1144 /* Ensure we contact this DC also. */
1145 saf_store( domain
->name
, name
);
1146 saf_store( domain
->alt_name
, name
);
1149 ads_destroy( &ads
);
1153 ads_destroy( &ads
);
1157 status
= nbt_getdc(winbind_messaging_context(), pss
, domain
->name
,
1158 &domain
->sid
, nt_version
, mem_ctx
, &nt_version
,
1160 if (NT_STATUS_IS_OK(status
)) {
1161 fstrcpy(name
, dc_name
);
1162 namecache_store(name
, 0x20, 1, &ip_list
);
1166 /* try node status request */
1168 if ( name_status_find(domain
->name
, 0x1c, 0x20, pss
, name
) ) {
1169 namecache_store(name
, 0x20, 1, &ip_list
);
1175 /*******************************************************************
1176 Retrieve a list of IP addresses for domain controllers.
1178 The array is sorted in the preferred connection order.
1180 @param[in] mem_ctx talloc memory context to allocate from
1181 @param[in] domain domain to retrieve DCs for
1182 @param[out] dcs array of dcs that will be returned
1183 @param[out] num_dcs number of dcs returned in the dcs array
1185 *******************************************************************/
1187 static bool get_dcs(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
1188 struct dc_name_ip
**dcs
, int *num_dcs
)
1191 struct sockaddr_storage ss
;
1192 struct ip_service
*ip_list
= NULL
;
1193 int iplist_size
= 0;
1196 enum security_types sec
= (enum security_types
)lp_security();
1198 is_our_domain
= strequal(domain
->name
, lp_workgroup());
1200 /* If not our domain, get the preferred DC, by asking our primary DC */
1202 && get_dc_name_via_netlogon(domain
, dcname
, &ss
)
1203 && add_one_dc_unique(mem_ctx
, domain
->name
, dcname
, &ss
, dcs
,
1206 char addr
[INET6_ADDRSTRLEN
];
1207 print_sockaddr(addr
, sizeof(addr
), &ss
);
1208 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1213 if (sec
== SEC_ADS
) {
1214 char *sitename
= NULL
;
1216 /* We need to make sure we know the local site before
1217 doing any DNS queries, as this will restrict the
1218 get_sorted_dc_list() call below to only fetching
1219 DNS records for the correct site. */
1221 /* Find any DC to get the site record.
1222 We deliberately don't care about the
1225 get_dc_name(domain
->name
, domain
->alt_name
, dcname
, &ss
);
1227 sitename
= sitename_fetch(domain
->alt_name
);
1230 /* Do the site-specific AD dns lookup first. */
1231 get_sorted_dc_list(domain
->alt_name
, sitename
, &ip_list
,
1232 &iplist_size
, True
);
1234 /* Add ips to the DC array. We don't look up the name
1235 of the DC in this function, but we fill in the char*
1236 of the ip now to make the failed connection cache
1238 for ( i
=0; i
<iplist_size
; i
++ ) {
1239 char addr
[INET6_ADDRSTRLEN
];
1240 print_sockaddr(addr
, sizeof(addr
),
1242 add_one_dc_unique(mem_ctx
,
1251 SAFE_FREE(sitename
);
1255 /* Now we add DCs from the main AD DNS lookup. */
1256 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
,
1257 &iplist_size
, True
);
1259 for ( i
=0; i
<iplist_size
; i
++ ) {
1260 char addr
[INET6_ADDRSTRLEN
];
1261 print_sockaddr(addr
, sizeof(addr
),
1263 add_one_dc_unique(mem_ctx
,
1275 /* Try standard netbios queries if no ADS */
1276 if (*num_dcs
== 0) {
1277 get_sorted_dc_list(domain
->name
, NULL
, &ip_list
, &iplist_size
,
1280 for ( i
=0; i
<iplist_size
; i
++ ) {
1281 char addr
[INET6_ADDRSTRLEN
];
1282 print_sockaddr(addr
, sizeof(addr
),
1284 add_one_dc_unique(mem_ctx
,
1299 /*******************************************************************
1300 Find and make a connection to a DC in the given domain.
1302 @param[in] mem_ctx talloc memory context to allocate from
1303 @param[in] domain domain to find a dc in
1304 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1305 @param[out] pss DC Internet address and port
1306 @param[out] fd fd of the open socket connected to the newly found dc
1307 @return true when a DC connection is made, false otherwise
1308 *******************************************************************/
1310 static bool find_new_dc(TALLOC_CTX
*mem_ctx
,
1311 struct winbindd_domain
*domain
,
1312 fstring dcname
, struct sockaddr_storage
*pss
, int *fd
)
1314 struct dc_name_ip
*dcs
= NULL
;
1317 const char **dcnames
= NULL
;
1318 int num_dcnames
= 0;
1320 struct sockaddr_storage
*addrs
= NULL
;
1331 if (!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
) || (num_dcs
== 0))
1334 for (i
=0; i
<num_dcs
; i
++) {
1336 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1337 &dcnames
, &num_dcnames
)) {
1340 if (!add_sockaddr_to_array(mem_ctx
, &dcs
[i
].ss
, 445,
1341 &addrs
, &num_addrs
)) {
1346 if ((num_dcnames
== 0) || (num_dcnames
!= num_addrs
))
1349 if ((addrs
== NULL
) || (dcnames
== NULL
))
1352 status
= smbsock_any_connect(addrs
, dcnames
, NULL
, NULL
, NULL
,
1353 num_addrs
, 0, 10, fd
, &fd_index
, NULL
);
1354 if (!NT_STATUS_IS_OK(status
)) {
1355 for (i
=0; i
<num_dcs
; i
++) {
1356 char ab
[INET6_ADDRSTRLEN
];
1357 print_sockaddr(ab
, sizeof(ab
), &dcs
[i
].ss
);
1358 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1359 "domain %s address %s. Error was %s\n",
1360 domain
->name
, ab
, nt_errstr(status
) ));
1361 winbind_add_failed_connection_entry(domain
,
1362 dcs
[i
].name
, NT_STATUS_UNSUCCESSFUL
);
1367 *pss
= addrs
[fd_index
];
1369 if (*dcnames
[fd_index
] != '\0' && !is_ipaddress(dcnames
[fd_index
])) {
1370 /* Ok, we've got a name for the DC */
1371 fstrcpy(dcname
, dcnames
[fd_index
]);
1375 /* Try to figure out the name */
1376 if (dcip_to_name(mem_ctx
, domain
, pss
, dcname
)) {
1380 /* We can not continue without the DC's name */
1381 winbind_add_failed_connection_entry(domain
, dcs
[fd_index
].name
,
1382 NT_STATUS_UNSUCCESSFUL
);
1384 /* Throw away all arrays as we're doing this again. */
1388 TALLOC_FREE(dcnames
);
1400 static char *current_dc_key(TALLOC_CTX
*mem_ctx
, const char *domain_name
)
1402 return talloc_asprintf_strupper_m(mem_ctx
, "CURRENT_DCNAME/%s",
1406 static void store_current_dc_in_gencache(const char *domain_name
,
1407 const char *dc_name
,
1408 struct cli_state
*cli
)
1410 char addr
[INET6_ADDRSTRLEN
];
1414 if (!cli_state_is_connected(cli
)) {
1418 print_sockaddr(addr
, sizeof(addr
),
1419 cli_state_remote_sockaddr(cli
));
1421 key
= current_dc_key(talloc_tos(), domain_name
);
1426 value
= talloc_asprintf(talloc_tos(), "%s %s", addr
, dc_name
);
1427 if (value
== NULL
) {
1431 gencache_set(key
, value
, 0x7fffffff);
1437 bool fetch_current_dc_from_gencache(TALLOC_CTX
*mem_ctx
,
1438 const char *domain_name
,
1439 char **p_dc_name
, char **p_dc_ip
)
1441 char *key
, *value
, *p
;
1443 char *dc_name
= NULL
;
1446 key
= current_dc_key(talloc_tos(), domain_name
);
1450 if (!gencache_get(key
, &value
, NULL
)) {
1453 p
= strchr(value
, ' ');
1457 dc_ip
= talloc_strndup(mem_ctx
, value
, p
- value
);
1458 if (dc_ip
== NULL
) {
1461 dc_name
= talloc_strdup(mem_ctx
, p
+1);
1462 if (dc_name
== NULL
) {
1466 if (p_dc_ip
!= NULL
) {
1470 if (p_dc_name
!= NULL
) {
1471 *p_dc_name
= dc_name
;
1476 TALLOC_FREE(dc_name
);
1482 static NTSTATUS
cm_open_connection(struct winbindd_domain
*domain
,
1483 struct winbindd_cm_conn
*new_conn
)
1485 TALLOC_CTX
*mem_ctx
;
1487 char *saf_servername
= saf_fetch( domain
->name
);
1490 if ((mem_ctx
= talloc_init("cm_open_connection")) == NULL
) {
1491 SAFE_FREE(saf_servername
);
1492 set_domain_offline(domain
);
1493 return NT_STATUS_NO_MEMORY
;
1496 /* we have to check the server affinity cache here since
1497 later we select a DC based on response time and not preference */
1499 /* Check the negative connection cache
1500 before talking to it. It going down may have
1501 triggered the reconnection. */
1503 if ( saf_servername
&& NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, saf_servername
))) {
1505 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1506 saf_servername
, domain
->name
));
1508 /* convert an ip address to a name */
1509 if (is_ipaddress( saf_servername
) ) {
1511 struct sockaddr_storage ss
;
1513 if (!interpret_string_addr(&ss
, saf_servername
,
1515 return NT_STATUS_UNSUCCESSFUL
;
1517 if (dcip_to_name(mem_ctx
, domain
, &ss
, saf_name
)) {
1518 strlcpy(domain
->dcname
, saf_name
, sizeof(domain
->dcname
));
1520 winbind_add_failed_connection_entry(
1521 domain
, saf_servername
,
1522 NT_STATUS_UNSUCCESSFUL
);
1525 fstrcpy( domain
->dcname
, saf_servername
);
1528 SAFE_FREE( saf_servername
);
1531 for (retries
= 0; retries
< 3; retries
++) {
1535 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1537 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1538 domain
->dcname
, domain
->name
));
1541 && NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, domain
->dcname
))
1542 && (resolve_name(domain
->dcname
, &domain
->dcaddr
, 0x20, true)))
1546 status
= smbsock_connect(&domain
->dcaddr
, 0,
1549 if (!NT_STATUS_IS_OK(status
)) {
1555 && !find_new_dc(mem_ctx
, domain
, domain
->dcname
, &domain
->dcaddr
, &fd
))
1557 /* This is the one place where we will
1558 set the global winbindd offline state
1559 to true, if a "WINBINDD_OFFLINE" entry
1560 is found in the winbindd cache. */
1561 set_global_winbindd_state_offline();
1565 new_conn
->cli
= NULL
;
1567 result
= cm_prepare_connection(domain
, fd
, domain
->dcname
,
1568 &new_conn
->cli
, &retry
);
1574 if (NT_STATUS_IS_OK(result
)) {
1576 winbindd_set_locator_kdc_envs(domain
);
1578 if (domain
->online
== False
) {
1579 /* We're changing state from offline to online. */
1580 set_global_winbindd_state_online();
1582 set_domain_online(domain
);
1585 * Much as I hate global state, this seems to be the point
1586 * where we can be certain that we have a proper connection to
1587 * a DC. wbinfo --dc-info needs that information, store it in
1588 * gencache with a looong timeout. This will need revisiting
1589 * once we start to connect to multiple DCs, wbcDcInfo is
1590 * already prepared for that.
1592 store_current_dc_in_gencache(domain
->name
, domain
->dcname
,
1595 /* Ensure we setup the retry handler. */
1596 set_domain_offline(domain
);
1599 talloc_destroy(mem_ctx
);
1603 /* Close down all open pipes on a connection. */
1605 void invalidate_cm_connection(struct winbindd_cm_conn
*conn
)
1609 /* We're closing down a possibly dead
1610 connection. Don't have impossibly long (10s) timeouts. */
1613 cli_set_timeout(conn
->cli
, 1000); /* 1 second. */
1616 if (conn
->samr_pipe
!= NULL
) {
1617 if (is_valid_policy_hnd(&conn
->sam_connect_handle
)) {
1618 dcerpc_samr_Close(conn
->samr_pipe
->binding_handle
,
1620 &conn
->sam_connect_handle
,
1623 TALLOC_FREE(conn
->samr_pipe
);
1624 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1626 cli_set_timeout(conn
->cli
, 500);
1630 if (conn
->lsa_pipe
!= NULL
) {
1631 if (is_valid_policy_hnd(&conn
->lsa_policy
)) {
1632 dcerpc_lsa_Close(conn
->lsa_pipe
->binding_handle
,
1637 TALLOC_FREE(conn
->lsa_pipe
);
1638 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1640 cli_set_timeout(conn
->cli
, 500);
1644 if (conn
->lsa_pipe_tcp
!= NULL
) {
1645 if (is_valid_policy_hnd(&conn
->lsa_policy
)) {
1646 dcerpc_lsa_Close(conn
->lsa_pipe_tcp
->binding_handle
,
1651 TALLOC_FREE(conn
->lsa_pipe_tcp
);
1652 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1654 cli_set_timeout(conn
->cli
, 500);
1658 if (conn
->netlogon_pipe
!= NULL
) {
1659 TALLOC_FREE(conn
->netlogon_pipe
);
1660 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1662 cli_set_timeout(conn
->cli
, 500);
1667 cli_shutdown(conn
->cli
);
1673 void close_conns_after_fork(void)
1675 struct winbindd_domain
*domain
;
1676 struct winbindd_cli_state
*cli_state
;
1678 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
1680 * first close the low level SMB TCP connection
1681 * so that we don't generate any SMBclose
1682 * requests in invalidate_cm_connection()
1684 if (cli_state_is_connected(domain
->conn
.cli
)) {
1685 cli_state_disconnect(domain
->conn
.cli
);
1688 invalidate_cm_connection(&domain
->conn
);
1691 for (cli_state
= winbindd_client_list();
1693 cli_state
= cli_state
->next
) {
1694 if (cli_state
->sock
>= 0) {
1695 close(cli_state
->sock
);
1696 cli_state
->sock
= -1;
1701 static bool connection_ok(struct winbindd_domain
*domain
)
1705 ok
= cli_state_is_connected(domain
->conn
.cli
);
1707 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1708 domain
->dcname
, domain
->name
));
1712 if (domain
->online
== False
) {
1713 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain
->name
));
1720 /* Initialize a new connection up to the RPC BIND.
1721 Bypass online status check so always does network calls. */
1723 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
)
1727 /* Internal connections never use the network. */
1728 if (domain
->internal
) {
1729 domain
->initialized
= True
;
1730 return NT_STATUS_OK
;
1733 if (!winbindd_can_contact_domain(domain
)) {
1734 invalidate_cm_connection(&domain
->conn
);
1735 domain
->initialized
= True
;
1736 return NT_STATUS_OK
;
1739 if (connection_ok(domain
)) {
1740 if (!domain
->initialized
) {
1741 set_dc_type_and_flags(domain
);
1743 return NT_STATUS_OK
;
1746 invalidate_cm_connection(&domain
->conn
);
1748 result
= cm_open_connection(domain
, &domain
->conn
);
1750 if (NT_STATUS_IS_OK(result
) && !domain
->initialized
) {
1751 set_dc_type_and_flags(domain
);
1757 NTSTATUS
init_dc_connection(struct winbindd_domain
*domain
)
1759 if (domain
->internal
) {
1760 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1763 if (domain
->initialized
&& !domain
->online
) {
1764 /* We check for online status elsewhere. */
1765 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1768 return init_dc_connection_network(domain
);
1771 static NTSTATUS
init_dc_connection_rpc(struct winbindd_domain
*domain
)
1775 status
= init_dc_connection(domain
);
1776 if (!NT_STATUS_IS_OK(status
)) {
1780 if (!domain
->internal
&& domain
->conn
.cli
== NULL
) {
1781 /* happens for trusted domains without inbound trust */
1782 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
1785 return NT_STATUS_OK
;
1788 /******************************************************************************
1789 Set the trust flags (direction and forest location) for a domain
1790 ******************************************************************************/
1792 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain
*domain
)
1794 struct winbindd_domain
*our_domain
;
1795 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1797 struct netr_DomainTrustList trusts
;
1799 uint32 flags
= (NETR_TRUST_FLAG_IN_FOREST
|
1800 NETR_TRUST_FLAG_OUTBOUND
|
1801 NETR_TRUST_FLAG_INBOUND
);
1802 struct rpc_pipe_client
*cli
;
1803 TALLOC_CTX
*mem_ctx
= NULL
;
1804 struct dcerpc_binding_handle
*b
;
1806 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain
->name
));
1808 /* Our primary domain doesn't need to worry about trust flags.
1809 Force it to go through the network setup */
1810 if ( domain
->primary
) {
1814 our_domain
= find_our_domain();
1816 if ( !connection_ok(our_domain
) ) {
1817 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1821 /* This won't work unless our domain is AD */
1823 if ( !our_domain
->active_directory
) {
1827 /* Use DsEnumerateDomainTrusts to get us the trust direction
1830 result
= cm_connect_netlogon(our_domain
, &cli
);
1832 if (!NT_STATUS_IS_OK(result
)) {
1833 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1834 "a connection to %s for PIPE_NETLOGON (%s)\n",
1835 domain
->name
, nt_errstr(result
)));
1839 b
= cli
->binding_handle
;
1841 if ( (mem_ctx
= talloc_init("set_dc_type_and_flags_trustinfo")) == NULL
) {
1842 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1846 result
= dcerpc_netr_DsrEnumerateDomainTrusts(b
, mem_ctx
,
1851 if (!NT_STATUS_IS_OK(result
)) {
1852 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1853 "failed to query trusted domain list: %s\n",
1854 nt_errstr(result
)));
1855 talloc_destroy(mem_ctx
);
1858 if (!W_ERROR_IS_OK(werr
)) {
1859 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1860 "failed to query trusted domain list: %s\n",
1862 talloc_destroy(mem_ctx
);
1866 /* Now find the domain name and get the flags */
1868 for ( i
=0; i
<trusts
.count
; i
++ ) {
1869 if ( strequal( domain
->name
, trusts
.array
[i
].netbios_name
) ) {
1870 domain
->domain_flags
= trusts
.array
[i
].trust_flags
;
1871 domain
->domain_type
= trusts
.array
[i
].trust_type
;
1872 domain
->domain_trust_attribs
= trusts
.array
[i
].trust_attributes
;
1874 if ( domain
->domain_type
== NETR_TRUST_TYPE_UPLEVEL
)
1875 domain
->active_directory
= True
;
1877 /* This flag is only set if the domain is *our*
1878 primary domain and the primary domain is in
1881 domain
->native_mode
= (domain
->domain_flags
& NETR_TRUST_FLAG_NATIVE
);
1883 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1884 "native mode.\n", domain
->name
,
1885 domain
->native_mode
? "" : "NOT "));
1887 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1888 "running active directory.\n", domain
->name
,
1889 domain
->active_directory
? "" : "NOT "));
1892 domain
->initialized
= True
;
1898 talloc_destroy( mem_ctx
);
1900 return domain
->initialized
;
1903 /******************************************************************************
1904 We can 'sense' certain things about the DC by it's replies to certain
1907 This tells us if this particular remote server is Active Directory, and if it
1909 ******************************************************************************/
1911 static void set_dc_type_and_flags_connect( struct winbindd_domain
*domain
)
1913 NTSTATUS status
, result
;
1915 TALLOC_CTX
*mem_ctx
= NULL
;
1916 struct rpc_pipe_client
*cli
= NULL
;
1917 struct policy_handle pol
;
1918 union dssetup_DsRoleInfo info
;
1919 union lsa_PolicyInformation
*lsa_info
= NULL
;
1921 if (!connection_ok(domain
)) {
1925 mem_ctx
= talloc_init("set_dc_type_and_flags on domain %s\n",
1928 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1932 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain
->name
));
1934 status
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
1935 &ndr_table_dssetup
.syntax_id
,
1938 if (!NT_STATUS_IS_OK(status
)) {
1939 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1940 "PI_DSSETUP on domain %s: (%s)\n",
1941 domain
->name
, nt_errstr(status
)));
1943 /* if this is just a non-AD domain we need to continue
1944 * identifying so that we can in the end return with
1945 * domain->initialized = True - gd */
1950 status
= dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli
->binding_handle
, mem_ctx
,
1951 DS_ROLE_BASIC_INFORMATION
,
1956 if (NT_STATUS_IS_OK(status
)) {
1957 result
= werror_to_ntstatus(werr
);
1959 if (!NT_STATUS_IS_OK(status
)) {
1960 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1961 "on domain %s failed: (%s)\n",
1962 domain
->name
, nt_errstr(status
)));
1964 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1965 * every opcode on the DSSETUP pipe, continue with
1966 * no_dssetup mode here as well to get domain->initialized
1969 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1973 TALLOC_FREE(mem_ctx
);
1977 if ((info
.basic
.flags
& DS_ROLE_PRIMARY_DS_RUNNING
) &&
1978 !(info
.basic
.flags
& DS_ROLE_PRIMARY_DS_MIXED_MODE
)) {
1979 domain
->native_mode
= True
;
1981 domain
->native_mode
= False
;
1985 status
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
1986 &ndr_table_lsarpc
.syntax_id
, &cli
);
1988 if (!NT_STATUS_IS_OK(status
)) {
1989 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1990 "PI_LSARPC on domain %s: (%s)\n",
1991 domain
->name
, nt_errstr(status
)));
1993 TALLOC_FREE(mem_ctx
);
1997 status
= rpccli_lsa_open_policy2(cli
, mem_ctx
, True
,
1998 SEC_FLAG_MAXIMUM_ALLOWED
, &pol
);
2000 if (NT_STATUS_IS_OK(status
)) {
2001 /* This particular query is exactly what Win2k clients use
2002 to determine that the DC is active directory */
2003 status
= dcerpc_lsa_QueryInfoPolicy2(cli
->binding_handle
, mem_ctx
,
2005 LSA_POLICY_INFO_DNS
,
2010 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2011 domain
->active_directory
= True
;
2013 if (lsa_info
->dns
.name
.string
) {
2014 fstrcpy(domain
->name
, lsa_info
->dns
.name
.string
);
2017 if (lsa_info
->dns
.dns_domain
.string
) {
2018 fstrcpy(domain
->alt_name
,
2019 lsa_info
->dns
.dns_domain
.string
);
2022 /* See if we can set some domain trust flags about
2025 if (lsa_info
->dns
.dns_forest
.string
) {
2026 fstrcpy(domain
->forest_name
,
2027 lsa_info
->dns
.dns_forest
.string
);
2029 if (strequal(domain
->forest_name
, domain
->alt_name
)) {
2030 domain
->domain_flags
|= NETR_TRUST_FLAG_TREEROOT
;
2034 if (lsa_info
->dns
.sid
) {
2035 sid_copy(&domain
->sid
, lsa_info
->dns
.sid
);
2038 domain
->active_directory
= False
;
2040 status
= rpccli_lsa_open_policy(cli
, mem_ctx
, True
,
2041 SEC_FLAG_MAXIMUM_ALLOWED
,
2044 if (!NT_STATUS_IS_OK(status
)) {
2048 status
= dcerpc_lsa_QueryInfoPolicy(cli
->binding_handle
, mem_ctx
,
2050 LSA_POLICY_INFO_ACCOUNT_DOMAIN
,
2053 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2055 if (lsa_info
->account_domain
.name
.string
) {
2056 fstrcpy(domain
->name
,
2057 lsa_info
->account_domain
.name
.string
);
2060 if (lsa_info
->account_domain
.sid
) {
2061 sid_copy(&domain
->sid
, lsa_info
->account_domain
.sid
);
2067 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2068 domain
->name
, domain
->native_mode
? "" : "NOT "));
2070 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2071 domain
->name
, domain
->active_directory
? "" : "NOT "));
2073 domain
->can_do_ncacn_ip_tcp
= domain
->active_directory
;
2074 domain
->can_do_validation6
= domain
->active_directory
;
2078 TALLOC_FREE(mem_ctx
);
2080 domain
->initialized
= True
;
2083 /**********************************************************************
2084 Set the domain_flags (trust attributes, domain operating modes, etc...
2085 ***********************************************************************/
2087 static void set_dc_type_and_flags( struct winbindd_domain
*domain
)
2089 /* we always have to contact our primary domain */
2091 if ( domain
->primary
) {
2092 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2093 "primary domain\n"));
2094 set_dc_type_and_flags_connect( domain
);
2098 /* Use our DC to get the information if possible */
2100 if ( !set_dc_type_and_flags_trustinfo( domain
) ) {
2101 /* Otherwise, fallback to contacting the
2103 set_dc_type_and_flags_connect( domain
);
2111 /**********************************************************************
2112 ***********************************************************************/
2114 static NTSTATUS
cm_get_schannel_creds(struct winbindd_domain
*domain
,
2115 struct netlogon_creds_CredentialState
**ppdc
)
2117 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2118 struct rpc_pipe_client
*netlogon_pipe
;
2120 if (lp_client_schannel() == False
) {
2121 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2124 result
= cm_connect_netlogon(domain
, &netlogon_pipe
);
2125 if (!NT_STATUS_IS_OK(result
)) {
2129 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2132 if (!domain
->conn
.netlogon_pipe
->dc
) {
2133 return NT_STATUS_INTERNAL_ERROR
; /* This shouldn't happen. */
2136 *ppdc
= domain
->conn
.netlogon_pipe
->dc
;
2137 return NT_STATUS_OK
;
2140 NTSTATUS
cm_connect_sam(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
2141 struct rpc_pipe_client
**cli
, struct policy_handle
*sam_handle
)
2143 struct winbindd_cm_conn
*conn
;
2144 NTSTATUS status
, result
;
2145 struct netlogon_creds_CredentialState
*p_creds
;
2146 char *machine_password
= NULL
;
2147 char *machine_account
= NULL
;
2148 char *domain_name
= NULL
;
2150 if (sid_check_is_domain(&domain
->sid
)) {
2151 return open_internal_samr_conn(mem_ctx
, domain
, cli
, sam_handle
);
2154 status
= init_dc_connection_rpc(domain
);
2155 if (!NT_STATUS_IS_OK(status
)) {
2159 conn
= &domain
->conn
;
2161 if (rpccli_is_connected(conn
->samr_pipe
)) {
2165 TALLOC_FREE(conn
->samr_pipe
);
2168 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2169 * sign and sealed pipe using the machine account password by
2170 * preference. If we can't - try schannel, if that fails, try
2174 if ((conn
->cli
->user_name
[0] == '\0') ||
2175 (conn
->cli
->domain
[0] == '\0') ||
2176 (conn
->cli
->password
== NULL
|| conn
->cli
->password
[0] == '\0'))
2178 status
= get_trust_creds(domain
, &machine_password
,
2179 &machine_account
, NULL
);
2180 if (!NT_STATUS_IS_OK(status
)) {
2181 DEBUG(10, ("cm_connect_sam: No no user available for "
2182 "domain %s, trying schannel\n", conn
->cli
->domain
));
2185 domain_name
= domain
->name
;
2187 machine_password
= SMB_STRDUP(conn
->cli
->password
);
2188 machine_account
= SMB_STRDUP(conn
->cli
->user_name
);
2189 domain_name
= conn
->cli
->domain
;
2192 if (!machine_password
|| !machine_account
) {
2193 status
= NT_STATUS_NO_MEMORY
;
2197 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2198 authenticated SAMR pipe with sign & seal. */
2199 status
= cli_rpc_pipe_open_spnego_ntlmssp(conn
->cli
,
2200 &ndr_table_samr
.syntax_id
,
2202 DCERPC_AUTH_LEVEL_PRIVACY
,
2208 if (!NT_STATUS_IS_OK(status
)) {
2209 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2210 "pipe for domain %s using NTLMSSP "
2211 "authenticated pipe: user %s\\%s. Error was "
2212 "%s\n", domain
->name
, domain_name
,
2213 machine_account
, nt_errstr(status
)));
2217 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2218 "domain %s using NTLMSSP authenticated "
2219 "pipe: user %s\\%s\n", domain
->name
,
2220 domain_name
, machine_account
));
2222 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2223 conn
->samr_pipe
->desthost
,
2224 SEC_FLAG_MAXIMUM_ALLOWED
,
2225 &conn
->sam_connect_handle
,
2227 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2230 if (NT_STATUS_IS_OK(status
)) {
2234 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2235 "failed for domain %s, error was %s. Trying schannel\n",
2236 domain
->name
, nt_errstr(status
) ));
2237 TALLOC_FREE(conn
->samr_pipe
);
2241 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2243 status
= cm_get_schannel_creds(domain
, &p_creds
);
2244 if (!NT_STATUS_IS_OK(status
)) {
2245 /* If this call fails - conn->cli can now be NULL ! */
2246 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2247 "for domain %s (error %s), trying anon\n",
2249 nt_errstr(status
) ));
2252 status
= cli_rpc_pipe_open_schannel_with_key
2253 (conn
->cli
, &ndr_table_samr
.syntax_id
, NCACN_NP
,
2254 DCERPC_AUTH_LEVEL_PRIVACY
,
2255 domain
->name
, &p_creds
, &conn
->samr_pipe
);
2257 if (!NT_STATUS_IS_OK(status
)) {
2258 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2259 "domain %s using schannel. Error was %s\n",
2260 domain
->name
, nt_errstr(status
) ));
2263 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2264 "schannel.\n", domain
->name
));
2266 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2267 conn
->samr_pipe
->desthost
,
2268 SEC_FLAG_MAXIMUM_ALLOWED
,
2269 &conn
->sam_connect_handle
,
2271 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2274 if (NT_STATUS_IS_OK(status
)) {
2277 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2278 "for domain %s, error was %s. Trying anonymous\n",
2279 domain
->name
, nt_errstr(status
) ));
2280 TALLOC_FREE(conn
->samr_pipe
);
2284 /* Finally fall back to anonymous. */
2285 status
= cli_rpc_pipe_open_noauth(conn
->cli
, &ndr_table_samr
.syntax_id
,
2288 if (!NT_STATUS_IS_OK(status
)) {
2292 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2293 conn
->samr_pipe
->desthost
,
2294 SEC_FLAG_MAXIMUM_ALLOWED
,
2295 &conn
->sam_connect_handle
,
2297 if (!NT_STATUS_IS_OK(status
)) {
2298 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2299 "for domain %s Error was %s\n",
2300 domain
->name
, nt_errstr(status
) ));
2303 if (!NT_STATUS_IS_OK(result
)) {
2305 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2306 "for domain %s Error was %s\n",
2307 domain
->name
, nt_errstr(result
)));
2312 status
= dcerpc_samr_OpenDomain(conn
->samr_pipe
->binding_handle
,
2314 &conn
->sam_connect_handle
,
2315 SEC_FLAG_MAXIMUM_ALLOWED
,
2317 &conn
->sam_domain_handle
,
2319 if (!NT_STATUS_IS_OK(status
)) {
2326 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
2328 * if we got access denied, we might just have no access rights
2329 * to talk to the remote samr server server (e.g. when we are a
2330 * PDC and we are connecting a w2k8 pdc via an interdomain
2331 * trust). In that case do not invalidate the whole connection
2334 TALLOC_FREE(conn
->samr_pipe
);
2335 ZERO_STRUCT(conn
->sam_domain_handle
);
2337 } else if (!NT_STATUS_IS_OK(status
)) {
2338 invalidate_cm_connection(conn
);
2342 *cli
= conn
->samr_pipe
;
2343 *sam_handle
= conn
->sam_domain_handle
;
2344 SAFE_FREE(machine_password
);
2345 SAFE_FREE(machine_account
);
2349 /**********************************************************************
2350 open an schanneld ncacn_ip_tcp connection to LSA
2351 ***********************************************************************/
2353 NTSTATUS
cm_connect_lsa_tcp(struct winbindd_domain
*domain
,
2354 TALLOC_CTX
*mem_ctx
,
2355 struct rpc_pipe_client
**cli
)
2357 struct winbindd_cm_conn
*conn
;
2358 struct netlogon_creds_CredentialState
*creds
;
2361 DEBUG(10,("cm_connect_lsa_tcp\n"));
2363 status
= init_dc_connection_rpc(domain
);
2364 if (!NT_STATUS_IS_OK(status
)) {
2368 conn
= &domain
->conn
;
2370 if (conn
->lsa_pipe_tcp
&&
2371 conn
->lsa_pipe_tcp
->transport
->transport
== NCACN_IP_TCP
&&
2372 conn
->lsa_pipe_tcp
->auth
->auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
&&
2373 rpccli_is_connected(conn
->lsa_pipe_tcp
)) {
2377 TALLOC_FREE(conn
->lsa_pipe_tcp
);
2379 status
= cm_get_schannel_creds(domain
, &creds
);
2380 if (!NT_STATUS_IS_OK(status
)) {
2384 status
= cli_rpc_pipe_open_schannel_with_key(conn
->cli
,
2385 &ndr_table_lsarpc
.syntax_id
,
2387 DCERPC_AUTH_LEVEL_PRIVACY
,
2390 &conn
->lsa_pipe_tcp
);
2391 if (!NT_STATUS_IS_OK(status
)) {
2392 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2393 nt_errstr(status
)));
2398 if (!NT_STATUS_IS_OK(status
)) {
2399 TALLOC_FREE(conn
->lsa_pipe_tcp
);
2403 *cli
= conn
->lsa_pipe_tcp
;
2408 NTSTATUS
cm_connect_lsa(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
2409 struct rpc_pipe_client
**cli
, struct policy_handle
*lsa_policy
)
2411 struct winbindd_cm_conn
*conn
;
2412 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2413 struct netlogon_creds_CredentialState
*p_creds
;
2415 result
= init_dc_connection_rpc(domain
);
2416 if (!NT_STATUS_IS_OK(result
))
2419 conn
= &domain
->conn
;
2421 if (rpccli_is_connected(conn
->lsa_pipe
)) {
2425 TALLOC_FREE(conn
->lsa_pipe
);
2427 if ((conn
->cli
->user_name
[0] == '\0') ||
2428 (conn
->cli
->domain
[0] == '\0') ||
2429 (conn
->cli
->password
== NULL
|| conn
->cli
->password
[0] == '\0')) {
2430 DEBUG(10, ("cm_connect_lsa: No no user available for "
2431 "domain %s, trying schannel\n", conn
->cli
->domain
));
2435 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2436 * authenticated LSA pipe with sign & seal. */
2437 result
= cli_rpc_pipe_open_spnego_ntlmssp
2438 (conn
->cli
, &ndr_table_lsarpc
.syntax_id
, NCACN_NP
,
2439 DCERPC_AUTH_LEVEL_PRIVACY
,
2440 conn
->cli
->domain
, conn
->cli
->user_name
, conn
->cli
->password
,
2443 if (!NT_STATUS_IS_OK(result
)) {
2444 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2445 "domain %s using NTLMSSP authenticated pipe: user "
2446 "%s\\%s. Error was %s. Trying schannel.\n",
2447 domain
->name
, conn
->cli
->domain
,
2448 conn
->cli
->user_name
, nt_errstr(result
)));
2452 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2453 "NTLMSSP authenticated pipe: user %s\\%s\n",
2454 domain
->name
, conn
->cli
->domain
, conn
->cli
->user_name
));
2456 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2457 SEC_FLAG_MAXIMUM_ALLOWED
,
2459 if (NT_STATUS_IS_OK(result
)) {
2463 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2466 TALLOC_FREE(conn
->lsa_pipe
);
2470 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2472 result
= cm_get_schannel_creds(domain
, &p_creds
);
2473 if (!NT_STATUS_IS_OK(result
)) {
2474 /* If this call fails - conn->cli can now be NULL ! */
2475 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2476 "for domain %s (error %s), trying anon\n",
2478 nt_errstr(result
) ));
2481 result
= cli_rpc_pipe_open_schannel_with_key
2482 (conn
->cli
, &ndr_table_lsarpc
.syntax_id
, NCACN_NP
,
2483 DCERPC_AUTH_LEVEL_PRIVACY
,
2484 domain
->name
, &p_creds
, &conn
->lsa_pipe
);
2486 if (!NT_STATUS_IS_OK(result
)) {
2487 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2488 "domain %s using schannel. Error was %s\n",
2489 domain
->name
, nt_errstr(result
) ));
2492 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2493 "schannel.\n", domain
->name
));
2495 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2496 SEC_FLAG_MAXIMUM_ALLOWED
,
2498 if (NT_STATUS_IS_OK(result
)) {
2502 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2505 TALLOC_FREE(conn
->lsa_pipe
);
2509 result
= cli_rpc_pipe_open_noauth(conn
->cli
,
2510 &ndr_table_lsarpc
.syntax_id
,
2512 if (!NT_STATUS_IS_OK(result
)) {
2513 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
2517 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2518 SEC_FLAG_MAXIMUM_ALLOWED
,
2521 if (!NT_STATUS_IS_OK(result
)) {
2522 invalidate_cm_connection(conn
);
2526 *cli
= conn
->lsa_pipe
;
2527 *lsa_policy
= conn
->lsa_policy
;
2531 /****************************************************************************
2532 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2533 session key stored in conn->netlogon_pipe->dc->sess_key.
2534 ****************************************************************************/
2536 NTSTATUS
cm_connect_netlogon(struct winbindd_domain
*domain
,
2537 struct rpc_pipe_client
**cli
)
2539 struct winbindd_cm_conn
*conn
;
2542 uint32_t neg_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
2544 enum netr_SchannelType sec_chan_type
;
2545 const char *account_name
;
2546 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
2550 result
= init_dc_connection_rpc(domain
);
2551 if (!NT_STATUS_IS_OK(result
)) {
2555 conn
= &domain
->conn
;
2557 if (rpccli_is_connected(conn
->netlogon_pipe
)) {
2558 *cli
= conn
->netlogon_pipe
;
2559 return NT_STATUS_OK
;
2562 TALLOC_FREE(conn
->netlogon_pipe
);
2564 result
= cli_rpc_pipe_open_noauth(conn
->cli
,
2565 &ndr_table_netlogon
.syntax_id
,
2567 if (!NT_STATUS_IS_OK(result
)) {
2571 if ((!IS_DC
) && (!domain
->primary
)) {
2572 /* Clear the schannel request bit and drop down */
2573 neg_flags
&= ~NETLOGON_NEG_SCHANNEL
;
2577 if (lp_client_schannel() != False
) {
2578 neg_flags
|= NETLOGON_NEG_SCHANNEL
;
2581 if (!get_trust_pw_hash(domain
->name
, mach_pwd
, &account_name
,
2584 TALLOC_FREE(netlogon_pipe
);
2585 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2588 result
= rpccli_netlogon_setup_creds(
2590 domain
->dcname
, /* server name. */
2591 domain
->name
, /* domain name */
2592 lp_netbios_name(), /* client name */
2593 account_name
, /* machine account */
2594 mach_pwd
, /* machine password */
2595 sec_chan_type
, /* from get_trust_pw */
2598 if (!NT_STATUS_IS_OK(result
)) {
2599 TALLOC_FREE(netlogon_pipe
);
2603 if ((lp_client_schannel() == True
) &&
2604 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2605 DEBUG(3, ("Server did not offer schannel\n"));
2606 TALLOC_FREE(netlogon_pipe
);
2607 return NT_STATUS_ACCESS_DENIED
;
2611 if ((lp_client_schannel() == False
) ||
2612 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2614 * NetSamLogonEx only works for schannel
2616 domain
->can_do_samlogon_ex
= False
;
2618 /* We're done - just keep the existing connection to NETLOGON
2620 conn
->netlogon_pipe
= netlogon_pipe
;
2621 *cli
= conn
->netlogon_pipe
;
2622 return NT_STATUS_OK
;
2625 /* Using the credentials from the first pipe, open a signed and sealed
2626 second netlogon pipe. The session key is stored in the schannel
2627 part of the new pipe auth struct.
2630 result
= cli_rpc_pipe_open_schannel_with_key(
2631 conn
->cli
, &ndr_table_netlogon
.syntax_id
, NCACN_NP
,
2632 DCERPC_AUTH_LEVEL_PRIVACY
, domain
->name
, &netlogon_pipe
->dc
,
2633 &conn
->netlogon_pipe
);
2635 /* We can now close the initial netlogon pipe. */
2636 TALLOC_FREE(netlogon_pipe
);
2638 if (!NT_STATUS_IS_OK(result
)) {
2639 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2640 "was %s\n", nt_errstr(result
)));
2642 invalidate_cm_connection(conn
);
2647 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2648 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2649 * supported). We used to only try SamLogonEx for AD, but
2650 * Samba DCs can also do it. And because we don't distinguish
2651 * between Samba and NT4, always try it once.
2653 domain
->can_do_samlogon_ex
= true;
2655 *cli
= conn
->netlogon_pipe
;
2656 return NT_STATUS_OK
;
2659 void winbind_msg_ip_dropped(struct messaging_context
*msg_ctx
,
2662 struct server_id server_id
,
2665 struct winbindd_domain
*domain
;
2666 char *freeit
= NULL
;
2670 || (data
->data
== NULL
)
2671 || (data
->length
== 0)
2672 || (data
->data
[data
->length
-1] != '\0')) {
2673 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2678 addr
= (char *)data
->data
;
2679 DEBUG(10, ("IP %s dropped\n", addr
));
2681 if (!is_ipaddress(addr
)) {
2684 * Some code sends us ip addresses with the /netmask
2687 slash
= strchr(addr
, '/');
2688 if (slash
== NULL
) {
2689 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2693 freeit
= talloc_strndup(talloc_tos(), addr
, slash
-addr
);
2694 if (freeit
== NULL
) {
2695 DEBUG(1, ("talloc failed\n"));
2699 DEBUG(10, ("Stripped /netmask to IP %s\n", addr
));
2702 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
2703 char sockaddr
[INET6_ADDRSTRLEN
];
2705 if (!cli_state_is_connected(domain
->conn
.cli
)) {
2709 print_sockaddr(sockaddr
, sizeof(sockaddr
),
2710 cli_state_local_sockaddr(domain
->conn
.cli
));
2712 if (strequal(sockaddr
, addr
)) {
2713 cli_state_disconnect(domain
->conn
.cli
);
2716 TALLOC_FREE(freeit
);