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"
66 #define DBGC_CLASS DBGC_WINBIND
70 struct sockaddr_storage ss
;
73 extern struct winbindd_methods reconnect_methods
;
74 extern bool override_logfile
;
76 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
);
77 static void set_dc_type_and_flags( struct winbindd_domain
*domain
);
78 static bool get_dcs(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
79 struct dc_name_ip
**dcs
, int *num_dcs
);
81 /****************************************************************
82 Child failed to find DC's. Reschedule check.
83 ****************************************************************/
85 static void msg_failed_to_go_online(struct messaging_context
*msg
,
88 struct server_id server_id
,
91 struct winbindd_domain
*domain
;
92 const char *domainname
= (const char *)data
->data
;
94 if (data
->data
== NULL
|| data
->length
== 0) {
98 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname
));
100 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
101 if (domain
->internal
) {
105 if (strequal(domain
->name
, domainname
)) {
106 if (domain
->online
) {
107 /* We're already online, ignore. */
108 DEBUG(5,("msg_fail_to_go_online: domain %s "
109 "already online.\n", domainname
));
113 /* Reschedule the online check. */
114 set_domain_offline(domain
);
120 /****************************************************************
121 Actually cause a reconnect from a message.
122 ****************************************************************/
124 static void msg_try_to_go_online(struct messaging_context
*msg
,
127 struct server_id server_id
,
130 struct winbindd_domain
*domain
;
131 const char *domainname
= (const char *)data
->data
;
133 if (data
->data
== NULL
|| data
->length
== 0) {
137 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname
));
139 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
140 if (domain
->internal
) {
144 if (strequal(domain
->name
, domainname
)) {
146 if (domain
->online
) {
147 /* We're already online, ignore. */
148 DEBUG(5,("msg_try_to_go_online: domain %s "
149 "already online.\n", domainname
));
153 /* This call takes care of setting the online
154 flag to true if we connected, or re-adding
155 the offline handler if false. Bypasses online
156 check so always does network calls. */
158 init_dc_connection_network(domain
);
164 /****************************************************************
165 Fork a child to try and contact a DC. Do this as contacting a
166 DC requires blocking lookups and we don't want to block our
168 ****************************************************************/
170 static bool fork_child_dc_connect(struct winbindd_domain
*domain
)
172 struct dc_name_ip
*dcs
= NULL
;
174 TALLOC_CTX
*mem_ctx
= NULL
;
175 pid_t parent_pid
= sys_getpid();
181 if (domain
->dc_probe_pid
!= (pid_t
)-1) {
183 * We might already have a DC probe
184 * child working, check.
186 if (process_exists_by_pid(domain
->dc_probe_pid
)) {
187 DEBUG(10,("fork_child_dc_connect: pid %u already "
188 "checking for DC's.\n",
189 (unsigned int)domain
->dc_probe_pid
));
192 domain
->dc_probe_pid
= (pid_t
)-1;
195 domain
->dc_probe_pid
= sys_fork();
197 if (domain
->dc_probe_pid
== (pid_t
)-1) {
198 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno
)));
202 if (domain
->dc_probe_pid
!= (pid_t
)0) {
204 messaging_register(winbind_messaging_context(), NULL
,
205 MSG_WINBIND_TRY_TO_GO_ONLINE
,
206 msg_try_to_go_online
);
207 messaging_register(winbind_messaging_context(), NULL
,
208 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
209 msg_failed_to_go_online
);
215 /* Leave messages blocked - we will never process one. */
217 if (!override_logfile
) {
218 if (asprintf(&lfile
, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
219 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
224 if (!winbindd_reinit_after_fork(lfile
)) {
225 messaging_send_buf(winbind_messaging_context(),
226 pid_to_procid(parent_pid
),
227 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
228 (uint8
*)domain
->name
,
229 strlen(domain
->name
)+1);
234 mem_ctx
= talloc_init("fork_child_dc_connect");
236 DEBUG(0,("talloc_init failed.\n"));
237 messaging_send_buf(winbind_messaging_context(),
238 pid_to_procid(parent_pid
),
239 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
240 (uint8
*)domain
->name
,
241 strlen(domain
->name
)+1);
245 if ((!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
)) || (num_dcs
== 0)) {
246 /* Still offline ? Can't find DC's. */
247 messaging_send_buf(winbind_messaging_context(),
248 pid_to_procid(parent_pid
),
249 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
250 (uint8
*)domain
->name
,
251 strlen(domain
->name
)+1);
255 /* We got a DC. Send a message to our parent to get it to
256 try and do the same. */
258 messaging_send_buf(winbind_messaging_context(),
259 pid_to_procid(parent_pid
),
260 MSG_WINBIND_TRY_TO_GO_ONLINE
,
261 (uint8
*)domain
->name
,
262 strlen(domain
->name
)+1);
266 /****************************************************************
267 Handler triggered if we're offline to try and detect a DC.
268 ****************************************************************/
270 static void check_domain_online_handler(struct event_context
*ctx
,
271 struct timed_event
*te
,
275 struct winbindd_domain
*domain
=
276 (struct winbindd_domain
*)private_data
;
278 DEBUG(10,("check_domain_online_handler: called for domain "
279 "%s (online = %s)\n", domain
->name
,
280 domain
->online
? "True" : "False" ));
282 TALLOC_FREE(domain
->check_online_event
);
284 /* Are we still in "startup" mode ? */
286 if (domain
->startup
&& (now
.tv_sec
> domain
->startup_time
+ 30)) {
287 /* No longer in "startup" mode. */
288 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
290 domain
->startup
= False
;
293 /* We've been told to stay offline, so stay
296 if (get_global_winbindd_state_offline()) {
297 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
302 /* Fork a child to test if it can contact a DC.
303 If it can then send ourselves a message to
304 cause a reconnect. */
306 fork_child_dc_connect(domain
);
309 /****************************************************************
310 If we're still offline setup the timeout check.
311 ****************************************************************/
313 static void calc_new_online_timeout_check(struct winbindd_domain
*domain
)
315 int wbr
= lp_winbind_reconnect_delay();
317 if (domain
->startup
) {
318 domain
->check_online_timeout
= 10;
319 } else if (domain
->check_online_timeout
< wbr
) {
320 domain
->check_online_timeout
= wbr
;
324 /****************************************************************
325 Set domain offline and also add handler to put us back online
327 ****************************************************************/
329 void set_domain_offline(struct winbindd_domain
*domain
)
331 DEBUG(10,("set_domain_offline: called for domain %s\n",
334 TALLOC_FREE(domain
->check_online_event
);
336 if (domain
->internal
) {
337 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
342 domain
->online
= False
;
344 /* Offline domains are always initialized. They're
345 re-initialized when they go back online. */
347 domain
->initialized
= True
;
349 /* We only add the timeout handler that checks and
350 allows us to go back online when we've not
351 been told to remain offline. */
353 if (get_global_winbindd_state_offline()) {
354 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
359 /* If we're in statup mode, check again in 10 seconds, not in
360 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
362 calc_new_online_timeout_check(domain
);
364 domain
->check_online_event
= event_add_timed(winbind_event_context(),
366 timeval_current_ofs(domain
->check_online_timeout
,0),
367 check_domain_online_handler
,
370 /* The above *has* to succeed for winbindd to work. */
371 if (!domain
->check_online_event
) {
372 smb_panic("set_domain_offline: failed to add online handler");
375 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
378 /* Send an offline message to the idmap child when our
379 primary domain goes offline */
381 if ( domain
->primary
) {
382 struct winbindd_child
*idmap
= idmap_child();
384 if ( idmap
->pid
!= 0 ) {
385 messaging_send_buf(winbind_messaging_context(),
386 pid_to_procid(idmap
->pid
),
388 (uint8
*)domain
->name
,
389 strlen(domain
->name
)+1);
396 /****************************************************************
397 Set domain online - if allowed.
398 ****************************************************************/
400 static void set_domain_online(struct winbindd_domain
*domain
)
402 DEBUG(10,("set_domain_online: called for domain %s\n",
405 if (domain
->internal
) {
406 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
411 if (get_global_winbindd_state_offline()) {
412 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
417 winbindd_set_locator_kdc_envs(domain
);
419 /* If we are waiting to get a krb5 ticket, trigger immediately. */
420 ccache_regain_all_now();
422 /* Ok, we're out of any startup mode now... */
423 domain
->startup
= False
;
425 if (domain
->online
== False
) {
426 /* We were offline - now we're online. We default to
427 using the MS-RPC backend if we started offline,
428 and if we're going online for the first time we
429 should really re-initialize the backends and the
430 checks to see if we're talking to an AD or NT domain.
433 domain
->initialized
= False
;
435 /* 'reconnect_methods' is the MS-RPC backend. */
436 if (domain
->backend
== &reconnect_methods
) {
437 domain
->backend
= NULL
;
441 /* Ensure we have no online timeout checks. */
442 domain
->check_online_timeout
= 0;
443 TALLOC_FREE(domain
->check_online_event
);
445 /* Ensure we ignore any pending child messages. */
446 messaging_deregister(winbind_messaging_context(),
447 MSG_WINBIND_TRY_TO_GO_ONLINE
, NULL
);
448 messaging_deregister(winbind_messaging_context(),
449 MSG_WINBIND_FAILED_TO_GO_ONLINE
, NULL
);
451 domain
->online
= True
;
453 /* Send an online message to the idmap child when our
454 primary domain comes online */
456 if ( domain
->primary
) {
457 struct winbindd_child
*idmap
= idmap_child();
459 if ( idmap
->pid
!= 0 ) {
460 messaging_send_buf(winbind_messaging_context(),
461 pid_to_procid(idmap
->pid
),
463 (uint8
*)domain
->name
,
464 strlen(domain
->name
)+1);
471 /****************************************************************
472 Requested to set a domain online.
473 ****************************************************************/
475 void set_domain_online_request(struct winbindd_domain
*domain
)
479 DEBUG(10,("set_domain_online_request: called for domain %s\n",
482 if (get_global_winbindd_state_offline()) {
483 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
488 /* We've been told it's safe to go online and
489 try and connect to a DC. But I don't believe it
490 because network manager seems to lie.
491 Wait at least 5 seconds. Heuristics suck... */
496 /* Go into "startup" mode again. */
497 domain
->startup_time
= tev
.tv_sec
;
498 domain
->startup
= True
;
502 if (!domain
->check_online_event
) {
503 /* If we've come from being globally offline we
504 don't have a check online event handler set.
505 We need to add one now we're trying to go
508 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
512 TALLOC_FREE(domain
->check_online_event
);
514 domain
->check_online_event
= event_add_timed(winbind_event_context(),
517 check_domain_online_handler
,
520 /* The above *has* to succeed for winbindd to work. */
521 if (!domain
->check_online_event
) {
522 smb_panic("set_domain_online_request: failed to add online handler");
526 /****************************************************************
527 Add -ve connection cache entries for domain and realm.
528 ****************************************************************/
530 void winbind_add_failed_connection_entry(const struct winbindd_domain
*domain
,
534 add_failed_connection_entry(domain
->name
, server
, result
);
535 /* If this was the saf name for the last thing we talked to,
537 saf_delete(domain
->name
);
538 if (*domain
->alt_name
) {
539 add_failed_connection_entry(domain
->alt_name
, server
, result
);
540 saf_delete(domain
->alt_name
);
542 winbindd_unset_locator_kdc_env(domain
);
545 /* Choose between anonymous or authenticated connections. We need to use
546 an authenticated connection if DCs have the RestrictAnonymous registry
547 entry set > 0, or the "Additional restrictions for anonymous
548 connections" set in the win2k Local Security Policy.
550 Caller to free() result in domain, username, password
553 static void cm_get_ipc_userpass(char **username
, char **domain
, char **password
)
555 *username
= (char *)secrets_fetch(SECRETS_AUTH_USER
, NULL
);
556 *domain
= (char *)secrets_fetch(SECRETS_AUTH_DOMAIN
, NULL
);
557 *password
= (char *)secrets_fetch(SECRETS_AUTH_PASSWORD
, NULL
);
559 if (*username
&& **username
) {
561 if (!*domain
|| !**domain
)
562 *domain
= smb_xstrdup(lp_workgroup());
564 if (!*password
|| !**password
)
565 *password
= smb_xstrdup("");
567 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
568 *domain
, *username
));
571 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
572 *username
= smb_xstrdup("");
573 *domain
= smb_xstrdup("");
574 *password
= smb_xstrdup("");
578 static bool get_dc_name_via_netlogon(struct winbindd_domain
*domain
,
580 struct sockaddr_storage
*dc_ss
)
582 struct winbindd_domain
*our_domain
= NULL
;
583 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
587 unsigned int orig_timeout
;
588 const char *tmp
= NULL
;
591 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
598 if (domain
->primary
) {
602 our_domain
= find_our_domain();
604 if ((mem_ctx
= talloc_init("get_dc_name_via_netlogon")) == NULL
) {
608 result
= cm_connect_netlogon(our_domain
, &netlogon_pipe
);
609 if (!NT_STATUS_IS_OK(result
)) {
610 talloc_destroy(mem_ctx
);
614 /* This call can take a long time - allow the server to time out.
615 35 seconds should do it. */
617 orig_timeout
= rpccli_set_timeout(netlogon_pipe
, 35000);
619 if (our_domain
->active_directory
) {
620 struct netr_DsRGetDCNameInfo
*domain_info
= NULL
;
622 result
= rpccli_netr_DsRGetDCName(netlogon_pipe
,
631 if (NT_STATUS_IS_OK(result
) && W_ERROR_IS_OK(werr
)) {
633 mem_ctx
, domain_info
->dc_unc
);
635 DEBUG(0, ("talloc_strdup failed\n"));
636 talloc_destroy(mem_ctx
);
639 if (strlen(domain
->alt_name
) == 0) {
640 fstrcpy(domain
->alt_name
,
641 domain_info
->domain_name
);
643 if (strlen(domain
->forest_name
) == 0) {
644 fstrcpy(domain
->forest_name
,
645 domain_info
->forest_name
);
649 result
= rpccli_netr_GetAnyDCName(netlogon_pipe
, mem_ctx
,
656 /* And restore our original timeout. */
657 rpccli_set_timeout(netlogon_pipe
, orig_timeout
);
659 if (!NT_STATUS_IS_OK(result
)) {
660 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
662 talloc_destroy(mem_ctx
);
666 if (!W_ERROR_IS_OK(werr
)) {
667 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
669 talloc_destroy(mem_ctx
);
673 /* rpccli_netr_GetAnyDCName gives us a name with \\ */
674 p
= strip_hostname(tmp
);
678 talloc_destroy(mem_ctx
);
680 DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname
));
682 if (!resolve_name(dcname
, dc_ss
, 0x20)) {
690 * Helper function to assemble trust password and account name
692 static NTSTATUS
get_trust_creds(const struct winbindd_domain
*domain
,
693 char **machine_password
,
694 char **machine_account
,
695 char **machine_krb5_principal
)
697 const char *account_name
;
698 const char *name
= NULL
;
700 /* If we are a DC and this is not our own domain */
705 struct winbindd_domain
*our_domain
= find_our_domain();
708 return NT_STATUS_INVALID_SERVER_STATE
;
710 name
= our_domain
->name
;
713 if (!get_trust_pw_clear(name
, machine_password
,
714 &account_name
, NULL
))
716 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
719 if ((machine_account
!= NULL
) &&
720 (asprintf(machine_account
, "%s$", account_name
) == -1))
722 return NT_STATUS_NO_MEMORY
;
725 /* For now assume our machine account only exists in our domain */
727 if (machine_krb5_principal
!= NULL
)
729 struct winbindd_domain
*our_domain
= find_our_domain();
732 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
735 if (asprintf(machine_krb5_principal
, "%s$@%s",
736 account_name
, our_domain
->alt_name
) == -1)
738 return NT_STATUS_NO_MEMORY
;
741 strupper_m(*machine_krb5_principal
);
747 /************************************************************************
748 Given a fd with a just-connected TCP connection to a DC, open a connection
750 ************************************************************************/
752 static NTSTATUS
cm_prepare_connection(const struct winbindd_domain
*domain
,
754 const char *controller
,
755 struct cli_state
**cli
,
758 char *machine_password
= NULL
;
759 char *machine_krb5_principal
= NULL
;
760 char *machine_account
= NULL
;
761 char *ipc_username
= NULL
;
762 char *ipc_domain
= NULL
;
763 char *ipc_password
= NULL
;
765 struct named_mutex
*mutex
;
767 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
769 struct sockaddr peeraddr
;
770 socklen_t peeraddr_len
;
772 struct sockaddr_in
*peeraddr_in
=
773 (struct sockaddr_in
*)(void *)&peeraddr
;
775 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
776 controller
, domain
->name
));
780 mutex
= grab_named_mutex(talloc_tos(), controller
,
781 WINBIND_SERVER_MUTEX_WAIT_TIME
);
783 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
785 result
= NT_STATUS_POSSIBLE_DEADLOCK
;
789 if ((*cli
= cli_initialise()) == NULL
) {
790 DEBUG(1, ("Could not cli_initialize\n"));
791 result
= NT_STATUS_NO_MEMORY
;
795 (*cli
)->timeout
= 10000; /* 10 seconds */
797 fstrcpy((*cli
)->desthost
, controller
);
798 (*cli
)->use_kerberos
= True
;
800 peeraddr_len
= sizeof(peeraddr
);
802 if ((getpeername((*cli
)->fd
, &peeraddr
, &peeraddr_len
) != 0) ||
803 (peeraddr_len
!= sizeof(struct sockaddr_in
)) ||
804 (peeraddr_in
->sin_family
!= PF_INET
))
806 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno
)));
807 result
= NT_STATUS_UNSUCCESSFUL
;
811 if (ntohs(peeraddr_in
->sin_port
) == 139) {
812 struct nmb_name calling
;
813 struct nmb_name called
;
815 make_nmb_name(&calling
, global_myname(), 0x0);
816 make_nmb_name(&called
, "*SMBSERVER", 0x20);
818 if (!cli_session_request(*cli
, &calling
, &called
)) {
819 DEBUG(8, ("cli_session_request failed for %s\n",
821 result
= NT_STATUS_UNSUCCESSFUL
;
826 result
= cli_negprot(*cli
);
828 if (!NT_STATUS_IS_OK(result
)) {
829 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result
)));
833 if (!is_dc_trusted_domain_situation(domain
->name
) &&
834 (*cli
)->protocol
>= PROTOCOL_NT1
&&
835 (*cli
)->capabilities
& CAP_EXTENDED_SECURITY
)
837 ADS_STATUS ads_status
;
839 result
= get_trust_creds(domain
, &machine_password
,
841 &machine_krb5_principal
);
842 if (!NT_STATUS_IS_OK(result
)) {
846 if (lp_security() == SEC_ADS
) {
848 /* Try a krb5 session */
850 (*cli
)->use_kerberos
= True
;
851 DEBUG(5, ("connecting to %s from %s with kerberos principal "
852 "[%s] and realm [%s]\n", controller
, global_myname(),
853 machine_krb5_principal
, domain
->alt_name
));
855 winbindd_set_locator_kdc_envs(domain
);
857 ads_status
= cli_session_setup_spnego(*cli
,
858 machine_krb5_principal
,
863 if (!ADS_ERR_OK(ads_status
)) {
864 DEBUG(4,("failed kerberos session setup with %s\n",
865 ads_errstr(ads_status
)));
868 result
= ads_ntstatus(ads_status
);
869 if (NT_STATUS_IS_OK(result
)) {
870 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
871 result
= cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
872 if (!NT_STATUS_IS_OK(result
)) {
875 goto session_setup_done
;
879 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
880 (*cli
)->use_kerberos
= False
;
882 DEBUG(5, ("connecting to %s from %s with username "
883 "[%s]\\[%s]\n", controller
, global_myname(),
884 lp_workgroup(), machine_account
));
886 ads_status
= cli_session_setup_spnego(*cli
,
891 if (!ADS_ERR_OK(ads_status
)) {
892 DEBUG(4, ("authenticated session setup failed with %s\n",
893 ads_errstr(ads_status
)));
896 result
= ads_ntstatus(ads_status
);
897 if (NT_STATUS_IS_OK(result
)) {
898 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
899 result
= cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
900 if (!NT_STATUS_IS_OK(result
)) {
903 goto session_setup_done
;
907 /* Fall back to non-kerberos session setup with auth_user */
909 (*cli
)->use_kerberos
= False
;
911 cm_get_ipc_userpass(&ipc_username
, &ipc_domain
, &ipc_password
);
913 if ((((*cli
)->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) != 0) &&
914 (strlen(ipc_username
) > 0)) {
916 /* Only try authenticated if we have a username */
918 DEBUG(5, ("connecting to %s from %s with username "
919 "[%s]\\[%s]\n", controller
, global_myname(),
920 ipc_domain
, ipc_username
));
922 if (NT_STATUS_IS_OK(cli_session_setup(
924 ipc_password
, strlen(ipc_password
)+1,
925 ipc_password
, strlen(ipc_password
)+1,
927 /* Successful logon with given username. */
928 result
= cli_init_creds(*cli
, ipc_username
, ipc_domain
, ipc_password
);
929 if (!NT_STATUS_IS_OK(result
)) {
932 goto session_setup_done
;
934 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
935 ipc_domain
, ipc_username
));
941 /* Fall back to anonymous connection, this might fail later */
942 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
943 "connection for DC %s\n",
946 if (NT_STATUS_IS_OK(cli_session_setup(*cli
, "", NULL
, 0,
948 DEBUG(5, ("Connected anonymously\n"));
949 result
= cli_init_creds(*cli
, "", "", "");
950 if (!NT_STATUS_IS_OK(result
)) {
953 goto session_setup_done
;
956 result
= cli_nt_error(*cli
);
958 if (NT_STATUS_IS_OK(result
))
959 result
= NT_STATUS_UNSUCCESSFUL
;
961 /* We can't session setup */
967 /* cache the server name for later connections */
969 saf_store( domain
->name
, (*cli
)->desthost
);
970 if (domain
->alt_name
&& (*cli
)->use_kerberos
) {
971 saf_store( domain
->alt_name
, (*cli
)->desthost
);
974 winbindd_set_locator_kdc_envs(domain
);
976 result
= cli_tcon_andx(*cli
, "IPC$", "IPC", "", 0);
978 if (!NT_STATUS_IS_OK(result
)) {
979 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result
)));
986 /* set the domain if empty; needed for schannel connections */
987 if ( !(*cli
)->domain
[0] ) {
988 result
= cli_set_domain((*cli
), domain
->name
);
989 if (!NT_STATUS_IS_OK(result
)) {
994 result
= NT_STATUS_OK
;
998 SAFE_FREE(machine_account
);
999 SAFE_FREE(machine_password
);
1000 SAFE_FREE(machine_krb5_principal
);
1001 SAFE_FREE(ipc_username
);
1002 SAFE_FREE(ipc_domain
);
1003 SAFE_FREE(ipc_password
);
1005 if (!NT_STATUS_IS_OK(result
)) {
1006 winbind_add_failed_connection_entry(domain
, controller
, result
);
1007 if ((*cli
) != NULL
) {
1016 /*******************************************************************
1017 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1020 Keeps the list unique by not adding duplicate entries.
1022 @param[in] mem_ctx talloc memory context to allocate from
1023 @param[in] domain_name domain of the DC
1024 @param[in] dcname name of the DC to add to the list
1025 @param[in] pss Internet address and port pair to add to the list
1026 @param[in,out] dcs array of dc_name_ip structures to add to
1027 @param[in,out] num_dcs number of dcs returned in the dcs array
1028 @return true if the list was added to, false otherwise
1029 *******************************************************************/
1031 static bool add_one_dc_unique(TALLOC_CTX
*mem_ctx
, const char *domain_name
,
1032 const char *dcname
, struct sockaddr_storage
*pss
,
1033 struct dc_name_ip
**dcs
, int *num
)
1037 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name
, dcname
))) {
1038 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname
));
1042 /* Make sure there's no duplicates in the list */
1043 for (i
=0; i
<*num
; i
++)
1045 (struct sockaddr
*)(void *)&(*dcs
)[i
].ss
,
1046 (struct sockaddr
*)(void *)pss
))
1049 *dcs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *dcs
, struct dc_name_ip
, (*num
)+1);
1054 fstrcpy((*dcs
)[*num
].name
, dcname
);
1055 (*dcs
)[*num
].ss
= *pss
;
1060 static bool add_sockaddr_to_array(TALLOC_CTX
*mem_ctx
,
1061 struct sockaddr_storage
*pss
, uint16 port
,
1062 struct sockaddr_storage
**addrs
, int *num
)
1064 *addrs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *addrs
, struct sockaddr_storage
, (*num
)+1);
1066 if (*addrs
== NULL
) {
1071 (*addrs
)[*num
] = *pss
;
1072 set_sockaddr_port((struct sockaddr
*)&(*addrs
)[*num
], port
);
1078 /*******************************************************************
1079 convert an ip to a name
1080 *******************************************************************/
1082 static bool dcip_to_name(TALLOC_CTX
*mem_ctx
,
1083 const struct winbindd_domain
*domain
,
1084 struct sockaddr_storage
*pss
,
1087 struct ip_service ip_list
;
1088 uint32_t nt_version
= NETLOGON_NT_VERSION_1
;
1094 /* For active directory servers, try to get the ldap server name.
1095 None of these failures should be considered critical for now */
1097 if (lp_security() == SEC_ADS
) {
1099 ADS_STATUS ads_status
;
1100 char addr
[INET6_ADDRSTRLEN
];
1102 print_sockaddr(addr
, sizeof(addr
), pss
);
1104 ads
= ads_init(domain
->alt_name
, domain
->name
, addr
);
1105 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
1107 ads_status
= ads_connect(ads
);
1108 if (ADS_ERR_OK(ads_status
)) {
1109 /* We got a cldap packet. */
1110 fstrcpy(name
, ads
->config
.ldap_server_name
);
1111 namecache_store(name
, 0x20, 1, &ip_list
);
1113 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads
->config
.flags
));
1115 if (domain
->primary
&& (ads
->config
.flags
& NBT_SERVER_KDC
)) {
1116 if (ads_closest_dc(ads
)) {
1117 char *sitename
= sitename_fetch(ads
->config
.realm
);
1119 /* We're going to use this KDC for this realm/domain.
1120 If we are using sites, then force the krb5 libs
1123 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1128 SAFE_FREE(sitename
);
1130 /* use an off site KDC */
1131 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1136 winbindd_set_locator_kdc_envs(domain
);
1138 /* Ensure we contact this DC also. */
1139 saf_store( domain
->name
, name
);
1140 saf_store( domain
->alt_name
, name
);
1143 ads_destroy( &ads
);
1147 ads_destroy( &ads
);
1151 /* try GETDC requests next */
1153 if (send_getdc_request(mem_ctx
, winbind_messaging_context(),
1154 pss
, domain
->name
, &domain
->sid
,
1156 const char *dc_name
= NULL
;
1159 for (i
=0; i
<5; i
++) {
1160 if (receive_getdc_response(mem_ctx
, pss
, domain
->name
,
1163 fstrcpy(name
, dc_name
);
1164 namecache_store(name
, 0x20, 1, &ip_list
);
1171 /* try node status request */
1173 if ( name_status_find(domain
->name
, 0x1c, 0x20, pss
, name
) ) {
1174 namecache_store(name
, 0x20, 1, &ip_list
);
1180 /*******************************************************************
1181 Retrieve a list of IP addresses for domain controllers.
1183 The array is sorted in the preferred connection order.
1185 @param[in] mem_ctx talloc memory context to allocate from
1186 @param[in] domain domain to retrieve DCs for
1187 @param[out] dcs array of dcs that will be returned
1188 @param[out] num_dcs number of dcs returned in the dcs array
1190 *******************************************************************/
1192 static bool get_dcs(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
1193 struct dc_name_ip
**dcs
, int *num_dcs
)
1196 struct sockaddr_storage ss
;
1197 struct ip_service
*ip_list
= NULL
;
1198 int iplist_size
= 0;
1201 enum security_types sec
= (enum security_types
)lp_security();
1203 is_our_domain
= strequal(domain
->name
, lp_workgroup());
1205 /* If not our domain, get the preferred DC, by asking our primary DC */
1207 && get_dc_name_via_netlogon(domain
, dcname
, &ss
)
1208 && add_one_dc_unique(mem_ctx
, domain
->name
, dcname
, &ss
, dcs
,
1211 char addr
[INET6_ADDRSTRLEN
];
1212 print_sockaddr(addr
, sizeof(addr
), &ss
);
1213 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1218 if (sec
== SEC_ADS
) {
1219 char *sitename
= NULL
;
1221 /* We need to make sure we know the local site before
1222 doing any DNS queries, as this will restrict the
1223 get_sorted_dc_list() call below to only fetching
1224 DNS records for the correct site. */
1226 /* Find any DC to get the site record.
1227 We deliberately don't care about the
1230 get_dc_name(domain
->name
, domain
->alt_name
, dcname
, &ss
);
1232 sitename
= sitename_fetch(domain
->alt_name
);
1235 /* Do the site-specific AD dns lookup first. */
1236 get_sorted_dc_list(domain
->alt_name
, sitename
, &ip_list
,
1237 &iplist_size
, True
);
1239 /* Add ips to the DC array. We don't look up the name
1240 of the DC in this function, but we fill in the char*
1241 of the ip now to make the failed connection cache
1243 for ( i
=0; i
<iplist_size
; i
++ ) {
1244 char addr
[INET6_ADDRSTRLEN
];
1245 print_sockaddr(addr
, sizeof(addr
),
1247 add_one_dc_unique(mem_ctx
,
1256 SAFE_FREE(sitename
);
1260 /* Now we add DCs from the main AD DNS lookup. */
1261 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
,
1262 &iplist_size
, True
);
1264 for ( i
=0; i
<iplist_size
; i
++ ) {
1265 char addr
[INET6_ADDRSTRLEN
];
1266 print_sockaddr(addr
, sizeof(addr
),
1268 add_one_dc_unique(mem_ctx
,
1280 /* Try standard netbios queries if no ADS */
1281 if (*num_dcs
== 0) {
1282 get_sorted_dc_list(domain
->name
, NULL
, &ip_list
, &iplist_size
,
1285 for ( i
=0; i
<iplist_size
; i
++ ) {
1286 char addr
[INET6_ADDRSTRLEN
];
1287 print_sockaddr(addr
, sizeof(addr
),
1289 add_one_dc_unique(mem_ctx
,
1304 /*******************************************************************
1305 Find and make a connection to a DC in the given domain.
1307 @param[in] mem_ctx talloc memory context to allocate from
1308 @param[in] domain domain to find a dc in
1309 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1310 @param[out] pss DC Internet address and port
1311 @param[out] fd fd of the open socket connected to the newly found dc
1312 @return true when a DC connection is made, false otherwise
1313 *******************************************************************/
1315 static bool find_new_dc(TALLOC_CTX
*mem_ctx
,
1316 struct winbindd_domain
*domain
,
1317 fstring dcname
, struct sockaddr_storage
*pss
, int *fd
)
1319 struct dc_name_ip
*dcs
= NULL
;
1322 const char **dcnames
= NULL
;
1323 int num_dcnames
= 0;
1325 struct sockaddr_storage
*addrs
= NULL
;
1333 if (!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
) || (num_dcs
== 0))
1336 for (i
=0; i
<num_dcs
; i
++) {
1338 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1339 &dcnames
, &num_dcnames
)) {
1342 if (!add_sockaddr_to_array(mem_ctx
, &dcs
[i
].ss
, 445,
1343 &addrs
, &num_addrs
)) {
1347 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1348 &dcnames
, &num_dcnames
)) {
1351 if (!add_sockaddr_to_array(mem_ctx
, &dcs
[i
].ss
, 139,
1352 &addrs
, &num_addrs
)) {
1357 if ((num_dcnames
== 0) || (num_dcnames
!= num_addrs
))
1360 if ((addrs
== NULL
) || (dcnames
== NULL
))
1363 /* 5 second timeout. */
1364 if (!open_any_socket_out(addrs
, num_addrs
, 5000, &fd_index
, fd
) ) {
1365 for (i
=0; i
<num_dcs
; i
++) {
1366 char ab
[INET6_ADDRSTRLEN
];
1367 print_sockaddr(ab
, sizeof(ab
), &dcs
[i
].ss
);
1368 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1369 "domain %s address %s. Error was %s\n",
1370 domain
->name
, ab
, strerror(errno
) ));
1371 winbind_add_failed_connection_entry(domain
,
1372 dcs
[i
].name
, NT_STATUS_UNSUCCESSFUL
);
1377 *pss
= addrs
[fd_index
];
1379 if (*dcnames
[fd_index
] != '\0' && !is_ipaddress(dcnames
[fd_index
])) {
1380 /* Ok, we've got a name for the DC */
1381 fstrcpy(dcname
, dcnames
[fd_index
]);
1385 /* Try to figure out the name */
1386 if (dcip_to_name(mem_ctx
, domain
, pss
, dcname
)) {
1390 /* We can not continue without the DC's name */
1391 winbind_add_failed_connection_entry(domain
, dcs
[fd_index
].name
,
1392 NT_STATUS_UNSUCCESSFUL
);
1394 /* Throw away all arrays as we're doing this again. */
1398 TALLOC_FREE(dcnames
);
1410 static NTSTATUS
cm_open_connection(struct winbindd_domain
*domain
,
1411 struct winbindd_cm_conn
*new_conn
)
1413 TALLOC_CTX
*mem_ctx
;
1415 char *saf_servername
= saf_fetch( domain
->name
);
1418 if ((mem_ctx
= talloc_init("cm_open_connection")) == NULL
) {
1419 SAFE_FREE(saf_servername
);
1420 set_domain_offline(domain
);
1421 return NT_STATUS_NO_MEMORY
;
1424 /* we have to check the server affinity cache here since
1425 later we selecte a DC based on response time and not preference */
1427 /* Check the negative connection cache
1428 before talking to it. It going down may have
1429 triggered the reconnection. */
1431 if ( saf_servername
&& NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, saf_servername
))) {
1433 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1434 saf_servername
, domain
->name
));
1436 /* convert an ip address to a name */
1437 if (is_ipaddress( saf_servername
) ) {
1439 struct sockaddr_storage ss
;
1441 if (!interpret_string_addr(&ss
, saf_servername
,
1443 return NT_STATUS_UNSUCCESSFUL
;
1445 if (dcip_to_name(mem_ctx
, domain
, &ss
, saf_name
)) {
1446 fstrcpy( domain
->dcname
, saf_name
);
1448 winbind_add_failed_connection_entry(
1449 domain
, saf_servername
,
1450 NT_STATUS_UNSUCCESSFUL
);
1453 fstrcpy( domain
->dcname
, saf_servername
);
1456 SAFE_FREE( saf_servername
);
1459 for (retries
= 0; retries
< 3; retries
++) {
1463 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1465 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1466 domain
->dcname
, domain
->name
));
1469 && NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, domain
->dcname
))
1470 && (resolve_name(domain
->dcname
, &domain
->dcaddr
, 0x20)))
1472 struct sockaddr_storage
*addrs
= NULL
;
1476 if (!add_sockaddr_to_array(mem_ctx
, &domain
->dcaddr
, 445, &addrs
, &num_addrs
)) {
1477 set_domain_offline(domain
);
1478 talloc_destroy(mem_ctx
);
1479 return NT_STATUS_NO_MEMORY
;
1481 if (!add_sockaddr_to_array(mem_ctx
, &domain
->dcaddr
, 139, &addrs
, &num_addrs
)) {
1482 set_domain_offline(domain
);
1483 talloc_destroy(mem_ctx
);
1484 return NT_STATUS_NO_MEMORY
;
1487 /* 5 second timeout. */
1488 if (!open_any_socket_out(addrs
, num_addrs
, 5000, &dummy
, &fd
)) {
1494 && !find_new_dc(mem_ctx
, domain
, domain
->dcname
, &domain
->dcaddr
, &fd
))
1496 /* This is the one place where we will
1497 set the global winbindd offline state
1498 to true, if a "WINBINDD_OFFLINE" entry
1499 is found in the winbindd cache. */
1500 set_global_winbindd_state_offline();
1504 new_conn
->cli
= NULL
;
1506 result
= cm_prepare_connection(domain
, fd
, domain
->dcname
,
1507 &new_conn
->cli
, &retry
);
1513 if (NT_STATUS_IS_OK(result
)) {
1515 winbindd_set_locator_kdc_envs(domain
);
1517 if (domain
->online
== False
) {
1518 /* We're changing state from offline to online. */
1519 set_global_winbindd_state_online();
1521 set_domain_online(domain
);
1523 /* Ensure we setup the retry handler. */
1524 set_domain_offline(domain
);
1527 talloc_destroy(mem_ctx
);
1531 /* Close down all open pipes on a connection. */
1533 void invalidate_cm_connection(struct winbindd_cm_conn
*conn
)
1535 /* We're closing down a possibly dead
1536 connection. Don't have impossibly long (10s) timeouts. */
1539 cli_set_timeout(conn
->cli
, 1000); /* 1 second. */
1542 if (conn
->samr_pipe
!= NULL
) {
1543 TALLOC_FREE(conn
->samr_pipe
);
1544 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1546 cli_set_timeout(conn
->cli
, 500);
1550 if (conn
->lsa_pipe
!= NULL
) {
1551 TALLOC_FREE(conn
->lsa_pipe
);
1552 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1554 cli_set_timeout(conn
->cli
, 500);
1558 if (conn
->netlogon_pipe
!= NULL
) {
1559 TALLOC_FREE(conn
->netlogon_pipe
);
1560 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1562 cli_set_timeout(conn
->cli
, 500);
1567 cli_shutdown(conn
->cli
);
1573 void close_conns_after_fork(void)
1575 struct winbindd_domain
*domain
;
1577 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
1578 if (domain
->conn
.cli
== NULL
)
1581 if (domain
->conn
.cli
->fd
== -1)
1584 close(domain
->conn
.cli
->fd
);
1585 domain
->conn
.cli
->fd
= -1;
1589 static bool connection_ok(struct winbindd_domain
*domain
)
1591 if (domain
->conn
.cli
== NULL
) {
1592 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1593 "cli!\n", domain
->dcname
, domain
->name
));
1597 if (!domain
->conn
.cli
->initialised
) {
1598 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1599 "initialised!\n", domain
->dcname
, domain
->name
));
1603 if (domain
->conn
.cli
->fd
== -1) {
1604 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1605 "never started (fd == -1)\n",
1606 domain
->dcname
, domain
->name
));
1610 if (domain
->online
== False
) {
1611 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain
->name
));
1618 /* Initialize a new connection up to the RPC BIND.
1619 Bypass online status check so always does network calls. */
1621 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
)
1625 /* Internal connections never use the network. */
1626 if (domain
->internal
) {
1627 domain
->initialized
= True
;
1628 return NT_STATUS_OK
;
1631 if (connection_ok(domain
)) {
1632 if (!domain
->initialized
) {
1633 set_dc_type_and_flags(domain
);
1635 return NT_STATUS_OK
;
1638 invalidate_cm_connection(&domain
->conn
);
1640 result
= cm_open_connection(domain
, &domain
->conn
);
1642 if (NT_STATUS_IS_OK(result
) && !domain
->initialized
) {
1643 set_dc_type_and_flags(domain
);
1649 NTSTATUS
init_dc_connection(struct winbindd_domain
*domain
)
1651 if (domain
->initialized
&& !domain
->online
) {
1652 /* We check for online status elsewhere. */
1653 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1656 return init_dc_connection_network(domain
);
1659 /******************************************************************************
1660 Set the trust flags (direction and forest location) for a domain
1661 ******************************************************************************/
1663 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain
*domain
)
1665 struct winbindd_domain
*our_domain
;
1666 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1667 struct netr_DomainTrustList trusts
;
1669 uint32 flags
= (NETR_TRUST_FLAG_IN_FOREST
|
1670 NETR_TRUST_FLAG_OUTBOUND
|
1671 NETR_TRUST_FLAG_INBOUND
);
1672 struct rpc_pipe_client
*cli
;
1673 TALLOC_CTX
*mem_ctx
= NULL
;
1675 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain
->name
));
1677 /* Our primary domain doesn't need to worry about trust flags.
1678 Force it to go through the network setup */
1679 if ( domain
->primary
) {
1683 our_domain
= find_our_domain();
1685 if ( !connection_ok(our_domain
) ) {
1686 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1690 /* This won't work unless our domain is AD */
1692 if ( !our_domain
->active_directory
) {
1696 /* Use DsEnumerateDomainTrusts to get us the trust direction
1699 result
= cm_connect_netlogon(our_domain
, &cli
);
1701 if (!NT_STATUS_IS_OK(result
)) {
1702 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1703 "a connection to %s for PIPE_NETLOGON (%s)\n",
1704 domain
->name
, nt_errstr(result
)));
1708 if ( (mem_ctx
= talloc_init("set_dc_type_and_flags_trustinfo")) == NULL
) {
1709 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1713 result
= rpccli_netr_DsrEnumerateDomainTrusts(cli
, mem_ctx
,
1718 if (!NT_STATUS_IS_OK(result
)) {
1719 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1720 "failed to query trusted domain list: %s\n",
1721 nt_errstr(result
)));
1722 talloc_destroy(mem_ctx
);
1726 /* Now find the domain name and get the flags */
1728 for ( i
=0; i
<trusts
.count
; i
++ ) {
1729 if ( strequal( domain
->name
, trusts
.array
[i
].netbios_name
) ) {
1730 domain
->domain_flags
= trusts
.array
[i
].trust_flags
;
1731 domain
->domain_type
= trusts
.array
[i
].trust_type
;
1732 domain
->domain_trust_attribs
= trusts
.array
[i
].trust_attributes
;
1734 if ( domain
->domain_type
== NETR_TRUST_TYPE_UPLEVEL
)
1735 domain
->active_directory
= True
;
1737 /* This flag is only set if the domain is *our*
1738 primary domain and the primary domain is in
1741 domain
->native_mode
= (domain
->domain_flags
& NETR_TRUST_FLAG_NATIVE
);
1743 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1744 "native mode.\n", domain
->name
,
1745 domain
->native_mode
? "" : "NOT "));
1747 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1748 "running active directory.\n", domain
->name
,
1749 domain
->active_directory
? "" : "NOT "));
1752 domain
->initialized
= True
;
1754 if ( !winbindd_can_contact_domain( domain
) )
1755 domain
->internal
= True
;
1761 talloc_destroy( mem_ctx
);
1763 return domain
->initialized
;
1766 /******************************************************************************
1767 We can 'sense' certain things about the DC by it's replies to certain
1770 This tells us if this particular remote server is Active Directory, and if it
1772 ******************************************************************************/
1774 static void set_dc_type_and_flags_connect( struct winbindd_domain
*domain
)
1778 TALLOC_CTX
*mem_ctx
= NULL
;
1779 struct rpc_pipe_client
*cli
= NULL
;
1780 struct policy_handle pol
;
1781 union dssetup_DsRoleInfo info
;
1782 union lsa_PolicyInformation
*lsa_info
= NULL
;
1784 if (!connection_ok(domain
)) {
1788 mem_ctx
= talloc_init("set_dc_type_and_flags on domain %s\n",
1791 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1795 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain
->name
));
1797 result
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
1798 &ndr_table_dssetup
.syntax_id
,
1801 if (!NT_STATUS_IS_OK(result
)) {
1802 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1803 "PI_DSSETUP on domain %s: (%s)\n",
1804 domain
->name
, nt_errstr(result
)));
1806 /* if this is just a non-AD domain we need to continue
1807 * identifying so that we can in the end return with
1808 * domain->initialized = True - gd */
1813 result
= rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli
, mem_ctx
,
1814 DS_ROLE_BASIC_INFORMATION
,
1819 if (!NT_STATUS_IS_OK(result
)) {
1820 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1821 "on domain %s failed: (%s)\n",
1822 domain
->name
, nt_errstr(result
)));
1824 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1825 * every opcode on the DSSETUP pipe, continue with
1826 * no_dssetup mode here as well to get domain->initialized
1829 if (NT_STATUS_V(result
) == DCERPC_FAULT_OP_RNG_ERROR
) {
1833 TALLOC_FREE(mem_ctx
);
1837 if ((info
.basic
.flags
& DS_ROLE_PRIMARY_DS_RUNNING
) &&
1838 !(info
.basic
.flags
& DS_ROLE_PRIMARY_DS_MIXED_MODE
)) {
1839 domain
->native_mode
= True
;
1841 domain
->native_mode
= False
;
1845 result
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
1846 &ndr_table_lsarpc
.syntax_id
, &cli
);
1848 if (!NT_STATUS_IS_OK(result
)) {
1849 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1850 "PI_LSARPC on domain %s: (%s)\n",
1851 domain
->name
, nt_errstr(result
)));
1853 TALLOC_FREE(mem_ctx
);
1857 result
= rpccli_lsa_open_policy2(cli
, mem_ctx
, True
,
1858 SEC_FLAG_MAXIMUM_ALLOWED
, &pol
);
1860 if (NT_STATUS_IS_OK(result
)) {
1861 /* This particular query is exactly what Win2k clients use
1862 to determine that the DC is active directory */
1863 result
= rpccli_lsa_QueryInfoPolicy2(cli
, mem_ctx
,
1865 LSA_POLICY_INFO_DNS
,
1869 if (NT_STATUS_IS_OK(result
)) {
1870 domain
->active_directory
= True
;
1872 if (lsa_info
->dns
.name
.string
) {
1873 fstrcpy(domain
->name
, lsa_info
->dns
.name
.string
);
1876 if (lsa_info
->dns
.dns_domain
.string
) {
1877 fstrcpy(domain
->alt_name
,
1878 lsa_info
->dns
.dns_domain
.string
);
1881 /* See if we can set some domain trust flags about
1884 if (lsa_info
->dns
.dns_forest
.string
) {
1885 fstrcpy(domain
->forest_name
,
1886 lsa_info
->dns
.dns_forest
.string
);
1888 if (strequal(domain
->forest_name
, domain
->alt_name
)) {
1889 domain
->domain_flags
|= NETR_TRUST_FLAG_TREEROOT
;
1893 if (lsa_info
->dns
.sid
) {
1894 sid_copy(&domain
->sid
, lsa_info
->dns
.sid
);
1897 domain
->active_directory
= False
;
1899 result
= rpccli_lsa_open_policy(cli
, mem_ctx
, True
,
1900 SEC_FLAG_MAXIMUM_ALLOWED
,
1903 if (!NT_STATUS_IS_OK(result
)) {
1907 result
= rpccli_lsa_QueryInfoPolicy(cli
, mem_ctx
,
1909 LSA_POLICY_INFO_ACCOUNT_DOMAIN
,
1912 if (NT_STATUS_IS_OK(result
)) {
1914 if (lsa_info
->account_domain
.name
.string
) {
1915 fstrcpy(domain
->name
,
1916 lsa_info
->account_domain
.name
.string
);
1919 if (lsa_info
->account_domain
.sid
) {
1920 sid_copy(&domain
->sid
, lsa_info
->account_domain
.sid
);
1926 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1927 domain
->name
, domain
->native_mode
? "" : "NOT "));
1929 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1930 domain
->name
, domain
->active_directory
? "" : "NOT "));
1934 TALLOC_FREE(mem_ctx
);
1936 domain
->initialized
= True
;
1939 /**********************************************************************
1940 Set the domain_flags (trust attributes, domain operating modes, etc...
1941 ***********************************************************************/
1943 static void set_dc_type_and_flags( struct winbindd_domain
*domain
)
1945 /* we always have to contact our primary domain */
1947 if ( domain
->primary
) {
1948 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1949 "primary domain\n"));
1950 set_dc_type_and_flags_connect( domain
);
1954 /* Use our DC to get the information if possible */
1956 if ( !set_dc_type_and_flags_trustinfo( domain
) ) {
1957 /* Otherwise, fallback to contacting the
1959 set_dc_type_and_flags_connect( domain
);
1967 /**********************************************************************
1968 ***********************************************************************/
1970 static bool cm_get_schannel_creds(struct winbindd_domain
*domain
,
1971 struct netlogon_creds_CredentialState
**ppdc
)
1974 struct rpc_pipe_client
*netlogon_pipe
;
1976 if (lp_client_schannel() == False
) {
1980 result
= cm_connect_netlogon(domain
, &netlogon_pipe
);
1981 if (!NT_STATUS_IS_OK(result
)) {
1985 /* Return a pointer to the struct netlogon_creds_CredentialState from the
1988 if (!domain
->conn
.netlogon_pipe
->dc
) {
1992 *ppdc
= domain
->conn
.netlogon_pipe
->dc
;
1996 NTSTATUS
cm_connect_sam(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
1997 struct rpc_pipe_client
**cli
, struct policy_handle
*sam_handle
)
1999 struct winbindd_cm_conn
*conn
;
2000 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2001 struct netlogon_creds_CredentialState
*p_creds
;
2002 char *machine_password
= NULL
;
2003 char *machine_account
= NULL
;
2004 char *domain_name
= NULL
;
2006 result
= init_dc_connection(domain
);
2007 if (!NT_STATUS_IS_OK(result
)) {
2011 conn
= &domain
->conn
;
2013 if (conn
->samr_pipe
!= NULL
) {
2019 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2020 * sign and sealed pipe using the machine account password by
2021 * preference. If we can't - try schannel, if that fails, try
2025 if ((conn
->cli
->user_name
[0] == '\0') ||
2026 (conn
->cli
->domain
[0] == '\0') ||
2027 (conn
->cli
->password
== NULL
|| conn
->cli
->password
[0] == '\0'))
2029 result
= get_trust_creds(domain
, &machine_password
,
2030 &machine_account
, NULL
);
2031 if (!NT_STATUS_IS_OK(result
)) {
2032 DEBUG(10, ("cm_connect_sam: No no user available for "
2033 "domain %s, trying schannel\n", conn
->cli
->domain
));
2036 domain_name
= domain
->name
;
2038 machine_password
= SMB_STRDUP(conn
->cli
->password
);
2039 machine_account
= SMB_STRDUP(conn
->cli
->user_name
);
2040 domain_name
= conn
->cli
->domain
;
2043 if (!machine_password
|| !machine_account
) {
2044 result
= NT_STATUS_NO_MEMORY
;
2048 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2049 authenticated SAMR pipe with sign & seal. */
2050 result
= cli_rpc_pipe_open_spnego_ntlmssp(conn
->cli
,
2051 &ndr_table_samr
.syntax_id
,
2052 PIPE_AUTH_LEVEL_PRIVACY
,
2058 if (!NT_STATUS_IS_OK(result
)) {
2059 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2060 "pipe for domain %s using NTLMSSP "
2061 "authenticated pipe: user %s\\%s. Error was "
2062 "%s\n", domain
->name
, domain_name
,
2063 machine_account
, nt_errstr(result
)));
2067 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2068 "domain %s using NTLMSSP authenticated "
2069 "pipe: user %s\\%s\n", domain
->name
,
2070 domain_name
, machine_account
));
2072 result
= rpccli_samr_Connect2(conn
->samr_pipe
, mem_ctx
,
2073 conn
->samr_pipe
->desthost
,
2074 SEC_FLAG_MAXIMUM_ALLOWED
,
2075 &conn
->sam_connect_handle
);
2076 if (NT_STATUS_IS_OK(result
)) {
2079 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2080 "failed for domain %s, error was %s. Trying schannel\n",
2081 domain
->name
, nt_errstr(result
) ));
2082 TALLOC_FREE(conn
->samr_pipe
);
2086 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2088 if (!cm_get_schannel_creds(domain
, &p_creds
)) {
2089 /* If this call fails - conn->cli can now be NULL ! */
2090 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2091 "for domain %s, trying anon\n", domain
->name
));
2094 result
= cli_rpc_pipe_open_schannel_with_key
2095 (conn
->cli
, &ndr_table_samr
.syntax_id
, PIPE_AUTH_LEVEL_PRIVACY
,
2096 domain
->name
, &p_creds
, &conn
->samr_pipe
);
2098 if (!NT_STATUS_IS_OK(result
)) {
2099 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2100 "domain %s using schannel. Error was %s\n",
2101 domain
->name
, nt_errstr(result
) ));
2104 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2105 "schannel.\n", domain
->name
));
2107 result
= rpccli_samr_Connect2(conn
->samr_pipe
, mem_ctx
,
2108 conn
->samr_pipe
->desthost
,
2109 SEC_FLAG_MAXIMUM_ALLOWED
,
2110 &conn
->sam_connect_handle
);
2111 if (NT_STATUS_IS_OK(result
)) {
2114 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2115 "for domain %s, error was %s. Trying anonymous\n",
2116 domain
->name
, nt_errstr(result
) ));
2117 TALLOC_FREE(conn
->samr_pipe
);
2121 /* Finally fall back to anonymous. */
2122 result
= cli_rpc_pipe_open_noauth(conn
->cli
, &ndr_table_samr
.syntax_id
,
2125 if (!NT_STATUS_IS_OK(result
)) {
2129 result
= rpccli_samr_Connect2(conn
->samr_pipe
, mem_ctx
,
2130 conn
->samr_pipe
->desthost
,
2131 SEC_FLAG_MAXIMUM_ALLOWED
,
2132 &conn
->sam_connect_handle
);
2133 if (!NT_STATUS_IS_OK(result
)) {
2134 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2135 "for domain %s Error was %s\n",
2136 domain
->name
, nt_errstr(result
) ));
2141 result
= rpccli_samr_OpenDomain(conn
->samr_pipe
,
2143 &conn
->sam_connect_handle
,
2144 SEC_FLAG_MAXIMUM_ALLOWED
,
2146 &conn
->sam_domain_handle
);
2150 if (!NT_STATUS_IS_OK(result
)) {
2151 invalidate_cm_connection(conn
);
2155 *cli
= conn
->samr_pipe
;
2156 *sam_handle
= conn
->sam_domain_handle
;
2157 SAFE_FREE(machine_password
);
2158 SAFE_FREE(machine_account
);
2162 NTSTATUS
cm_connect_lsa(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
2163 struct rpc_pipe_client
**cli
, struct policy_handle
*lsa_policy
)
2165 struct winbindd_cm_conn
*conn
;
2166 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2167 struct netlogon_creds_CredentialState
*p_creds
;
2169 result
= init_dc_connection(domain
);
2170 if (!NT_STATUS_IS_OK(result
))
2173 conn
= &domain
->conn
;
2175 if (conn
->lsa_pipe
!= NULL
) {
2179 if ((conn
->cli
->user_name
[0] == '\0') ||
2180 (conn
->cli
->domain
[0] == '\0') ||
2181 (conn
->cli
->password
== NULL
|| conn
->cli
->password
[0] == '\0')) {
2182 DEBUG(10, ("cm_connect_lsa: No no user available for "
2183 "domain %s, trying schannel\n", conn
->cli
->domain
));
2187 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2188 * authenticated LSA pipe with sign & seal. */
2189 result
= cli_rpc_pipe_open_spnego_ntlmssp
2190 (conn
->cli
, &ndr_table_lsarpc
.syntax_id
,
2191 PIPE_AUTH_LEVEL_PRIVACY
,
2192 conn
->cli
->domain
, conn
->cli
->user_name
, conn
->cli
->password
,
2195 if (!NT_STATUS_IS_OK(result
)) {
2196 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2197 "domain %s using NTLMSSP authenticated pipe: user "
2198 "%s\\%s. Error was %s. Trying schannel.\n",
2199 domain
->name
, conn
->cli
->domain
,
2200 conn
->cli
->user_name
, nt_errstr(result
)));
2204 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2205 "NTLMSSP authenticated pipe: user %s\\%s\n",
2206 domain
->name
, conn
->cli
->domain
, conn
->cli
->user_name
));
2208 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2209 SEC_FLAG_MAXIMUM_ALLOWED
,
2211 if (NT_STATUS_IS_OK(result
)) {
2215 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2218 TALLOC_FREE(conn
->lsa_pipe
);
2222 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2224 if (!cm_get_schannel_creds(domain
, &p_creds
)) {
2225 /* If this call fails - conn->cli can now be NULL ! */
2226 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2227 "for domain %s, trying anon\n", domain
->name
));
2230 result
= cli_rpc_pipe_open_schannel_with_key
2231 (conn
->cli
, &ndr_table_lsarpc
.syntax_id
,
2232 PIPE_AUTH_LEVEL_PRIVACY
,
2233 domain
->name
, &p_creds
, &conn
->lsa_pipe
);
2235 if (!NT_STATUS_IS_OK(result
)) {
2236 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2237 "domain %s using schannel. Error was %s\n",
2238 domain
->name
, nt_errstr(result
) ));
2241 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2242 "schannel.\n", domain
->name
));
2244 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2245 SEC_FLAG_MAXIMUM_ALLOWED
,
2247 if (NT_STATUS_IS_OK(result
)) {
2251 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2254 TALLOC_FREE(conn
->lsa_pipe
);
2258 result
= cli_rpc_pipe_open_noauth(conn
->cli
,
2259 &ndr_table_lsarpc
.syntax_id
,
2261 if (!NT_STATUS_IS_OK(result
)) {
2262 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
2266 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2267 SEC_FLAG_MAXIMUM_ALLOWED
,
2270 if (!NT_STATUS_IS_OK(result
)) {
2271 invalidate_cm_connection(conn
);
2275 *cli
= conn
->lsa_pipe
;
2276 *lsa_policy
= conn
->lsa_policy
;
2280 /****************************************************************************
2281 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2282 session key stored in conn->netlogon_pipe->dc->sess_key.
2283 ****************************************************************************/
2285 NTSTATUS
cm_connect_netlogon(struct winbindd_domain
*domain
,
2286 struct rpc_pipe_client
**cli
)
2288 struct winbindd_cm_conn
*conn
;
2291 uint32_t neg_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
2293 uint32 sec_chan_type
;
2294 const char *account_name
;
2295 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
2299 result
= init_dc_connection(domain
);
2300 if (!NT_STATUS_IS_OK(result
)) {
2304 conn
= &domain
->conn
;
2306 if (conn
->netlogon_pipe
!= NULL
) {
2307 *cli
= conn
->netlogon_pipe
;
2308 return NT_STATUS_OK
;
2311 result
= cli_rpc_pipe_open_noauth(conn
->cli
,
2312 &ndr_table_netlogon
.syntax_id
,
2314 if (!NT_STATUS_IS_OK(result
)) {
2318 if ((!IS_DC
) && (!domain
->primary
)) {
2319 /* Clear the schannel request bit and drop down */
2320 neg_flags
&= ~NETLOGON_NEG_SCHANNEL
;
2324 if (lp_client_schannel() != False
) {
2325 neg_flags
|= NETLOGON_NEG_SCHANNEL
;
2328 if (!get_trust_pw_hash(domain
->name
, mach_pwd
, &account_name
,
2331 TALLOC_FREE(netlogon_pipe
);
2332 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2335 result
= rpccli_netlogon_setup_creds(
2337 domain
->dcname
, /* server name. */
2338 domain
->name
, /* domain name */
2339 global_myname(), /* client name */
2340 account_name
, /* machine account */
2341 mach_pwd
, /* machine password */
2342 sec_chan_type
, /* from get_trust_pw */
2345 if (!NT_STATUS_IS_OK(result
)) {
2346 TALLOC_FREE(netlogon_pipe
);
2350 if ((lp_client_schannel() == True
) &&
2351 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2352 DEBUG(3, ("Server did not offer schannel\n"));
2353 TALLOC_FREE(netlogon_pipe
);
2354 return NT_STATUS_ACCESS_DENIED
;
2358 if ((lp_client_schannel() == False
) ||
2359 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2361 * NetSamLogonEx only works for schannel
2363 domain
->can_do_samlogon_ex
= False
;
2365 /* We're done - just keep the existing connection to NETLOGON
2367 conn
->netlogon_pipe
= netlogon_pipe
;
2368 *cli
= conn
->netlogon_pipe
;
2369 return NT_STATUS_OK
;
2372 /* Using the credentials from the first pipe, open a signed and sealed
2373 second netlogon pipe. The session key is stored in the schannel
2374 part of the new pipe auth struct.
2377 result
= cli_rpc_pipe_open_schannel_with_key(
2378 conn
->cli
, &ndr_table_netlogon
.syntax_id
,
2379 PIPE_AUTH_LEVEL_PRIVACY
, domain
->name
, &netlogon_pipe
->dc
,
2380 &conn
->netlogon_pipe
);
2382 /* We can now close the initial netlogon pipe. */
2383 TALLOC_FREE(netlogon_pipe
);
2385 if (!NT_STATUS_IS_OK(result
)) {
2386 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2387 "was %s\n", nt_errstr(result
)));
2389 /* make sure we return something besides OK */
2390 return !NT_STATUS_IS_OK(result
) ? result
: NT_STATUS_PIPE_NOT_AVAILABLE
;
2394 * Try NetSamLogonEx for AD domains
2396 domain
->can_do_samlogon_ex
= domain
->active_directory
;
2398 *cli
= conn
->netlogon_pipe
;
2399 return NT_STATUS_OK
;