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
65 #define DBGC_CLASS DBGC_WINBIND
72 extern struct winbindd_methods reconnect_methods
;
73 extern BOOL override_logfile
;
75 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
);
76 static void set_dc_type_and_flags( struct winbindd_domain
*domain
);
77 static BOOL
get_dcs(TALLOC_CTX
*mem_ctx
, const struct winbindd_domain
*domain
,
78 struct dc_name_ip
**dcs
, int *num_dcs
);
80 /****************************************************************
81 Child failed to find DC's. Reschedule check.
82 ****************************************************************/
84 static void msg_failed_to_go_online(struct messaging_context
*msg
,
87 struct server_id server_id
,
90 struct winbindd_domain
*domain
;
91 const char *domainname
= (const char *)data
->data
;
93 if (data
->data
== NULL
|| data
->length
== 0) {
97 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname
));
99 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
100 if (domain
->internal
) {
104 if (strequal(domain
->name
, domainname
)) {
105 if (domain
->online
) {
106 /* We're already online, ignore. */
107 DEBUG(5,("msg_fail_to_go_online: domain %s "
108 "already online.\n", domainname
));
112 /* Reschedule the online check. */
113 set_domain_offline(domain
);
119 /****************************************************************
120 Actually cause a reconnect from a message.
121 ****************************************************************/
123 static void msg_try_to_go_online(struct messaging_context
*msg
,
126 struct server_id server_id
,
129 struct winbindd_domain
*domain
;
130 const char *domainname
= (const char *)data
->data
;
132 if (data
->data
== NULL
|| data
->length
== 0) {
136 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname
));
138 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
139 if (domain
->internal
) {
143 if (strequal(domain
->name
, domainname
)) {
145 if (domain
->online
) {
146 /* We're already online, ignore. */
147 DEBUG(5,("msg_try_to_go_online: domain %s "
148 "already online.\n", domainname
));
152 /* This call takes care of setting the online
153 flag to true if we connected, or re-adding
154 the offline handler if false. Bypasses online
155 check so always does network calls. */
157 init_dc_connection_network(domain
);
163 /****************************************************************
164 Fork a child to try and contact a DC. Do this as contacting a
165 DC requires blocking lookups and we don't want to block our
167 ****************************************************************/
169 static BOOL
fork_child_dc_connect(struct winbindd_domain
*domain
)
171 struct dc_name_ip
*dcs
= NULL
;
173 TALLOC_CTX
*mem_ctx
= NULL
;
175 pid_t parent_pid
= sys_getpid();
180 child_pid
= sys_fork();
182 if (child_pid
== -1) {
183 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno
)));
187 if (child_pid
!= 0) {
189 messaging_register(winbind_messaging_context(), NULL
,
190 MSG_WINBIND_TRY_TO_GO_ONLINE
,
191 msg_try_to_go_online
);
192 messaging_register(winbind_messaging_context(), NULL
,
193 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
194 msg_failed_to_go_online
);
200 /* Leave messages blocked - we will never process one. */
202 /* tdb needs special fork handling */
203 if (tdb_reopen_all(1) == -1) {
204 DEBUG(0,("tdb_reopen_all failed.\n"));
208 close_conns_after_fork();
210 if (!override_logfile
) {
212 pstr_sprintf(logfile
, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE
);
213 lp_set_logfile(logfile
);
217 mem_ctx
= talloc_init("fork_child_dc_connect");
219 DEBUG(0,("talloc_init failed.\n"));
223 if ((!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
)) || (num_dcs
== 0)) {
224 /* Still offline ? Can't find DC's. */
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);
233 /* We got a DC. Send a message to our parent to get it to
234 try and do the same. */
236 messaging_send_buf(winbind_messaging_context(),
237 pid_to_procid(parent_pid
),
238 MSG_WINBIND_TRY_TO_GO_ONLINE
,
239 (uint8
*)domain
->name
,
240 strlen(domain
->name
)+1);
244 /****************************************************************
245 Handler triggered if we're offline to try and detect a DC.
246 ****************************************************************/
248 static void check_domain_online_handler(struct event_context
*ctx
,
249 struct timed_event
*te
,
250 const struct timeval
*now
,
253 struct winbindd_domain
*domain
=
254 (struct winbindd_domain
*)private_data
;
256 DEBUG(10,("check_domain_online_handler: called for domain "
257 "%s (online = %s)\n", domain
->name
,
258 domain
->online
? "True" : "False" ));
260 TALLOC_FREE(domain
->check_online_event
);
262 /* Are we still in "startup" mode ? */
264 if (domain
->startup
&& (now
->tv_sec
> domain
->startup_time
+ 30)) {
265 /* No longer in "startup" mode. */
266 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
268 domain
->startup
= False
;
271 /* We've been told to stay offline, so stay
274 if (get_global_winbindd_state_offline()) {
275 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
280 /* Fork a child to test if it can contact a DC.
281 If it can then send ourselves a message to
282 cause a reconnect. */
284 fork_child_dc_connect(domain
);
287 /****************************************************************
288 If we're still offline setup the timeout check.
289 ****************************************************************/
291 static void calc_new_online_timeout_check(struct winbindd_domain
*domain
)
293 int wbc
= lp_winbind_cache_time();
295 if (domain
->startup
) {
296 domain
->check_online_timeout
= 10;
297 } else if (domain
->check_online_timeout
< wbc
) {
298 domain
->check_online_timeout
= wbc
;
302 /****************************************************************
303 Set domain offline and also add handler to put us back online
305 ****************************************************************/
307 void set_domain_offline(struct winbindd_domain
*domain
)
309 DEBUG(10,("set_domain_offline: called for domain %s\n",
312 TALLOC_FREE(domain
->check_online_event
);
314 if (domain
->internal
) {
315 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
320 domain
->online
= False
;
322 /* Offline domains are always initialized. They're
323 re-initialized when they go back online. */
325 domain
->initialized
= True
;
327 /* We only add the timeout handler that checks and
328 allows us to go back online when we've not
329 been told to remain offline. */
331 if (get_global_winbindd_state_offline()) {
332 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
337 /* If we're in statup mode, check again in 10 seconds, not in
338 lp_winbind_cache_time() seconds (which is 5 mins by default). */
340 calc_new_online_timeout_check(domain
);
342 domain
->check_online_event
= event_add_timed(winbind_event_context(),
344 timeval_current_ofs(domain
->check_online_timeout
,0),
345 "check_domain_online_handler",
346 check_domain_online_handler
,
349 /* The above *has* to succeed for winbindd to work. */
350 if (!domain
->check_online_event
) {
351 smb_panic("set_domain_offline: failed to add online handler");
354 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
357 /* Send an offline message to the idmap child when our
358 primary domain goes offline */
360 if ( domain
->primary
) {
361 struct winbindd_child
*idmap
= idmap_child();
363 if ( idmap
->pid
!= 0 ) {
364 messaging_send_buf(winbind_messaging_context(),
365 pid_to_procid(idmap
->pid
),
367 (uint8
*)domain
->name
,
368 strlen(domain
->name
)+1);
375 /****************************************************************
376 Set domain online - if allowed.
377 ****************************************************************/
379 static void set_domain_online(struct winbindd_domain
*domain
)
383 DEBUG(10,("set_domain_online: called for domain %s\n",
386 if (domain
->internal
) {
387 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
392 if (get_global_winbindd_state_offline()) {
393 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
398 winbindd_set_locator_kdc_envs(domain
);
400 /* If we are waiting to get a krb5 ticket, trigger immediately. */
402 set_event_dispatch_time(winbind_event_context(),
403 "krb5_ticket_gain_handler", now
);
405 /* Ok, we're out of any startup mode now... */
406 domain
->startup
= False
;
408 if (domain
->online
== False
) {
409 /* We were offline - now we're online. We default to
410 using the MS-RPC backend if we started offline,
411 and if we're going online for the first time we
412 should really re-initialize the backends and the
413 checks to see if we're talking to an AD or NT domain.
416 domain
->initialized
= False
;
418 /* 'reconnect_methods' is the MS-RPC backend. */
419 if (domain
->backend
== &reconnect_methods
) {
420 domain
->backend
= NULL
;
424 /* Ensure we have no online timeout checks. */
425 domain
->check_online_timeout
= 0;
426 TALLOC_FREE(domain
->check_online_event
);
428 /* Ensure we ignore any pending child messages. */
429 messaging_deregister(winbind_messaging_context(),
430 MSG_WINBIND_TRY_TO_GO_ONLINE
, NULL
);
431 messaging_deregister(winbind_messaging_context(),
432 MSG_WINBIND_FAILED_TO_GO_ONLINE
, NULL
);
434 domain
->online
= True
;
436 /* Send an online message to the idmap child when our
437 primary domain comes online */
439 if ( domain
->primary
) {
440 struct winbindd_child
*idmap
= idmap_child();
442 if ( idmap
->pid
!= 0 ) {
443 messaging_send_buf(winbind_messaging_context(),
444 pid_to_procid(idmap
->pid
),
446 (uint8
*)domain
->name
,
447 strlen(domain
->name
)+1);
454 /****************************************************************
455 Requested to set a domain online.
456 ****************************************************************/
458 void set_domain_online_request(struct winbindd_domain
*domain
)
462 DEBUG(10,("set_domain_online_request: called for domain %s\n",
465 if (get_global_winbindd_state_offline()) {
466 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
471 /* We've been told it's safe to go online and
472 try and connect to a DC. But I don't believe it
473 because network manager seems to lie.
474 Wait at least 5 seconds. Heuristics suck... */
476 if (!domain
->check_online_event
) {
477 /* If we've come from being globally offline we
478 don't have a check online event handler set.
479 We need to add one now we're trying to go
482 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
485 domain
->check_online_event
= event_add_timed(winbind_event_context(),
487 timeval_current_ofs(5, 0),
488 "check_domain_online_handler",
489 check_domain_online_handler
,
492 /* The above *has* to succeed for winbindd to work. */
493 if (!domain
->check_online_event
) {
494 smb_panic("set_domain_online_request: failed to add online handler");
500 /* Go into "startup" mode again. */
501 domain
->startup_time
= tev
.tv_sec
;
502 domain
->startup
= True
;
506 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev
);
509 /****************************************************************
510 Add -ve connection cache entries for domain and realm.
511 ****************************************************************/
513 void winbind_add_failed_connection_entry(const struct winbindd_domain
*domain
,
517 add_failed_connection_entry(domain
->name
, server
, result
);
518 /* If this was the saf name for the last thing we talked to,
520 saf_delete(domain
->name
);
521 if (*domain
->alt_name
) {
522 add_failed_connection_entry(domain
->alt_name
, server
, result
);
523 saf_delete(domain
->alt_name
);
525 winbindd_unset_locator_kdc_env(domain
);
528 /* Choose between anonymous or authenticated connections. We need to use
529 an authenticated connection if DCs have the RestrictAnonymous registry
530 entry set > 0, or the "Additional restrictions for anonymous
531 connections" set in the win2k Local Security Policy.
533 Caller to free() result in domain, username, password
536 static void cm_get_ipc_userpass(char **username
, char **domain
, char **password
)
538 *username
= (char *)secrets_fetch(SECRETS_AUTH_USER
, NULL
);
539 *domain
= (char *)secrets_fetch(SECRETS_AUTH_DOMAIN
, NULL
);
540 *password
= (char *)secrets_fetch(SECRETS_AUTH_PASSWORD
, NULL
);
542 if (*username
&& **username
) {
544 if (!*domain
|| !**domain
)
545 *domain
= smb_xstrdup(lp_workgroup());
547 if (!*password
|| !**password
)
548 *password
= smb_xstrdup("");
550 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
551 *domain
, *username
));
554 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
555 *username
= smb_xstrdup("");
556 *domain
= smb_xstrdup("");
557 *password
= smb_xstrdup("");
561 static BOOL
get_dc_name_via_netlogon(const struct winbindd_domain
*domain
,
562 fstring dcname
, struct in_addr
*dc_ip
)
564 struct winbindd_domain
*our_domain
= NULL
;
565 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
569 unsigned int orig_timeout
;
573 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
580 if (domain
->primary
) {
584 our_domain
= find_our_domain();
586 if ((mem_ctx
= talloc_init("get_dc_name_via_netlogon")) == NULL
) {
590 result
= cm_connect_netlogon(our_domain
, &netlogon_pipe
);
591 if (!NT_STATUS_IS_OK(result
)) {
592 talloc_destroy(mem_ctx
);
596 /* This call can take a long time - allow the server to time out.
597 35 seconds should do it. */
599 orig_timeout
= cli_set_timeout(netlogon_pipe
->cli
, 35000);
601 werr
= rpccli_netlogon_getanydcname(netlogon_pipe
, mem_ctx
, our_domain
->dcname
,
604 /* And restore our original timeout. */
605 cli_set_timeout(netlogon_pipe
->cli
, orig_timeout
);
607 talloc_destroy(mem_ctx
);
609 if (!W_ERROR_IS_OK(werr
)) {
610 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
615 /* cli_netlogon_getanydcname gives us a name with \\ */
626 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname
));
628 if (!resolve_name(dcname
, dc_ip
, 0x20)) {
635 /************************************************************************
636 Given a fd with a just-connected TCP connection to a DC, open a connection
638 ************************************************************************/
640 static NTSTATUS
cm_prepare_connection(const struct winbindd_domain
*domain
,
642 const char *controller
,
643 struct cli_state
**cli
,
646 char *machine_password
, *machine_krb5_principal
, *machine_account
;
647 char *ipc_username
, *ipc_domain
, *ipc_password
;
651 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
653 struct sockaddr peeraddr
;
654 socklen_t peeraddr_len
;
656 struct sockaddr_in
*peeraddr_in
= (struct sockaddr_in
*)&peeraddr
;
658 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
659 controller
, domain
->name
));
661 machine_password
= secrets_fetch_machine_password(lp_workgroup(), NULL
,
664 if (asprintf(&machine_account
, "%s$", global_myname()) == -1) {
665 SAFE_FREE(machine_password
);
666 return NT_STATUS_NO_MEMORY
;
669 if (asprintf(&machine_krb5_principal
, "%s$@%s", global_myname(),
671 SAFE_FREE(machine_account
);
672 SAFE_FREE(machine_password
);
673 return NT_STATUS_NO_MEMORY
;
676 cm_get_ipc_userpass(&ipc_username
, &ipc_domain
, &ipc_password
);
680 got_mutex
= secrets_named_mutex(controller
,
681 WINBIND_SERVER_MUTEX_WAIT_TIME
);
684 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
686 result
= NT_STATUS_POSSIBLE_DEADLOCK
;
690 if ((*cli
= cli_initialise()) == NULL
) {
691 DEBUG(1, ("Could not cli_initialize\n"));
692 result
= NT_STATUS_NO_MEMORY
;
696 (*cli
)->timeout
= 10000; /* 10 seconds */
698 fstrcpy((*cli
)->desthost
, controller
);
699 (*cli
)->use_kerberos
= True
;
701 peeraddr_len
= sizeof(peeraddr
);
703 if ((getpeername((*cli
)->fd
, &peeraddr
, &peeraddr_len
) != 0) ||
704 (peeraddr_len
!= sizeof(struct sockaddr_in
)) ||
705 (peeraddr_in
->sin_family
!= PF_INET
))
707 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno
)));
708 result
= NT_STATUS_UNSUCCESSFUL
;
712 if (ntohs(peeraddr_in
->sin_port
) == 139) {
713 struct nmb_name calling
;
714 struct nmb_name called
;
716 make_nmb_name(&calling
, global_myname(), 0x0);
717 make_nmb_name(&called
, "*SMBSERVER", 0x20);
719 if (!cli_session_request(*cli
, &calling
, &called
)) {
720 DEBUG(8, ("cli_session_request failed for %s\n",
722 result
= NT_STATUS_UNSUCCESSFUL
;
727 cli_setup_signing_state(*cli
, Undefined
);
729 if (!cli_negprot(*cli
)) {
730 DEBUG(1, ("cli_negprot failed\n"));
731 result
= NT_STATUS_UNSUCCESSFUL
;
735 if ((*cli
)->protocol
>= PROTOCOL_NT1
&& (*cli
)->capabilities
& CAP_EXTENDED_SECURITY
) {
736 ADS_STATUS ads_status
;
738 if (lp_security() == SEC_ADS
) {
740 /* Try a krb5 session */
742 (*cli
)->use_kerberos
= True
;
743 DEBUG(5, ("connecting to %s from %s with kerberos principal "
744 "[%s]\n", controller
, global_myname(),
745 machine_krb5_principal
));
747 winbindd_set_locator_kdc_envs(domain
);
749 ads_status
= cli_session_setup_spnego(*cli
,
750 machine_krb5_principal
,
754 if (!ADS_ERR_OK(ads_status
)) {
755 DEBUG(4,("failed kerberos session setup with %s\n",
756 ads_errstr(ads_status
)));
759 result
= ads_ntstatus(ads_status
);
760 if (NT_STATUS_IS_OK(result
)) {
761 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
762 cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
763 goto session_setup_done
;
767 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
768 (*cli
)->use_kerberos
= False
;
770 DEBUG(5, ("connecting to %s from %s with username "
771 "[%s]\\[%s]\n", controller
, global_myname(),
772 lp_workgroup(), machine_account
));
774 ads_status
= cli_session_setup_spnego(*cli
,
778 if (!ADS_ERR_OK(ads_status
)) {
779 DEBUG(4, ("authenticated session setup failed with %s\n",
780 ads_errstr(ads_status
)));
783 result
= ads_ntstatus(ads_status
);
784 if (NT_STATUS_IS_OK(result
)) {
785 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
786 cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
787 goto session_setup_done
;
791 /* Fall back to non-kerberos session setup */
793 (*cli
)->use_kerberos
= False
;
795 if ((((*cli
)->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) != 0) &&
796 (strlen(ipc_username
) > 0)) {
798 /* Only try authenticated if we have a username */
800 DEBUG(5, ("connecting to %s from %s with username "
801 "[%s]\\[%s]\n", controller
, global_myname(),
802 ipc_domain
, ipc_username
));
804 if (NT_STATUS_IS_OK(cli_session_setup(
806 ipc_password
, strlen(ipc_password
)+1,
807 ipc_password
, strlen(ipc_password
)+1,
809 /* Successful logon with given username. */
810 cli_init_creds(*cli
, ipc_username
, ipc_domain
, ipc_password
);
811 goto session_setup_done
;
813 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
814 ipc_domain
, ipc_username
));
818 /* Fall back to anonymous connection, this might fail later */
820 if (NT_STATUS_IS_OK(cli_session_setup(*cli
, "", NULL
, 0,
822 DEBUG(5, ("Connected anonymously\n"));
823 cli_init_creds(*cli
, "", "", "");
824 goto session_setup_done
;
827 result
= cli_nt_error(*cli
);
829 if (NT_STATUS_IS_OK(result
))
830 result
= NT_STATUS_UNSUCCESSFUL
;
832 /* We can't session setup */
838 /* cache the server name for later connections */
840 saf_store( domain
->name
, (*cli
)->desthost
);
841 if (domain
->alt_name
&& (*cli
)->use_kerberos
) {
842 saf_store( domain
->alt_name
, (*cli
)->desthost
);
845 winbindd_set_locator_kdc_envs(domain
);
847 if (!cli_send_tconX(*cli
, "IPC$", "IPC", "", 0)) {
849 result
= cli_nt_error(*cli
);
851 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result
)));
853 if (NT_STATUS_IS_OK(result
))
854 result
= NT_STATUS_UNSUCCESSFUL
;
859 secrets_named_mutex_release(controller
);
863 /* set the domain if empty; needed for schannel connections */
864 if ( !*(*cli
)->domain
) {
865 fstrcpy( (*cli
)->domain
, domain
->name
);
868 result
= NT_STATUS_OK
;
872 secrets_named_mutex_release(controller
);
875 SAFE_FREE(machine_account
);
876 SAFE_FREE(machine_password
);
877 SAFE_FREE(machine_krb5_principal
);
878 SAFE_FREE(ipc_username
);
879 SAFE_FREE(ipc_domain
);
880 SAFE_FREE(ipc_password
);
882 if (!NT_STATUS_IS_OK(result
)) {
883 winbind_add_failed_connection_entry(domain
, controller
, result
);
884 if ((*cli
) != NULL
) {
893 static BOOL
add_one_dc_unique(TALLOC_CTX
*mem_ctx
, const char *domain_name
,
894 const char *dcname
, struct in_addr ip
,
895 struct dc_name_ip
**dcs
, int *num
)
897 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name
, dcname
))) {
898 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname
));
902 *dcs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *dcs
, struct dc_name_ip
, (*num
)+1);
907 fstrcpy((*dcs
)[*num
].name
, dcname
);
908 (*dcs
)[*num
].ip
= ip
;
913 static BOOL
add_sockaddr_to_array(TALLOC_CTX
*mem_ctx
,
914 struct in_addr ip
, uint16 port
,
915 struct sockaddr_in
**addrs
, int *num
)
917 *addrs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *addrs
, struct sockaddr_in
, (*num
)+1);
919 if (*addrs
== NULL
) {
924 (*addrs
)[*num
].sin_family
= PF_INET
;
925 putip((char *)&((*addrs
)[*num
].sin_addr
), (char *)&ip
);
926 (*addrs
)[*num
].sin_port
= htons(port
);
932 static void mailslot_name(struct in_addr dc_ip
, fstring name
)
934 fstr_sprintf(name
, "\\MAILSLOT\\NET\\GETDC%X", dc_ip
.s_addr
);
937 static BOOL
send_getdc_request(struct in_addr dc_ip
,
938 const char *domain_name
,
943 fstring my_acct_name
;
946 mailslot_name(dc_ip
, my_mailslot
);
948 memset(outbuf
, '\0', sizeof(outbuf
));
952 SCVAL(p
, 0, SAMLOGON
);
955 SCVAL(p
, 0, 0); /* Count pointer ... */
958 SIVAL(p
, 0, 0); /* The sender's token ... */
961 p
+= dos_PutUniCode(p
, global_myname(), sizeof(pstring
), True
);
962 fstr_sprintf(my_acct_name
, "%s$", global_myname());
963 p
+= dos_PutUniCode(p
, my_acct_name
, sizeof(pstring
), True
);
965 memcpy(p
, my_mailslot
, strlen(my_mailslot
)+1);
966 p
+= strlen(my_mailslot
)+1;
971 SIVAL(p
, 0, sid_size(sid
));
974 p
= ALIGN4(p
, outbuf
);
976 sid_linearize(p
, sid_size(sid
), sid
);
984 return cli_send_mailslot(winbind_messaging_context(),
985 False
, "\\MAILSLOT\\NET\\NTLOGON", 0,
986 outbuf
, PTR_DIFF(p
, outbuf
),
987 global_myname(), 0, domain_name
, 0x1c,
991 static BOOL
receive_getdc_response(struct in_addr dc_ip
,
992 const char *domain_name
,
995 struct packet_struct
*packet
;
998 fstring dcname
, user
, domain
;
1001 mailslot_name(dc_ip
, my_mailslot
);
1003 packet
= receive_unexpected(DGRAM_PACKET
, 0, my_mailslot
);
1005 if (packet
== NULL
) {
1006 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot
));
1010 DEBUG(5, ("Received packet for %s\n", my_mailslot
));
1012 buf
= packet
->packet
.dgram
.data
;
1013 len
= packet
->packet
.dgram
.datasize
;
1016 /* 70 is a completely arbitrary value to make sure
1017 the SVAL below does not read uninitialized memory */
1018 DEBUG(3, ("GetDC got short response\n"));
1022 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1023 p
= buf
+SVAL(buf
, smb_vwv10
);
1025 if (CVAL(p
,0) != SAMLOGON_R
) {
1026 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p
, 0)));
1031 pull_ucs2(buf
, dcname
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
1032 STR_TERMINATE
|STR_NOALIGN
);
1033 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
1034 pull_ucs2(buf
, user
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
1035 STR_TERMINATE
|STR_NOALIGN
);
1036 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
1037 pull_ucs2(buf
, domain
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
1038 STR_TERMINATE
|STR_NOALIGN
);
1039 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
1041 if (!strequal(domain
, domain_name
)) {
1042 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1043 domain_name
, domain
));
1048 if (*p
== '\\') p
+= 1;
1049 if (*p
== '\\') p
+= 1;
1051 fstrcpy(dc_name
, p
);
1053 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1059 /*******************************************************************
1060 convert an ip to a name
1061 *******************************************************************/
1063 static BOOL
dcip_to_name(const struct winbindd_domain
*domain
, struct in_addr ip
, fstring name
)
1065 struct ip_service ip_list
;
1071 /* For active directory servers, try to get the ldap server name.
1072 None of these failures should be considered critical for now */
1074 if (lp_security() == SEC_ADS
) {
1077 ads
= ads_init(domain
->alt_name
, domain
->name
, NULL
);
1078 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
1080 if (ads_try_connect( ads
, inet_ntoa(ip
) ) ) {
1081 /* We got a cldap packet. */
1082 fstrcpy(name
, ads
->config
.ldap_server_name
);
1083 namecache_store(name
, 0x20, 1, &ip_list
);
1085 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads
->config
.flags
));
1087 if (domain
->primary
&& (ads
->config
.flags
& ADS_KDC
)) {
1088 if (ads_closest_dc(ads
)) {
1089 char *sitename
= sitename_fetch(ads
->config
.realm
);
1091 /* We're going to use this KDC for this realm/domain.
1092 If we are using sites, then force the krb5 libs
1095 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1100 SAFE_FREE(sitename
);
1102 /* use an off site KDC */
1103 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1108 winbindd_set_locator_kdc_envs(domain
);
1110 /* Ensure we contact this DC also. */
1111 saf_store( domain
->name
, name
);
1112 saf_store( domain
->alt_name
, name
);
1115 ads_destroy( &ads
);
1119 ads_destroy( &ads
);
1123 /* try GETDC requests next */
1125 if (send_getdc_request(ip
, domain
->name
, &domain
->sid
)) {
1128 for (i
=0; i
<5; i
++) {
1129 if (receive_getdc_response(ip
, domain
->name
, name
)) {
1130 namecache_store(name
, 0x20, 1, &ip_list
);
1137 /* try node status request */
1139 if ( name_status_find(domain
->name
, 0x1c, 0x20, ip
, name
) ) {
1140 namecache_store(name
, 0x20, 1, &ip_list
);
1146 /*******************************************************************
1147 Retreive a list of IP address for domain controllers. Fill in
1148 the dcs[] with results.
1149 *******************************************************************/
1151 static BOOL
get_dcs(TALLOC_CTX
*mem_ctx
, const struct winbindd_domain
*domain
,
1152 struct dc_name_ip
**dcs
, int *num_dcs
)
1156 struct ip_service
*ip_list
= NULL
;
1157 int iplist_size
= 0;
1160 enum security_types sec
= (enum security_types
)lp_security();
1162 is_our_domain
= strequal(domain
->name
, lp_workgroup());
1165 && get_dc_name_via_netlogon(domain
, dcname
, &ip
)
1166 && add_one_dc_unique(mem_ctx
, domain
->name
, dcname
, ip
, dcs
, num_dcs
) )
1168 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1169 dcname
, inet_ntoa(ip
)));
1173 if (sec
== SEC_ADS
) {
1174 char *sitename
= NULL
;
1176 /* We need to make sure we know the local site before
1177 doing any DNS queries, as this will restrict the
1178 get_sorted_dc_list() call below to only fetching
1179 DNS records for the correct site. */
1181 /* Find any DC to get the site record.
1182 We deliberately don't care about the
1185 get_dc_name(domain
->name
, domain
->alt_name
, dcname
, &ip
);
1187 sitename
= sitename_fetch(domain
->alt_name
);
1190 /* Do the site-specific AD dns lookup first. */
1191 get_sorted_dc_list(domain
->alt_name
, sitename
, &ip_list
, &iplist_size
, True
);
1193 for ( i
=0; i
<iplist_size
; i
++ ) {
1194 add_one_dc_unique(mem_ctx
, domain
->name
, inet_ntoa(ip_list
[i
].ip
),
1195 ip_list
[i
].ip
, dcs
, num_dcs
);
1199 SAFE_FREE(sitename
);
1203 /* Now we add DCs from the main AD dns lookup. */
1204 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
, &iplist_size
, True
);
1206 for ( i
=0; i
<iplist_size
; i
++ ) {
1207 add_one_dc_unique(mem_ctx
, domain
->name
, inet_ntoa(ip_list
[i
].ip
),
1208 ip_list
[i
].ip
, dcs
, num_dcs
);
1212 /* try standard netbios queries if no ADS */
1214 if (iplist_size
==0) {
1215 get_sorted_dc_list(domain
->name
, NULL
, &ip_list
, &iplist_size
, False
);
1218 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1220 /* now add to the dc array. We'll wait until the last minute
1221 to look up the name of the DC. But we fill in the char* for
1222 the ip now in to make the failed connection cache work */
1224 for ( i
=0; i
<iplist_size
; i
++ ) {
1225 add_one_dc_unique(mem_ctx
, domain
->name
, inet_ntoa(ip_list
[i
].ip
),
1226 ip_list
[i
].ip
, dcs
, num_dcs
);
1229 SAFE_FREE( ip_list
);
1234 static BOOL
find_new_dc(TALLOC_CTX
*mem_ctx
,
1235 const struct winbindd_domain
*domain
,
1236 fstring dcname
, struct sockaddr_in
*addr
, int *fd
)
1238 struct dc_name_ip
*dcs
= NULL
;
1241 const char **dcnames
= NULL
;
1242 int num_dcnames
= 0;
1244 struct sockaddr_in
*addrs
= NULL
;
1250 if (!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
) || (num_dcs
== 0))
1253 for (i
=0; i
<num_dcs
; i
++) {
1255 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1256 &dcnames
, &num_dcnames
)) {
1259 if (!add_sockaddr_to_array(mem_ctx
, dcs
[i
].ip
, 445,
1260 &addrs
, &num_addrs
)) {
1264 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1265 &dcnames
, &num_dcnames
)) {
1268 if (!add_sockaddr_to_array(mem_ctx
, dcs
[i
].ip
, 139,
1269 &addrs
, &num_addrs
)) {
1274 if ((num_dcnames
== 0) || (num_dcnames
!= num_addrs
))
1277 if ((addrs
== NULL
) || (dcnames
== NULL
))
1280 /* 5 second timeout. */
1281 if ( !open_any_socket_out(addrs
, num_addrs
, 5000, &fd_index
, fd
) )
1283 for (i
=0; i
<num_dcs
; i
++) {
1284 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1285 "domain %s address %s. Error was %s\n",
1286 domain
->name
, inet_ntoa(dcs
[i
].ip
), strerror(errno
) ));
1287 winbind_add_failed_connection_entry(domain
,
1288 dcs
[i
].name
, NT_STATUS_UNSUCCESSFUL
);
1293 *addr
= addrs
[fd_index
];
1295 if (*dcnames
[fd_index
] != '\0' && !is_ipaddress(dcnames
[fd_index
])) {
1296 /* Ok, we've got a name for the DC */
1297 fstrcpy(dcname
, dcnames
[fd_index
]);
1301 /* Try to figure out the name */
1302 if (dcip_to_name( domain
, addr
->sin_addr
, dcname
)) {
1306 /* We can not continue without the DC's name */
1307 winbind_add_failed_connection_entry(domain
, dcs
[fd_index
].name
,
1308 NT_STATUS_UNSUCCESSFUL
);
1312 static NTSTATUS
cm_open_connection(struct winbindd_domain
*domain
,
1313 struct winbindd_cm_conn
*new_conn
)
1315 TALLOC_CTX
*mem_ctx
;
1317 char *saf_servername
= saf_fetch( domain
->name
);
1320 if ((mem_ctx
= talloc_init("cm_open_connection")) == NULL
) {
1321 SAFE_FREE(saf_servername
);
1322 set_domain_offline(domain
);
1323 return NT_STATUS_NO_MEMORY
;
1326 /* we have to check the server affinity cache here since
1327 later we selecte a DC based on response time and not preference */
1329 /* Check the negative connection cache
1330 before talking to it. It going down may have
1331 triggered the reconnection. */
1333 if ( saf_servername
&& NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, saf_servername
))) {
1335 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1336 saf_servername
, domain
->name
));
1338 /* convert an ip address to a name */
1339 if ( is_ipaddress( saf_servername
) ) {
1343 ip
= *interpret_addr2( saf_servername
);
1344 if (dcip_to_name( domain
, ip
, saf_name
)) {
1345 fstrcpy( domain
->dcname
, saf_name
);
1347 winbind_add_failed_connection_entry(
1348 domain
, saf_servername
,
1349 NT_STATUS_UNSUCCESSFUL
);
1352 fstrcpy( domain
->dcname
, saf_servername
);
1355 SAFE_FREE( saf_servername
);
1358 for (retries
= 0; retries
< 3; retries
++) {
1363 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1365 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1366 domain
->dcname
, domain
->name
));
1369 && NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, domain
->dcname
))
1370 && (resolve_name(domain
->dcname
, &domain
->dcaddr
.sin_addr
, 0x20)))
1372 struct sockaddr_in
*addrs
= NULL
;
1376 if (!add_sockaddr_to_array(mem_ctx
, domain
->dcaddr
.sin_addr
, 445, &addrs
, &num_addrs
)) {
1377 set_domain_offline(domain
);
1378 talloc_destroy(mem_ctx
);
1379 return NT_STATUS_NO_MEMORY
;
1381 if (!add_sockaddr_to_array(mem_ctx
, domain
->dcaddr
.sin_addr
, 139, &addrs
, &num_addrs
)) {
1382 set_domain_offline(domain
);
1383 talloc_destroy(mem_ctx
);
1384 return NT_STATUS_NO_MEMORY
;
1387 /* 5 second timeout. */
1388 if (!open_any_socket_out(addrs
, num_addrs
, 5000, &dummy
, &fd
)) {
1394 && !find_new_dc(mem_ctx
, domain
, domain
->dcname
, &domain
->dcaddr
, &fd
))
1396 /* This is the one place where we will
1397 set the global winbindd offline state
1398 to true, if a "WINBINDD_OFFLINE" entry
1399 is found in the winbindd cache. */
1400 set_global_winbindd_state_offline();
1404 new_conn
->cli
= NULL
;
1406 result
= cm_prepare_connection(domain
, fd
, domain
->dcname
,
1407 &new_conn
->cli
, &retry
);
1413 if (NT_STATUS_IS_OK(result
)) {
1415 winbindd_set_locator_kdc_envs(domain
);
1417 if (domain
->online
== False
) {
1418 /* We're changing state from offline to online. */
1419 set_global_winbindd_state_online();
1421 set_domain_online(domain
);
1423 /* Ensure we setup the retry handler. */
1424 set_domain_offline(domain
);
1427 talloc_destroy(mem_ctx
);
1431 /* Close down all open pipes on a connection. */
1433 void invalidate_cm_connection(struct winbindd_cm_conn
*conn
)
1435 /* We're closing down a possibly dead
1436 connection. Don't have impossibly long (10s) timeouts. */
1439 cli_set_timeout(conn
->cli
, 1000); /* 1 second. */
1442 if (conn
->samr_pipe
!= NULL
) {
1443 if (!cli_rpc_pipe_close(conn
->samr_pipe
)) {
1444 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1446 cli_set_timeout(conn
->cli
, 500);
1449 conn
->samr_pipe
= NULL
;
1452 if (conn
->lsa_pipe
!= NULL
) {
1453 if (!cli_rpc_pipe_close(conn
->lsa_pipe
)) {
1454 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1456 cli_set_timeout(conn
->cli
, 500);
1459 conn
->lsa_pipe
= NULL
;
1462 if (conn
->netlogon_pipe
!= NULL
) {
1463 if (!cli_rpc_pipe_close(conn
->netlogon_pipe
)) {
1464 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1466 cli_set_timeout(conn
->cli
, 500);
1469 conn
->netlogon_pipe
= NULL
;
1473 cli_shutdown(conn
->cli
);
1479 void close_conns_after_fork(void)
1481 struct winbindd_domain
*domain
;
1483 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
1484 if (domain
->conn
.cli
== NULL
)
1487 if (domain
->conn
.cli
->fd
== -1)
1490 close(domain
->conn
.cli
->fd
);
1491 domain
->conn
.cli
->fd
= -1;
1495 static BOOL
connection_ok(struct winbindd_domain
*domain
)
1497 if (domain
->conn
.cli
== NULL
) {
1498 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1499 "cli!\n", domain
->dcname
, domain
->name
));
1503 if (!domain
->conn
.cli
->initialised
) {
1504 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1505 "initialised!\n", domain
->dcname
, domain
->name
));
1509 if (domain
->conn
.cli
->fd
== -1) {
1510 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1511 "never started (fd == -1)\n",
1512 domain
->dcname
, domain
->name
));
1516 if (domain
->online
== False
) {
1517 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain
->name
));
1524 /* Initialize a new connection up to the RPC BIND.
1525 Bypass online status check so always does network calls. */
1527 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
)
1531 /* Internal connections never use the network. */
1532 if (domain
->internal
) {
1533 domain
->initialized
= True
;
1534 return NT_STATUS_OK
;
1537 if (connection_ok(domain
)) {
1538 if (!domain
->initialized
) {
1539 set_dc_type_and_flags(domain
);
1541 return NT_STATUS_OK
;
1544 invalidate_cm_connection(&domain
->conn
);
1546 result
= cm_open_connection(domain
, &domain
->conn
);
1548 if (NT_STATUS_IS_OK(result
) && !domain
->initialized
) {
1549 set_dc_type_and_flags(domain
);
1555 NTSTATUS
init_dc_connection(struct winbindd_domain
*domain
)
1557 if (domain
->initialized
&& !domain
->online
) {
1558 /* We check for online status elsewhere. */
1559 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1562 return init_dc_connection_network(domain
);
1565 /******************************************************************************
1566 Set the trust flags (direction and forest location) for a domain
1567 ******************************************************************************/
1569 static BOOL
set_dc_type_and_flags_trustinfo( struct winbindd_domain
*domain
)
1571 struct winbindd_domain
*our_domain
;
1572 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1573 struct ds_domain_trust
*domains
= NULL
;
1576 uint32 flags
= (DS_DOMAIN_IN_FOREST
|
1577 DS_DOMAIN_DIRECT_OUTBOUND
|
1578 DS_DOMAIN_DIRECT_INBOUND
);
1579 struct rpc_pipe_client
*cli
;
1580 TALLOC_CTX
*mem_ctx
= NULL
;
1582 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain
->name
));
1584 /* Our primary domain doesn't need to worry about trust flags.
1585 Force it to go through the network setup */
1586 if ( domain
->primary
) {
1590 our_domain
= find_our_domain();
1592 if ( !connection_ok(our_domain
) ) {
1593 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1597 /* This won't work unless our domain is AD */
1599 if ( !our_domain
->active_directory
) {
1603 /* Use DsEnumerateDomainTrusts to get us the trust direction
1606 result
= cm_connect_netlogon(our_domain
, &cli
);
1608 if (!NT_STATUS_IS_OK(result
)) {
1609 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1610 "a connection to %s for PIPE_NETLOGON (%s)\n",
1611 domain
->name
, nt_errstr(result
)));
1615 if ( (mem_ctx
= talloc_init("set_dc_type_and_flags_trustinfo")) == NULL
) {
1616 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1620 result
= rpccli_ds_enum_domain_trusts(cli
, mem_ctx
,
1623 (unsigned int *)&count
);
1625 /* Now find the domain name and get the flags */
1627 for ( i
=0; i
<count
; i
++ ) {
1628 if ( strequal( domain
->name
, domains
[i
].netbios_domain
) ) {
1629 domain
->domain_flags
= domains
[i
].flags
;
1630 domain
->domain_type
= domains
[i
].trust_type
;
1631 domain
->domain_trust_attribs
= domains
[i
].trust_attributes
;
1633 if ( domain
->domain_type
== DS_DOMAIN_TRUST_TYPE_UPLEVEL
)
1634 domain
->active_directory
= True
;
1636 /* This flag is only set if the domain is *our*
1637 primary domain and the primary domain is in
1640 domain
->native_mode
= (domain
->domain_flags
& DS_DOMAIN_NATIVE_MODE
);
1642 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1643 "native mode.\n", domain
->name
,
1644 domain
->native_mode
? "" : "NOT "));
1646 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1647 "running active directory.\n", domain
->name
,
1648 domain
->active_directory
? "" : "NOT "));
1651 domain
->initialized
= True
;
1653 if ( !winbindd_can_contact_domain( domain
) )
1654 domain
->internal
= True
;
1660 talloc_destroy( mem_ctx
);
1662 return domain
->initialized
;
1665 /******************************************************************************
1666 We can 'sense' certain things about the DC by it's replies to certain
1669 This tells us if this particular remote server is Active Directory, and if it
1671 ******************************************************************************/
1673 static void set_dc_type_and_flags_connect( struct winbindd_domain
*domain
)
1677 TALLOC_CTX
*mem_ctx
= NULL
;
1678 struct rpc_pipe_client
*cli
;
1681 char *domain_name
= NULL
;
1682 char *dns_name
= NULL
;
1683 char *forest_name
= NULL
;
1684 DOM_SID
*dom_sid
= NULL
;
1688 if (!connection_ok(domain
)) {
1692 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain
->name
));
1694 cli
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
, PI_LSARPC_DS
,
1698 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1699 "PI_LSARPC_DS on domain %s: (%s)\n",
1700 domain
->name
, nt_errstr(result
)));
1702 /* if this is just a non-AD domain we need to continue
1703 * identifying so that we can in the end return with
1704 * domain->initialized = True - gd */
1709 result
= rpccli_ds_getprimarydominfo(cli
, cli
->cli
->mem_ctx
,
1710 DsRolePrimaryDomainInfoBasic
,
1712 cli_rpc_pipe_close(cli
);
1714 if (!NT_STATUS_IS_OK(result
)) {
1715 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1716 "on domain %s failed: (%s)\n",
1717 domain
->name
, nt_errstr(result
)));
1719 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1720 * every opcode on the LSARPC_DS pipe, continue with
1721 * no_lsarpc_ds mode here as well to get domain->initialized
1724 if (NT_STATUS_V(result
) == DCERPC_FAULT_OP_RNG_ERROR
) {
1731 if ((ctr
.basic
->flags
& DSROLE_PRIMARY_DS_RUNNING
) &&
1732 !(ctr
.basic
->flags
& DSROLE_PRIMARY_DS_MIXED_MODE
)) {
1733 domain
->native_mode
= True
;
1735 domain
->native_mode
= False
;
1739 cli
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
, PI_LSARPC
, &result
);
1742 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1743 "PI_LSARPC on domain %s: (%s)\n",
1744 domain
->name
, nt_errstr(result
)));
1745 cli_rpc_pipe_close(cli
);
1749 mem_ctx
= talloc_init("set_dc_type_and_flags on domain %s\n",
1752 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1753 cli_rpc_pipe_close(cli
);
1757 result
= rpccli_lsa_open_policy2(cli
, mem_ctx
, True
,
1758 SEC_RIGHTS_MAXIMUM_ALLOWED
, &pol
);
1760 if (NT_STATUS_IS_OK(result
)) {
1761 /* This particular query is exactly what Win2k clients use
1762 to determine that the DC is active directory */
1763 result
= rpccli_lsa_query_info_policy2(cli
, mem_ctx
, &pol
,
1765 &dns_name
, &forest_name
,
1769 if (NT_STATUS_IS_OK(result
)) {
1770 domain
->active_directory
= True
;
1773 fstrcpy(domain
->name
, domain_name
);
1776 fstrcpy(domain
->alt_name
, dns_name
);
1779 fstrcpy(domain
->forest_name
, forest_name
);
1782 sid_copy(&domain
->sid
, dom_sid
);
1784 domain
->active_directory
= False
;
1786 result
= rpccli_lsa_open_policy(cli
, mem_ctx
, True
,
1787 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1790 if (!NT_STATUS_IS_OK(result
))
1793 result
= rpccli_lsa_query_info_policy(cli
, mem_ctx
,
1794 &pol
, 5, &domain_name
,
1797 if (NT_STATUS_IS_OK(result
)) {
1799 fstrcpy(domain
->name
, domain_name
);
1802 sid_copy(&domain
->sid
, dom_sid
);
1807 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1808 domain
->name
, domain
->native_mode
? "" : "NOT "));
1810 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1811 domain
->name
, domain
->active_directory
? "" : "NOT "));
1813 cli_rpc_pipe_close(cli
);
1815 talloc_destroy(mem_ctx
);
1817 domain
->initialized
= True
;
1820 /**********************************************************************
1821 Set the domain_flags (trust attributes, domain operating modes, etc...
1822 ***********************************************************************/
1824 static void set_dc_type_and_flags( struct winbindd_domain
*domain
)
1826 /* we always have to contact our primary domain */
1828 if ( domain
->primary
) {
1829 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1830 "primary domain\n"));
1831 set_dc_type_and_flags_connect( domain
);
1835 /* Use our DC to get the information if possible */
1837 if ( !set_dc_type_and_flags_trustinfo( domain
) ) {
1838 /* Otherwise, fallback to contacting the
1840 set_dc_type_and_flags_connect( domain
);
1848 /**********************************************************************
1849 ***********************************************************************/
1851 static BOOL
cm_get_schannel_dcinfo(struct winbindd_domain
*domain
,
1852 struct dcinfo
**ppdc
)
1855 struct rpc_pipe_client
*netlogon_pipe
;
1857 if (lp_client_schannel() == False
) {
1861 result
= cm_connect_netlogon(domain
, &netlogon_pipe
);
1862 if (!NT_STATUS_IS_OK(result
)) {
1866 /* Return a pointer to the struct dcinfo from the
1869 *ppdc
= domain
->conn
.netlogon_pipe
->dc
;
1873 NTSTATUS
cm_connect_sam(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
1874 struct rpc_pipe_client
**cli
, POLICY_HND
*sam_handle
)
1876 struct winbindd_cm_conn
*conn
;
1877 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1879 struct dcinfo
*p_dcinfo
;
1881 result
= init_dc_connection(domain
);
1882 if (!NT_STATUS_IS_OK(result
)) {
1886 conn
= &domain
->conn
;
1888 if (conn
->samr_pipe
!= NULL
) {
1893 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1894 * sign and sealed pipe using the machine account password by
1895 * preference. If we can't - try schannel, if that fails, try
1899 pwd_get_cleartext(&conn
->cli
->pwd
, conn_pwd
);
1900 if ((conn
->cli
->user_name
[0] == '\0') ||
1901 (conn
->cli
->domain
[0] == '\0') ||
1902 (conn_pwd
[0] == '\0')) {
1903 DEBUG(10, ("cm_connect_sam: No no user available for "
1904 "domain %s, trying schannel\n", conn
->cli
->domain
));
1908 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1909 authenticated SAMR pipe with sign & seal. */
1911 cli_rpc_pipe_open_spnego_ntlmssp(conn
->cli
, PI_SAMR
,
1912 PIPE_AUTH_LEVEL_PRIVACY
,
1914 conn
->cli
->user_name
,
1917 if (conn
->samr_pipe
== NULL
) {
1918 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1919 "pipe for domain %s using NTLMSSP "
1920 "authenticated pipe: user %s\\%s. Error was "
1921 "%s\n", domain
->name
, conn
->cli
->domain
,
1922 conn
->cli
->user_name
, nt_errstr(result
)));
1926 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1927 "domain %s using NTLMSSP authenticated "
1928 "pipe: user %s\\%s\n", domain
->name
,
1929 conn
->cli
->domain
, conn
->cli
->user_name
));
1931 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1932 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1933 &conn
->sam_connect_handle
);
1934 if (NT_STATUS_IS_OK(result
)) {
1937 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1938 "failed for domain %s, error was %s. Trying schannel\n",
1939 domain
->name
, nt_errstr(result
) ));
1940 cli_rpc_pipe_close(conn
->samr_pipe
);
1944 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1946 if (!cm_get_schannel_dcinfo(domain
, &p_dcinfo
)) {
1947 /* If this call fails - conn->cli can now be NULL ! */
1948 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1949 "for domain %s, trying anon\n", domain
->name
));
1952 conn
->samr_pipe
= cli_rpc_pipe_open_schannel_with_key
1953 (conn
->cli
, PI_SAMR
, PIPE_AUTH_LEVEL_PRIVACY
,
1954 domain
->name
, p_dcinfo
, &result
);
1956 if (conn
->samr_pipe
== NULL
) {
1957 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1958 "domain %s using schannel. Error was %s\n",
1959 domain
->name
, nt_errstr(result
) ));
1962 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1963 "schannel.\n", domain
->name
));
1965 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1966 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1967 &conn
->sam_connect_handle
);
1968 if (NT_STATUS_IS_OK(result
)) {
1971 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1972 "for domain %s, error was %s. Trying anonymous\n",
1973 domain
->name
, nt_errstr(result
) ));
1974 cli_rpc_pipe_close(conn
->samr_pipe
);
1978 /* Finally fall back to anonymous. */
1979 conn
->samr_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_SAMR
,
1982 if (conn
->samr_pipe
== NULL
) {
1983 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
1987 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1988 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1989 &conn
->sam_connect_handle
);
1990 if (!NT_STATUS_IS_OK(result
)) {
1991 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1992 "for domain %s Error was %s\n",
1993 domain
->name
, nt_errstr(result
) ));
1998 result
= rpccli_samr_open_domain(conn
->samr_pipe
,
2000 &conn
->sam_connect_handle
,
2001 SEC_RIGHTS_MAXIMUM_ALLOWED
,
2003 &conn
->sam_domain_handle
);
2007 if (!NT_STATUS_IS_OK(result
)) {
2008 invalidate_cm_connection(conn
);
2012 *cli
= conn
->samr_pipe
;
2013 *sam_handle
= conn
->sam_domain_handle
;
2017 NTSTATUS
cm_connect_lsa(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
2018 struct rpc_pipe_client
**cli
, POLICY_HND
*lsa_policy
)
2020 struct winbindd_cm_conn
*conn
;
2021 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2023 struct dcinfo
*p_dcinfo
;
2025 result
= init_dc_connection(domain
);
2026 if (!NT_STATUS_IS_OK(result
))
2029 conn
= &domain
->conn
;
2031 if (conn
->lsa_pipe
!= NULL
) {
2035 pwd_get_cleartext(&conn
->cli
->pwd
, conn_pwd
);
2036 if ((conn
->cli
->user_name
[0] == '\0') ||
2037 (conn
->cli
->domain
[0] == '\0') ||
2038 (conn_pwd
[0] == '\0')) {
2039 DEBUG(10, ("cm_connect_lsa: No no user available for "
2040 "domain %s, trying schannel\n", conn
->cli
->domain
));
2044 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2045 * authenticated LSA pipe with sign & seal. */
2046 conn
->lsa_pipe
= cli_rpc_pipe_open_spnego_ntlmssp
2047 (conn
->cli
, PI_LSARPC
, PIPE_AUTH_LEVEL_PRIVACY
,
2048 conn
->cli
->domain
, conn
->cli
->user_name
, conn_pwd
, &result
);
2050 if (conn
->lsa_pipe
== NULL
) {
2051 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2052 "domain %s using NTLMSSP authenticated pipe: user "
2053 "%s\\%s. Error was %s. Trying schannel.\n",
2054 domain
->name
, conn
->cli
->domain
,
2055 conn
->cli
->user_name
, nt_errstr(result
)));
2059 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2060 "NTLMSSP authenticated pipe: user %s\\%s\n",
2061 domain
->name
, conn
->cli
->domain
, conn
->cli
->user_name
));
2063 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2064 SEC_RIGHTS_MAXIMUM_ALLOWED
,
2066 if (NT_STATUS_IS_OK(result
)) {
2070 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2073 cli_rpc_pipe_close(conn
->lsa_pipe
);
2077 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2079 if (!cm_get_schannel_dcinfo(domain
, &p_dcinfo
)) {
2080 /* If this call fails - conn->cli can now be NULL ! */
2081 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2082 "for domain %s, trying anon\n", domain
->name
));
2085 conn
->lsa_pipe
= cli_rpc_pipe_open_schannel_with_key
2086 (conn
->cli
, PI_LSARPC
, PIPE_AUTH_LEVEL_PRIVACY
,
2087 domain
->name
, p_dcinfo
, &result
);
2089 if (conn
->lsa_pipe
== NULL
) {
2090 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2091 "domain %s using schannel. Error was %s\n",
2092 domain
->name
, nt_errstr(result
) ));
2095 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2096 "schannel.\n", domain
->name
));
2098 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2099 SEC_RIGHTS_MAXIMUM_ALLOWED
,
2101 if (NT_STATUS_IS_OK(result
)) {
2105 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2108 cli_rpc_pipe_close(conn
->lsa_pipe
);
2112 conn
->lsa_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_LSARPC
,
2114 if (conn
->lsa_pipe
== NULL
) {
2115 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
2119 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2120 SEC_RIGHTS_MAXIMUM_ALLOWED
,
2123 if (!NT_STATUS_IS_OK(result
)) {
2124 invalidate_cm_connection(conn
);
2128 *cli
= conn
->lsa_pipe
;
2129 *lsa_policy
= conn
->lsa_policy
;
2133 /****************************************************************************
2134 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2135 session key stored in conn->netlogon_pipe->dc->sess_key.
2136 ****************************************************************************/
2138 NTSTATUS
cm_connect_netlogon(struct winbindd_domain
*domain
,
2139 struct rpc_pipe_client
**cli
)
2141 struct winbindd_cm_conn
*conn
;
2144 uint32 neg_flags
= NETLOGON_NEG_AUTH2_FLAGS
;
2146 uint32 sec_chan_type
;
2147 const char *account_name
;
2148 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
2152 result
= init_dc_connection(domain
);
2153 if (!NT_STATUS_IS_OK(result
)) {
2157 conn
= &domain
->conn
;
2159 if (conn
->netlogon_pipe
!= NULL
) {
2160 *cli
= conn
->netlogon_pipe
;
2161 return NT_STATUS_OK
;
2164 if ((IS_DC
|| domain
->primary
) && !get_trust_pw(domain
->name
, mach_pwd
, &sec_chan_type
)) {
2165 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2168 netlogon_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_NETLOGON
,
2170 if (netlogon_pipe
== NULL
) {
2174 if ((!IS_DC
) && (!domain
->primary
)) {
2175 /* Clear the schannel request bit and drop down */
2176 neg_flags
&= ~NETLOGON_NEG_SCHANNEL
;
2180 if (lp_client_schannel() != False
) {
2181 neg_flags
|= NETLOGON_NEG_SCHANNEL
;
2184 /* if we are a DC and this is a trusted domain, then we need to use our
2185 domain name in the net_req_auth2() request */
2188 && !strequal(domain
->name
, lp_workgroup())
2189 && lp_allow_trusted_domains() )
2191 account_name
= lp_workgroup();
2193 account_name
= domain
->primary
?
2194 global_myname() : domain
->name
;
2197 if (account_name
== NULL
) {
2198 cli_rpc_pipe_close(netlogon_pipe
);
2199 return NT_STATUS_NO_MEMORY
;
2202 result
= rpccli_netlogon_setup_creds(
2204 domain
->dcname
, /* server name. */
2205 domain
->name
, /* domain name */
2206 global_myname(), /* client name */
2207 account_name
, /* machine account */
2208 mach_pwd
, /* machine password */
2209 sec_chan_type
, /* from get_trust_pw */
2212 if (!NT_STATUS_IS_OK(result
)) {
2213 cli_rpc_pipe_close(netlogon_pipe
);
2217 if ((lp_client_schannel() == True
) &&
2218 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2219 DEBUG(3, ("Server did not offer schannel\n"));
2220 cli_rpc_pipe_close(netlogon_pipe
);
2221 return NT_STATUS_ACCESS_DENIED
;
2225 if ((lp_client_schannel() == False
) ||
2226 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2229 * NetSamLogonEx only works for schannel
2231 domain
->can_do_samlogon_ex
= False
;
2233 /* We're done - just keep the existing connection to NETLOGON
2235 conn
->netlogon_pipe
= netlogon_pipe
;
2236 *cli
= conn
->netlogon_pipe
;
2237 return NT_STATUS_OK
;
2240 /* Using the credentials from the first pipe, open a signed and sealed
2241 second netlogon pipe. The session key is stored in the schannel
2242 part of the new pipe auth struct.
2245 conn
->netlogon_pipe
=
2246 cli_rpc_pipe_open_schannel_with_key(conn
->cli
,
2248 PIPE_AUTH_LEVEL_PRIVACY
,
2253 /* We can now close the initial netlogon pipe. */
2254 cli_rpc_pipe_close(netlogon_pipe
);
2256 if (conn
->netlogon_pipe
== NULL
) {
2257 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2258 "was %s\n", nt_errstr(result
)));
2260 /* make sure we return something besides OK */
2261 return !NT_STATUS_IS_OK(result
) ? result
: NT_STATUS_PIPE_NOT_AVAILABLE
;
2265 * Try NetSamLogonEx for AD domains
2267 domain
->can_do_samlogon_ex
= domain
->active_directory
;
2269 *cli
= conn
->netlogon_pipe
;
2270 return NT_STATUS_OK
;