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 2 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, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 We need to manage connections to domain controllers without having to
29 mess up the main winbindd code with other issues. The aim of the
30 connection manager is to:
32 - make connections to domain controllers and cache them
33 - re-establish connections when networks or servers go down
34 - centralise the policy on connection timeouts, domain controller
36 - manage re-entrancy for when winbindd becomes able to handle
37 multiple outstanding rpc requests
39 Why not have connection management as part of the rpc layer like tng?
40 Good question. This code may morph into libsmb/rpc_cache.c or something
41 like that but at the moment it's simply staying as part of winbind. I
42 think the TNG architecture of forcing every user of the rpc layer to use
43 the connection caching system is a bad idea. It should be an optional
44 method of using the routines.
46 The TNG design is quite good but I disagree with some aspects of the
54 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
55 moved down into another function.
57 - Take care when destroying cli_structs as they can be shared between
66 #define DBGC_CLASS DBGC_WINBIND
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
, const 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(int msg_type
, struct process_id src
,
86 void *buf
, size_t len
, void *private_data
)
88 struct winbindd_domain
*domain
;
89 const char *domainname
= (const char *)buf
;
91 if (buf
== NULL
|| len
== 0) {
95 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname
));
97 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
98 if (domain
->internal
) {
102 if (strequal(domain
->name
, domainname
)) {
103 if (domain
->online
) {
104 /* We're already online, ignore. */
105 DEBUG(5,("msg_fail_to_go_online: domain %s "
106 "already online.\n", domainname
));
110 /* Reschedule the online check. */
111 set_domain_offline(domain
);
117 /****************************************************************
118 Actually cause a reconnect from a message.
119 ****************************************************************/
121 static void msg_try_to_go_online(int msg_type
, struct process_id src
,
122 void *buf
, size_t len
, void *private_data
)
124 struct winbindd_domain
*domain
;
125 const char *domainname
= (const char *)buf
;
127 if (buf
== NULL
|| len
== 0) {
131 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname
));
133 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
134 if (domain
->internal
) {
138 if (strequal(domain
->name
, domainname
)) {
140 if (domain
->online
) {
141 /* We're already online, ignore. */
142 DEBUG(5,("msg_try_to_go_online: domain %s "
143 "already online.\n", domainname
));
147 /* This call takes care of setting the online
148 flag to true if we connected, or re-adding
149 the offline handler if false. Bypasses online
150 check so always does network calls. */
152 init_dc_connection_network(domain
);
158 /****************************************************************
159 Fork a child to try and contact a DC. Do this as contacting a
160 DC requires blocking lookups and we don't want to block our
162 ****************************************************************/
164 static BOOL
fork_child_dc_connect(struct winbindd_domain
*domain
)
166 struct dc_name_ip
*dcs
= NULL
;
168 TALLOC_CTX
*mem_ctx
= NULL
;
170 pid_t parent_pid
= sys_getpid();
177 child_pid
= sys_fork();
179 if (child_pid
== -1) {
180 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno
)));
185 if (child_pid
!= 0) {
187 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE
,
188 msg_try_to_go_online
, NULL
);
189 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE
,
190 msg_failed_to_go_online
, NULL
);
197 /* Leave messages blocked - we will never process one. */
199 /* tdb needs special fork handling */
200 if (tdb_reopen_all(1) == -1) {
201 DEBUG(0,("tdb_reopen_all failed.\n"));
205 close_conns_after_fork();
207 if (!override_logfile
) {
209 pstr_sprintf(logfile
, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE
);
210 lp_set_logfile(logfile
);
214 mem_ctx
= talloc_init("fork_child_dc_connect");
216 DEBUG(0,("talloc_init failed.\n"));
220 if ((!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
)) || (num_dcs
== 0)) {
221 /* Still offline ? Can't find DC's. */
222 message_send_pid(pid_to_procid(parent_pid
), MSG_WINBIND_FAILED_TO_GO_ONLINE
,
224 strlen(domain
->name
)+1, False
);
228 /* We got a DC. Send a message to our parent to get it to
229 try and do the same. */
231 message_send_pid(pid_to_procid(parent_pid
), MSG_WINBIND_TRY_TO_GO_ONLINE
,
233 strlen(domain
->name
)+1, False
);
237 /****************************************************************
238 Handler triggered if we're offline to try and detect a DC.
239 ****************************************************************/
241 static void check_domain_online_handler(struct event_context
*ctx
,
242 struct timed_event
*te
,
243 const struct timeval
*now
,
246 struct winbindd_domain
*domain
=
247 (struct winbindd_domain
*)private_data
;
249 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
252 TALLOC_FREE(domain
->check_online_event
);
254 /* Are we still in "startup" mode ? */
256 if (domain
->startup
&& (now
->tv_sec
> domain
->startup_time
+ 30)) {
257 /* No longer in "startup" mode. */
258 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
260 domain
->startup
= False
;
263 /* We've been told to stay offline, so stay
266 if (get_global_winbindd_state_offline()) {
267 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
272 /* Fork a child to test if it can contact a DC.
273 If it can then send ourselves a message to
274 cause a reconnect. */
276 fork_child_dc_connect(domain
);
279 /****************************************************************
280 If we're still offline setup the timeout check.
281 ****************************************************************/
283 static void calc_new_online_timeout_check(struct winbindd_domain
*domain
)
285 int wbc
= lp_winbind_cache_time();
287 if (domain
->startup
) {
288 domain
->check_online_timeout
= 10;
289 } else if (domain
->check_online_timeout
< wbc
) {
290 domain
->check_online_timeout
= wbc
;
294 /****************************************************************
295 Set domain offline and also add handler to put us back online
297 ****************************************************************/
299 void set_domain_offline(struct winbindd_domain
*domain
)
301 DEBUG(10,("set_domain_offline: called for domain %s\n",
304 TALLOC_FREE(domain
->check_online_event
);
306 if (domain
->internal
) {
307 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
312 domain
->online
= False
;
314 /* Offline domains are always initialized. They're
315 re-initialized when they go back online. */
317 domain
->initialized
= True
;
319 /* We only add the timeout handler that checks and
320 allows us to go back online when we've not
321 been told to remain offline. */
323 if (get_global_winbindd_state_offline()) {
324 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
329 /* If we're in statup mode, check again in 10 seconds, not in
330 lp_winbind_cache_time() seconds (which is 5 mins by default). */
332 calc_new_online_timeout_check(domain
);
334 domain
->check_online_event
= event_add_timed(winbind_event_context(),
336 timeval_current_ofs(domain
->check_online_timeout
,0),
337 "check_domain_online_handler",
338 check_domain_online_handler
,
341 /* The above *has* to succeed for winbindd to work. */
342 if (!domain
->check_online_event
) {
343 smb_panic("set_domain_offline: failed to add online handler.\n");
346 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
350 /****************************************************************
351 Set domain online - if allowed.
352 ****************************************************************/
354 static void set_domain_online(struct winbindd_domain
*domain
)
358 DEBUG(10,("set_domain_online: called for domain %s\n",
361 if (domain
->internal
) {
362 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
367 if (get_global_winbindd_state_offline()) {
368 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
373 /* If we are waiting to get a krb5 ticket, trigger immediately. */
375 set_event_dispatch_time(winbind_event_context(),
376 "krb5_ticket_gain_handler", now
);
378 /* Ok, we're out of any startup mode now... */
379 domain
->startup
= False
;
381 if (domain
->online
== False
) {
382 /* We were offline - now we're online. We default to
383 using the MS-RPC backend if we started offline,
384 and if we're going online for the first time we
385 should really re-initialize the backends and the
386 checks to see if we're talking to an AD or NT domain.
389 domain
->initialized
= False
;
391 /* 'reconnect_methods' is the MS-RPC backend. */
392 if (domain
->backend
== &reconnect_methods
) {
393 domain
->backend
= NULL
;
397 /* Ensure we have no online timeout checks. */
398 domain
->check_online_timeout
= 0;
399 TALLOC_FREE(domain
->check_online_event
);
401 /* Ensure we ignore any pending child messages. */
402 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE
);
403 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE
);
405 domain
->online
= True
;
408 /****************************************************************
409 Requested to set a domain online.
410 ****************************************************************/
412 void set_domain_online_request(struct winbindd_domain
*domain
)
416 DEBUG(10,("set_domain_online_request: called for domain %s\n",
419 if (get_global_winbindd_state_offline()) {
420 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
425 /* We've been told it's safe to go online and
426 try and connect to a DC. But I don't believe it
427 because network manager seems to lie.
428 Wait at least 5 seconds. Heuristics suck... */
430 if (!domain
->check_online_event
) {
431 /* If we've come from being globally offline we
432 don't have a check online event handler set.
433 We need to add one now we're trying to go
436 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
439 domain
->check_online_event
= event_add_timed(winbind_event_context(),
441 timeval_current_ofs(5, 0),
442 "check_domain_online_handler",
443 check_domain_online_handler
,
446 /* The above *has* to succeed for winbindd to work. */
447 if (!domain
->check_online_event
) {
448 smb_panic("set_domain_online_request: failed to add online handler.\n");
454 /* Go into "startup" mode again. */
455 domain
->startup_time
= tev
.tv_sec
;
456 domain
->startup
= True
;
460 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev
);
463 /****************************************************************
464 Add -ve connection cache entries for domain and realm.
465 ****************************************************************/
467 void winbind_add_failed_connection_entry(const struct winbindd_domain
*domain
,
471 add_failed_connection_entry(domain
->name
, server
, result
);
472 /* If this was the saf name for the last thing we talked to,
474 saf_delete(domain
->name
);
475 if (*domain
->alt_name
) {
476 add_failed_connection_entry(domain
->alt_name
, server
, result
);
477 saf_delete(domain
->alt_name
);
481 /* Choose between anonymous or authenticated connections. We need to use
482 an authenticated connection if DCs have the RestrictAnonymous registry
483 entry set > 0, or the "Additional restrictions for anonymous
484 connections" set in the win2k Local Security Policy.
486 Caller to free() result in domain, username, password
489 static void cm_get_ipc_userpass(char **username
, char **domain
, char **password
)
491 *username
= (char *)secrets_fetch(SECRETS_AUTH_USER
, NULL
);
492 *domain
= (char *)secrets_fetch(SECRETS_AUTH_DOMAIN
, NULL
);
493 *password
= (char *)secrets_fetch(SECRETS_AUTH_PASSWORD
, NULL
);
495 if (*username
&& **username
) {
497 if (!*domain
|| !**domain
)
498 *domain
= smb_xstrdup(lp_workgroup());
500 if (!*password
|| !**password
)
501 *password
= smb_xstrdup("");
503 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
504 *domain
, *username
));
507 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
508 *username
= smb_xstrdup("");
509 *domain
= smb_xstrdup("");
510 *password
= smb_xstrdup("");
514 static BOOL
get_dc_name_via_netlogon(const struct winbindd_domain
*domain
,
515 fstring dcname
, struct in_addr
*dc_ip
)
517 struct winbindd_domain
*our_domain
= NULL
;
518 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
522 unsigned int orig_timeout
;
526 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
533 if (domain
->primary
) {
537 our_domain
= find_our_domain();
539 if ((mem_ctx
= talloc_init("get_dc_name_via_netlogon")) == NULL
) {
543 result
= cm_connect_netlogon(our_domain
, &netlogon_pipe
);
544 if (!NT_STATUS_IS_OK(result
)) {
545 talloc_destroy(mem_ctx
);
549 /* This call can take a long time - allow the server to time out.
550 35 seconds should do it. */
552 orig_timeout
= cli_set_timeout(netlogon_pipe
->cli
, 35000);
554 werr
= rpccli_netlogon_getanydcname(netlogon_pipe
, mem_ctx
, our_domain
->dcname
,
557 /* And restore our original timeout. */
558 cli_set_timeout(netlogon_pipe
->cli
, orig_timeout
);
560 talloc_destroy(mem_ctx
);
562 if (!W_ERROR_IS_OK(werr
)) {
563 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
568 /* cli_netlogon_getanydcname gives us a name with \\ */
579 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname
));
581 if (!resolve_name(dcname
, dc_ip
, 0x20)) {
589 * Helper function to assemble trust password and account name
591 static NTSTATUS
get_trust_creds(const struct winbindd_domain
*domain
,
592 char **machine_password
,
593 char **machine_account
,
594 char **machine_krb5_principal
)
596 const char *account_name
;
598 if (!get_trust_pw_clear(domain
->name
, machine_password
,
599 &account_name
, NULL
))
601 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
604 if ((machine_account
!= NULL
) &&
605 (asprintf(machine_account
, "%s$", account_name
) == -1))
607 return NT_STATUS_NO_MEMORY
;
610 /* this is at least correct when domain is our domain,
611 * which is the only case, when this is currently used: */
612 if (machine_krb5_principal
!= NULL
)
614 if (asprintf(machine_krb5_principal
, "%s$@%s",
615 account_name
, domain
->alt_name
) == -1)
617 return NT_STATUS_NO_MEMORY
;
620 strupper_m(*machine_krb5_principal
);
626 /************************************************************************
627 Given a fd with a just-connected TCP connection to a DC, open a connection
629 ************************************************************************/
631 static NTSTATUS
cm_prepare_connection(const struct winbindd_domain
*domain
,
633 const char *controller
,
634 struct cli_state
**cli
,
637 char *machine_password
= NULL
;
638 char *machine_krb5_principal
= NULL
;
639 char *machine_account
= NULL
;
640 char *ipc_username
= NULL
;
641 char *ipc_domain
= NULL
;
642 char *ipc_password
= NULL
;
646 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
648 struct sockaddr peeraddr
;
649 socklen_t peeraddr_len
;
651 struct sockaddr_in
*peeraddr_in
= (struct sockaddr_in
*)&peeraddr
;
653 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
654 controller
, domain
->name
));
658 got_mutex
= secrets_named_mutex(controller
,
659 WINBIND_SERVER_MUTEX_WAIT_TIME
);
662 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
664 result
= NT_STATUS_POSSIBLE_DEADLOCK
;
668 if ((*cli
= cli_initialise()) == NULL
) {
669 DEBUG(1, ("Could not cli_initialize\n"));
670 result
= NT_STATUS_NO_MEMORY
;
674 (*cli
)->timeout
= 10000; /* 10 seconds */
676 fstrcpy((*cli
)->desthost
, controller
);
677 (*cli
)->use_kerberos
= True
;
679 peeraddr_len
= sizeof(peeraddr
);
681 if ((getpeername((*cli
)->fd
, &peeraddr
, &peeraddr_len
) != 0) ||
682 (peeraddr_len
!= sizeof(struct sockaddr_in
)) ||
683 (peeraddr_in
->sin_family
!= PF_INET
))
685 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno
)));
686 result
= NT_STATUS_UNSUCCESSFUL
;
690 if (ntohs(peeraddr_in
->sin_port
) == 139) {
691 struct nmb_name calling
;
692 struct nmb_name called
;
694 make_nmb_name(&calling
, global_myname(), 0x0);
695 make_nmb_name(&called
, "*SMBSERVER", 0x20);
697 if (!cli_session_request(*cli
, &calling
, &called
)) {
698 DEBUG(8, ("cli_session_request failed for %s\n",
700 result
= NT_STATUS_UNSUCCESSFUL
;
705 cli_setup_signing_state(*cli
, Undefined
);
707 if (!cli_negprot(*cli
)) {
708 DEBUG(1, ("cli_negprot failed\n"));
709 result
= NT_STATUS_UNSUCCESSFUL
;
713 if (!is_trusted_domain_situation(domain
->name
) &&
714 (*cli
)->protocol
>= PROTOCOL_NT1
&&
715 (*cli
)->capabilities
& CAP_EXTENDED_SECURITY
)
717 ADS_STATUS ads_status
;
719 result
= get_trust_creds(domain
, &machine_password
,
721 &machine_krb5_principal
);
722 if (!NT_STATUS_IS_OK(result
)) {
726 if (lp_security() == SEC_ADS
) {
728 /* Try a krb5 session */
730 (*cli
)->use_kerberos
= True
;
731 DEBUG(5, ("connecting to %s from %s with kerberos principal "
732 "[%s]\n", controller
, global_myname(),
733 machine_krb5_principal
));
735 ads_status
= cli_session_setup_spnego(*cli
,
736 machine_krb5_principal
,
740 if (!ADS_ERR_OK(ads_status
)) {
741 DEBUG(4,("failed kerberos session setup with %s\n",
742 ads_errstr(ads_status
)));
745 result
= ads_ntstatus(ads_status
);
746 if (NT_STATUS_IS_OK(result
)) {
747 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
748 cli_init_creds(*cli
, machine_account
, domain
->name
, machine_password
);
749 goto session_setup_done
;
753 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
754 (*cli
)->use_kerberos
= False
;
756 DEBUG(5, ("connecting to %s from %s with username "
757 "[%s]\\[%s]\n", controller
, global_myname(),
758 domain
->name
, machine_account
));
760 ads_status
= cli_session_setup_spnego(*cli
,
764 if (!ADS_ERR_OK(ads_status
)) {
765 DEBUG(4, ("authenticated session setup failed with %s\n",
766 ads_errstr(ads_status
)));
769 result
= ads_ntstatus(ads_status
);
770 if (NT_STATUS_IS_OK(result
)) {
771 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
772 cli_init_creds(*cli
, machine_account
, domain
->name
, machine_password
);
773 goto session_setup_done
;
777 /* Fall back to non-kerberos session setup with auth_user */
779 (*cli
)->use_kerberos
= False
;
781 cm_get_ipc_userpass(&ipc_username
, &ipc_domain
, &ipc_password
);
783 if ((((*cli
)->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) != 0) &&
784 (strlen(ipc_username
) > 0)) {
786 /* Only try authenticated if we have a username */
788 DEBUG(5, ("connecting to %s from %s with username "
789 "[%s]\\[%s]\n", controller
, global_myname(),
790 ipc_domain
, ipc_username
));
792 if (NT_STATUS_IS_OK(cli_session_setup(
794 ipc_password
, strlen(ipc_password
)+1,
795 ipc_password
, strlen(ipc_password
)+1,
797 /* Successful logon with given username. */
798 cli_init_creds(*cli
, ipc_username
, ipc_domain
, ipc_password
);
799 goto session_setup_done
;
801 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
802 ipc_domain
, ipc_username
));
808 /* Fall back to anonymous connection, this might fail later */
810 if (NT_STATUS_IS_OK(cli_session_setup(*cli
, "", NULL
, 0,
812 DEBUG(5, ("Connected anonymously\n"));
813 cli_init_creds(*cli
, "", "", "");
814 goto session_setup_done
;
817 result
= cli_nt_error(*cli
);
819 if (NT_STATUS_IS_OK(result
))
820 result
= NT_STATUS_UNSUCCESSFUL
;
822 /* We can't session setup */
828 /* cache the server name for later connections */
830 saf_store( domain
->name
, (*cli
)->desthost
);
831 if (domain
->alt_name
&& (*cli
)->use_kerberos
) {
832 saf_store( domain
->alt_name
, (*cli
)->desthost
);
835 if (!cli_send_tconX(*cli
, "IPC$", "IPC", "", 0)) {
837 result
= cli_nt_error(*cli
);
839 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result
)));
841 if (NT_STATUS_IS_OK(result
))
842 result
= NT_STATUS_UNSUCCESSFUL
;
847 secrets_named_mutex_release(controller
);
851 /* set the domain if empty; needed for schannel connections */
852 if ( !*(*cli
)->domain
) {
853 fstrcpy( (*cli
)->domain
, domain
->name
);
856 result
= NT_STATUS_OK
;
860 secrets_named_mutex_release(controller
);
863 SAFE_FREE(machine_account
);
864 SAFE_FREE(machine_password
);
865 SAFE_FREE(machine_krb5_principal
);
866 SAFE_FREE(ipc_username
);
867 SAFE_FREE(ipc_domain
);
868 SAFE_FREE(ipc_password
);
870 if (!NT_STATUS_IS_OK(result
)) {
871 winbind_add_failed_connection_entry(domain
, controller
, result
);
872 if ((*cli
) != NULL
) {
881 static BOOL
add_one_dc_unique(TALLOC_CTX
*mem_ctx
, const char *domain_name
,
882 const char *dcname
, struct in_addr ip
,
883 struct dc_name_ip
**dcs
, int *num
)
885 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name
, dcname
))) {
886 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname
));
890 *dcs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *dcs
, struct dc_name_ip
, (*num
)+1);
895 fstrcpy((*dcs
)[*num
].name
, dcname
);
896 (*dcs
)[*num
].ip
= ip
;
901 static BOOL
add_sockaddr_to_array(TALLOC_CTX
*mem_ctx
,
902 struct in_addr ip
, uint16 port
,
903 struct sockaddr_in
**addrs
, int *num
)
905 *addrs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *addrs
, struct sockaddr_in
, (*num
)+1);
907 if (*addrs
== NULL
) {
912 (*addrs
)[*num
].sin_family
= PF_INET
;
913 putip((char *)&((*addrs
)[*num
].sin_addr
), (char *)&ip
);
914 (*addrs
)[*num
].sin_port
= htons(port
);
920 static void mailslot_name(struct in_addr dc_ip
, fstring name
)
922 fstr_sprintf(name
, "\\MAILSLOT\\NET\\GETDC%X", dc_ip
.s_addr
);
925 static BOOL
send_getdc_request(struct in_addr dc_ip
,
926 const char *domain_name
,
931 fstring my_acct_name
;
934 mailslot_name(dc_ip
, my_mailslot
);
936 memset(outbuf
, '\0', sizeof(outbuf
));
940 SCVAL(p
, 0, SAMLOGON
);
943 SCVAL(p
, 0, 0); /* Count pointer ... */
946 SIVAL(p
, 0, 0); /* The sender's token ... */
949 p
+= dos_PutUniCode(p
, global_myname(),
950 sizeof(outbuf
) - PTR_DIFF(p
, outbuf
), True
);
951 fstr_sprintf(my_acct_name
, "%s$", global_myname());
952 p
+= dos_PutUniCode(p
, my_acct_name
,
953 sizeof(outbuf
) - PTR_DIFF(p
, outbuf
), True
);
955 if (strlen(my_mailslot
)+1 > sizeof(outbuf
) - PTR_DIFF(p
, outbuf
)) {
959 memcpy(p
, my_mailslot
, strlen(my_mailslot
)+1);
960 p
+= strlen(my_mailslot
)+1;
962 if (sizeof(outbuf
) - PTR_DIFF(p
, outbuf
) < 8) {
968 SIVAL(p
, 0, sid_size(sid
));
971 p
= ALIGN4(p
, outbuf
);
973 if (PTR_DIFF(p
, outbuf
) > sizeof(outbuf
)) {
977 if (sid_size(sid
) + 8 > sizeof(outbuf
) - PTR_DIFF(p
, outbuf
)) {
981 sid_linearize(p
, sizeof(outbuf
) - PTR_DIFF(p
, outbuf
), sid
);
989 return cli_send_mailslot(False
, "\\MAILSLOT\\NET\\NTLOGON", 0,
990 outbuf
, PTR_DIFF(p
, outbuf
),
991 global_myname(), 0, domain_name
, 0x1c,
995 static BOOL
receive_getdc_response(struct in_addr dc_ip
,
996 const char *domain_name
,
999 struct packet_struct
*packet
;
1000 fstring my_mailslot
;
1002 fstring dcname
, user
, domain
;
1005 mailslot_name(dc_ip
, my_mailslot
);
1007 packet
= receive_unexpected(DGRAM_PACKET
, 0, my_mailslot
);
1009 if (packet
== NULL
) {
1010 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot
));
1014 DEBUG(5, ("Received packet for %s\n", my_mailslot
));
1016 buf
= packet
->packet
.dgram
.data
;
1017 len
= packet
->packet
.dgram
.datasize
;
1020 /* 70 is a completely arbitrary value to make sure
1021 the SVAL below does not read uninitialized memory */
1022 DEBUG(3, ("GetDC got short response\n"));
1026 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1027 p
= buf
+SVAL(buf
, smb_vwv10
);
1029 if (CVAL(p
,0) != SAMLOGON_R
) {
1030 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p
, 0)));
1035 pull_ucs2(buf
, dcname
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
1036 STR_TERMINATE
|STR_NOALIGN
);
1037 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
1038 pull_ucs2(buf
, user
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
1039 STR_TERMINATE
|STR_NOALIGN
);
1040 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
1041 pull_ucs2(buf
, domain
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
1042 STR_TERMINATE
|STR_NOALIGN
);
1043 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
1045 if (!strequal(domain
, domain_name
)) {
1046 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1047 domain_name
, domain
));
1052 if (*p
== '\\') p
+= 1;
1053 if (*p
== '\\') p
+= 1;
1055 fstrcpy(dc_name
, p
);
1057 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1063 /*******************************************************************
1064 convert an ip to a name
1065 *******************************************************************/
1067 static BOOL
dcip_to_name(const struct winbindd_domain
*domain
, struct in_addr ip
, fstring name
)
1069 struct ip_service ip_list
;
1075 /* For active directory servers, try to get the ldap server name.
1076 None of these failures should be considered critical for now */
1078 if (lp_security() == SEC_ADS
) {
1081 ads
= ads_init(domain
->alt_name
, domain
->name
, NULL
);
1082 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
1084 if (ads_try_connect( ads
, inet_ntoa(ip
) ) ) {
1085 /* We got a cldap packet. */
1086 fstrcpy(name
, ads
->config
.ldap_server_name
);
1087 namecache_store(name
, 0x20, 1, &ip_list
);
1089 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads
->config
.flags
));
1091 if (domain
->primary
&& (ads
->config
.flags
& ADS_KDC
)) {
1092 if (ads_closest_dc(ads
)) {
1093 char *sitename
= sitename_fetch(ads
->config
.realm
);
1095 /* We're going to use this KDC for this realm/domain.
1096 If we are using sites, then force the krb5 libs
1099 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1104 SAFE_FREE(sitename
);
1106 /* use an off site KDC */
1107 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1112 /* Ensure we contact this DC also. */
1113 saf_store( domain
->name
, name
);
1114 saf_store( domain
->alt_name
, name
);
1117 ads_destroy( &ads
);
1121 ads_destroy( &ads
);
1125 /* try GETDC requests next */
1127 if (send_getdc_request(ip
, domain
->name
, &domain
->sid
)) {
1130 for (i
=0; i
<5; i
++) {
1131 if (receive_getdc_response(ip
, domain
->name
, name
)) {
1132 namecache_store(name
, 0x20, 1, &ip_list
);
1139 /* try node status request */
1141 if ( name_status_find(domain
->name
, 0x1c, 0x20, ip
, name
) ) {
1142 namecache_store(name
, 0x20, 1, &ip_list
);
1148 /*******************************************************************
1149 Retreive a list of IP address for domain controllers. Fill in
1150 the dcs[] with results.
1151 *******************************************************************/
1153 static BOOL
get_dcs(TALLOC_CTX
*mem_ctx
, const struct winbindd_domain
*domain
,
1154 struct dc_name_ip
**dcs
, int *num_dcs
)
1158 struct ip_service
*ip_list
= NULL
;
1159 int iplist_size
= 0;
1162 enum security_types sec
= (enum security_types
)lp_security();
1164 is_our_domain
= strequal(domain
->name
, lp_workgroup());
1167 && get_dc_name_via_netlogon(domain
, dcname
, &ip
)
1168 && add_one_dc_unique(mem_ctx
, domain
->name
, dcname
, ip
, dcs
, num_dcs
) )
1170 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1171 dcname
, inet_ntoa(ip
)));
1175 if (sec
== SEC_ADS
) {
1176 char *sitename
= NULL
;
1178 /* We need to make sure we know the local site before
1179 doing any DNS queries, as this will restrict the
1180 get_sorted_dc_list() call below to only fetching
1181 DNS records for the correct site. */
1183 /* Find any DC to get the site record.
1184 We deliberately don't care about the
1187 get_dc_name(domain
->name
, domain
->alt_name
, dcname
, &ip
);
1189 sitename
= sitename_fetch(domain
->alt_name
);
1192 /* Do the site-specific AD dns lookup first. */
1193 get_sorted_dc_list(domain
->alt_name
, sitename
, &ip_list
, &iplist_size
, True
);
1195 for ( i
=0; i
<iplist_size
; i
++ ) {
1196 add_one_dc_unique(mem_ctx
, domain
->name
, inet_ntoa(ip_list
[i
].ip
),
1197 ip_list
[i
].ip
, dcs
, num_dcs
);
1201 SAFE_FREE(sitename
);
1205 /* Now we add DCs from the main AD dns lookup. */
1206 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
, &iplist_size
, True
);
1208 for ( i
=0; i
<iplist_size
; i
++ ) {
1209 add_one_dc_unique(mem_ctx
, domain
->name
, inet_ntoa(ip_list
[i
].ip
),
1210 ip_list
[i
].ip
, dcs
, num_dcs
);
1214 /* try standard netbios queries if no ADS */
1216 if (iplist_size
==0) {
1217 get_sorted_dc_list(domain
->name
, NULL
, &ip_list
, &iplist_size
, False
);
1220 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1222 /* now add to the dc array. We'll wait until the last minute
1223 to look up the name of the DC. But we fill in the char* for
1224 the ip now in to make the failed connection cache work */
1226 for ( i
=0; i
<iplist_size
; i
++ ) {
1227 add_one_dc_unique(mem_ctx
, domain
->name
, inet_ntoa(ip_list
[i
].ip
),
1228 ip_list
[i
].ip
, dcs
, num_dcs
);
1231 SAFE_FREE( ip_list
);
1236 static BOOL
find_new_dc(TALLOC_CTX
*mem_ctx
,
1237 const struct winbindd_domain
*domain
,
1238 fstring dcname
, struct sockaddr_in
*addr
, int *fd
)
1240 struct dc_name_ip
*dcs
= NULL
;
1243 const char **dcnames
= NULL
;
1244 int num_dcnames
= 0;
1246 struct sockaddr_in
*addrs
= NULL
;
1252 if (!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
) || (num_dcs
== 0))
1255 for (i
=0; i
<num_dcs
; i
++) {
1257 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1258 &dcnames
, &num_dcnames
)) {
1261 if (!add_sockaddr_to_array(mem_ctx
, dcs
[i
].ip
, 445,
1262 &addrs
, &num_addrs
)) {
1266 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1267 &dcnames
, &num_dcnames
)) {
1270 if (!add_sockaddr_to_array(mem_ctx
, dcs
[i
].ip
, 139,
1271 &addrs
, &num_addrs
)) {
1276 if ((num_dcnames
== 0) || (num_dcnames
!= num_addrs
))
1279 if ((addrs
== NULL
) || (dcnames
== NULL
))
1282 /* 5 second timeout. */
1283 if ( !open_any_socket_out(addrs
, num_addrs
, 5000, &fd_index
, fd
) )
1285 for (i
=0; i
<num_dcs
; i
++) {
1286 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1287 "domain %s address %s. Error was %s\n",
1288 domain
->name
, inet_ntoa(dcs
[i
].ip
), strerror(errno
) ));
1289 winbind_add_failed_connection_entry(domain
,
1290 dcs
[i
].name
, NT_STATUS_UNSUCCESSFUL
);
1295 *addr
= addrs
[fd_index
];
1297 if (*dcnames
[fd_index
] != '\0' && !is_ipaddress(dcnames
[fd_index
])) {
1298 /* Ok, we've got a name for the DC */
1299 fstrcpy(dcname
, dcnames
[fd_index
]);
1303 /* Try to figure out the name */
1304 if (dcip_to_name( domain
, addr
->sin_addr
, dcname
)) {
1308 /* We can not continue without the DC's name */
1309 winbind_add_failed_connection_entry(domain
, dcs
[fd_index
].name
,
1310 NT_STATUS_UNSUCCESSFUL
);
1314 static NTSTATUS
cm_open_connection(struct winbindd_domain
*domain
,
1315 struct winbindd_cm_conn
*new_conn
)
1317 TALLOC_CTX
*mem_ctx
;
1319 char *saf_servername
= saf_fetch( domain
->name
);
1322 if ((mem_ctx
= talloc_init("cm_open_connection")) == NULL
) {
1323 SAFE_FREE(saf_servername
);
1324 set_domain_offline(domain
);
1325 return NT_STATUS_NO_MEMORY
;
1328 /* we have to check the server affinity cache here since
1329 later we selecte a DC based on response time and not preference */
1331 /* Check the negative connection cache
1332 before talking to it. It going down may have
1333 triggered the reconnection. */
1335 if ( saf_servername
&& NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, saf_servername
))) {
1337 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1338 saf_servername
, domain
->name
));
1340 /* convert an ip address to a name */
1341 if ( is_ipaddress( saf_servername
) ) {
1345 ip
= *interpret_addr2( saf_servername
);
1346 if (dcip_to_name( domain
, ip
, saf_name
)) {
1347 fstrcpy( domain
->dcname
, saf_name
);
1349 winbind_add_failed_connection_entry(
1350 domain
, saf_servername
,
1351 NT_STATUS_UNSUCCESSFUL
);
1354 fstrcpy( domain
->dcname
, saf_servername
);
1357 SAFE_FREE( saf_servername
);
1360 for (retries
= 0; retries
< 3; retries
++) {
1365 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1367 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1368 domain
->dcname
, domain
->name
));
1371 && NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, domain
->dcname
))
1372 && (resolve_name(domain
->dcname
, &domain
->dcaddr
.sin_addr
, 0x20)))
1374 struct sockaddr_in
*addrs
= NULL
;
1378 if (!add_sockaddr_to_array(mem_ctx
, domain
->dcaddr
.sin_addr
, 445, &addrs
, &num_addrs
)) {
1379 set_domain_offline(domain
);
1380 talloc_destroy(mem_ctx
);
1381 return NT_STATUS_NO_MEMORY
;
1383 if (!add_sockaddr_to_array(mem_ctx
, domain
->dcaddr
.sin_addr
, 139, &addrs
, &num_addrs
)) {
1384 set_domain_offline(domain
);
1385 talloc_destroy(mem_ctx
);
1386 return NT_STATUS_NO_MEMORY
;
1389 /* 5 second timeout. */
1390 if (!open_any_socket_out(addrs
, num_addrs
, 5000, &dummy
, &fd
)) {
1396 && !find_new_dc(mem_ctx
, domain
, domain
->dcname
, &domain
->dcaddr
, &fd
))
1398 /* This is the one place where we will
1399 set the global winbindd offline state
1400 to true, if a "WINBINDD_OFFLINE" entry
1401 is found in the winbindd cache. */
1402 set_global_winbindd_state_offline();
1406 new_conn
->cli
= NULL
;
1408 result
= cm_prepare_connection(domain
, fd
, domain
->dcname
,
1409 &new_conn
->cli
, &retry
);
1415 if (NT_STATUS_IS_OK(result
)) {
1416 if (domain
->online
== False
) {
1417 /* We're changing state from offline to online. */
1418 set_global_winbindd_state_online();
1420 set_domain_online(domain
);
1422 /* Ensure we setup the retry handler. */
1423 set_domain_offline(domain
);
1426 talloc_destroy(mem_ctx
);
1430 /* Close down all open pipes on a connection. */
1432 void invalidate_cm_connection(struct winbindd_cm_conn
*conn
)
1434 /* We're closing down a possibly dead
1435 connection. Don't have impossibly long (10s) timeouts. */
1438 cli_set_timeout(conn
->cli
, 1000); /* 1 second. */
1441 if (conn
->samr_pipe
!= NULL
) {
1442 if (!cli_rpc_pipe_close(conn
->samr_pipe
)) {
1443 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1445 cli_set_timeout(conn
->cli
, 500);
1448 conn
->samr_pipe
= NULL
;
1451 if (conn
->lsa_pipe
!= NULL
) {
1452 if (!cli_rpc_pipe_close(conn
->lsa_pipe
)) {
1453 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1455 cli_set_timeout(conn
->cli
, 500);
1458 conn
->lsa_pipe
= NULL
;
1461 if (conn
->netlogon_pipe
!= NULL
) {
1462 if (!cli_rpc_pipe_close(conn
->netlogon_pipe
)) {
1463 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1465 cli_set_timeout(conn
->cli
, 500);
1468 conn
->netlogon_pipe
= NULL
;
1472 cli_shutdown(conn
->cli
);
1478 void close_conns_after_fork(void)
1480 struct winbindd_domain
*domain
;
1482 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
1483 if (domain
->conn
.cli
== NULL
)
1486 if (domain
->conn
.cli
->fd
== -1)
1489 close(domain
->conn
.cli
->fd
);
1490 domain
->conn
.cli
->fd
= -1;
1494 static BOOL
connection_ok(struct winbindd_domain
*domain
)
1496 if (domain
->conn
.cli
== NULL
) {
1497 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1498 "cli!\n", domain
->dcname
, domain
->name
));
1502 if (!domain
->conn
.cli
->initialised
) {
1503 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1504 "initialised!\n", domain
->dcname
, domain
->name
));
1508 if (domain
->conn
.cli
->fd
== -1) {
1509 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1510 "never started (fd == -1)\n",
1511 domain
->dcname
, domain
->name
));
1515 if (domain
->online
== False
) {
1516 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain
->name
));
1523 /* Initialize a new connection up to the RPC BIND.
1524 Bypass online status check so always does network calls. */
1526 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
)
1530 /* Internal connections never use the network. */
1531 if (domain
->internal
) {
1532 domain
->initialized
= True
;
1533 return NT_STATUS_OK
;
1536 if (connection_ok(domain
)) {
1537 if (!domain
->initialized
) {
1538 set_dc_type_and_flags(domain
);
1540 return NT_STATUS_OK
;
1543 invalidate_cm_connection(&domain
->conn
);
1545 result
= cm_open_connection(domain
, &domain
->conn
);
1547 if (NT_STATUS_IS_OK(result
) && !domain
->initialized
) {
1548 set_dc_type_and_flags(domain
);
1554 NTSTATUS
init_dc_connection(struct winbindd_domain
*domain
)
1556 if (domain
->initialized
&& !domain
->online
) {
1557 /* We check for online status elsewhere. */
1558 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1561 return init_dc_connection_network(domain
);
1564 /******************************************************************************
1565 We can 'sense' certain things about the DC by it's replies to certain
1568 This tells us if this particular remote server is Active Directory, and if it
1570 ******************************************************************************/
1572 static void set_dc_type_and_flags( struct winbindd_domain
*domain
)
1576 TALLOC_CTX
*mem_ctx
= NULL
;
1577 struct rpc_pipe_client
*cli
;
1580 char *domain_name
= NULL
;
1581 char *dns_name
= NULL
;
1582 char *forest_name
= NULL
;
1583 DOM_SID
*dom_sid
= NULL
;
1587 if (!connection_ok(domain
)) {
1591 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain
->name
));
1593 cli
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
, PI_LSARPC_DS
,
1597 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1598 "PI_LSARPC_DS on domain %s: (%s)\n",
1599 domain
->name
, nt_errstr(result
)));
1601 /* if this is just a non-AD domain we need to continue
1602 * identifying so that we can in the end return with
1603 * domain->initialized = True - gd */
1608 result
= rpccli_ds_getprimarydominfo(cli
, cli
->cli
->mem_ctx
,
1609 DsRolePrimaryDomainInfoBasic
,
1611 cli_rpc_pipe_close(cli
);
1613 if (!NT_STATUS_IS_OK(result
)) {
1614 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1615 "on domain %s failed: (%s)\n",
1616 domain
->name
, nt_errstr(result
)));
1618 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1619 * every opcode on the LSARPC_DS pipe, continue with
1620 * no_lsarpc_ds mode here as well to get domain->initialized
1623 if (NT_STATUS_V(result
) == DCERPC_FAULT_OP_RNG_ERROR
) {
1630 if ((ctr
.basic
->flags
& DSROLE_PRIMARY_DS_RUNNING
) &&
1631 !(ctr
.basic
->flags
& DSROLE_PRIMARY_DS_MIXED_MODE
)) {
1632 domain
->native_mode
= True
;
1634 domain
->native_mode
= False
;
1638 cli
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
, PI_LSARPC
, &result
);
1641 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1642 "PI_LSARPC on domain %s: (%s)\n",
1643 domain
->name
, nt_errstr(result
)));
1644 cli_rpc_pipe_close(cli
);
1648 mem_ctx
= talloc_init("set_dc_type_and_flags on domain %s\n",
1651 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1652 cli_rpc_pipe_close(cli
);
1656 result
= rpccli_lsa_open_policy2(cli
, mem_ctx
, True
,
1657 SEC_RIGHTS_MAXIMUM_ALLOWED
, &pol
);
1659 if (NT_STATUS_IS_OK(result
)) {
1660 /* This particular query is exactly what Win2k clients use
1661 to determine that the DC is active directory */
1662 result
= rpccli_lsa_query_info_policy2(cli
, mem_ctx
, &pol
,
1664 &dns_name
, &forest_name
,
1668 if (NT_STATUS_IS_OK(result
)) {
1669 domain
->active_directory
= True
;
1672 fstrcpy(domain
->name
, domain_name
);
1675 fstrcpy(domain
->alt_name
, dns_name
);
1678 fstrcpy(domain
->forest_name
, forest_name
);
1681 sid_copy(&domain
->sid
, dom_sid
);
1683 domain
->active_directory
= False
;
1685 result
= rpccli_lsa_open_policy(cli
, mem_ctx
, True
,
1686 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1689 if (!NT_STATUS_IS_OK(result
))
1692 result
= rpccli_lsa_query_info_policy(cli
, mem_ctx
,
1693 &pol
, 5, &domain_name
,
1696 if (NT_STATUS_IS_OK(result
)) {
1698 fstrcpy(domain
->name
, domain_name
);
1701 sid_copy(&domain
->sid
, dom_sid
);
1706 DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
1707 domain
->name
, domain
->native_mode
? "" : "NOT "));
1709 DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
1710 domain
->name
, domain
->active_directory
? "" : "NOT "));
1712 cli_rpc_pipe_close(cli
);
1714 talloc_destroy(mem_ctx
);
1716 domain
->initialized
= True
;
1719 static BOOL
cm_get_schannel_dcinfo(struct winbindd_domain
*domain
,
1720 struct dcinfo
**ppdc
)
1723 struct rpc_pipe_client
*netlogon_pipe
;
1725 if (lp_client_schannel() == False
) {
1729 result
= cm_connect_netlogon(domain
, &netlogon_pipe
);
1730 if (!NT_STATUS_IS_OK(result
)) {
1734 /* Return a pointer to the struct dcinfo from the
1737 *ppdc
= domain
->conn
.netlogon_pipe
->dc
;
1741 NTSTATUS
cm_connect_sam(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
1742 struct rpc_pipe_client
**cli
, POLICY_HND
*sam_handle
)
1744 struct winbindd_cm_conn
*conn
;
1745 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1747 struct dcinfo
*p_dcinfo
;
1748 char *machine_password
= NULL
;
1749 char *machine_account
= NULL
;
1750 char *domain_name
= NULL
;
1752 result
= init_dc_connection(domain
);
1753 if (!NT_STATUS_IS_OK(result
)) {
1757 conn
= &domain
->conn
;
1759 if (conn
->samr_pipe
!= NULL
) {
1764 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1765 * sign and sealed pipe using the machine account password by
1766 * preference. If we can't - try schannel, if that fails, try
1770 pwd_get_cleartext(&conn
->cli
->pwd
, conn_pwd
);
1771 if ((conn
->cli
->user_name
[0] == '\0') ||
1772 (conn
->cli
->domain
[0] == '\0') ||
1773 (conn_pwd
[0] == '\0'))
1775 result
= get_trust_creds(domain
, &machine_password
,
1776 &machine_account
, NULL
);
1777 if (!NT_STATUS_IS_OK(result
)) {
1778 DEBUG(10, ("cm_connect_sam: No no user available for "
1779 "domain %s, trying schannel\n", conn
->cli
->domain
));
1782 domain_name
= domain
->name
;
1784 machine_password
= SMB_STRDUP(conn_pwd
);
1785 machine_account
= SMB_STRDUP(conn
->cli
->user_name
);
1786 domain_name
= conn
->cli
->domain
;
1789 if (!machine_password
|| !machine_account
) {
1790 result
= NT_STATUS_NO_MEMORY
;
1794 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1795 authenticated SAMR pipe with sign & seal. */
1797 cli_rpc_pipe_open_spnego_ntlmssp(conn
->cli
, PI_SAMR
,
1798 PIPE_AUTH_LEVEL_PRIVACY
,
1801 machine_password
, &result
);
1803 if (conn
->samr_pipe
== NULL
) {
1804 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1805 "pipe for domain %s using NTLMSSP "
1806 "authenticated pipe: user %s\\%s. Error was "
1807 "%s\n", domain
->name
, domain_name
,
1808 machine_account
, nt_errstr(result
)));
1812 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1813 "domain %s using NTLMSSP authenticated "
1814 "pipe: user %s\\%s\n", domain
->name
,
1815 domain_name
, machine_account
));
1817 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1818 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1819 &conn
->sam_connect_handle
);
1820 if (NT_STATUS_IS_OK(result
)) {
1823 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1824 "failed for domain %s, error was %s. Trying schannel\n",
1825 domain
->name
, nt_errstr(result
) ));
1826 cli_rpc_pipe_close(conn
->samr_pipe
);
1830 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1832 if (!cm_get_schannel_dcinfo(domain
, &p_dcinfo
)) {
1833 /* If this call fails - conn->cli can now be NULL ! */
1834 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1835 "for domain %s, trying anon\n", domain
->name
));
1838 conn
->samr_pipe
= cli_rpc_pipe_open_schannel_with_key
1839 (conn
->cli
, PI_SAMR
, PIPE_AUTH_LEVEL_PRIVACY
,
1840 domain
->name
, p_dcinfo
, &result
);
1842 if (conn
->samr_pipe
== NULL
) {
1843 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1844 "domain %s using schannel. Error was %s\n",
1845 domain
->name
, nt_errstr(result
) ));
1848 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1849 "schannel.\n", domain
->name
));
1851 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1852 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1853 &conn
->sam_connect_handle
);
1854 if (NT_STATUS_IS_OK(result
)) {
1857 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1858 "for domain %s, error was %s. Trying anonymous\n",
1859 domain
->name
, nt_errstr(result
) ));
1860 cli_rpc_pipe_close(conn
->samr_pipe
);
1864 /* Finally fall back to anonymous. */
1865 conn
->samr_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_SAMR
,
1868 if (conn
->samr_pipe
== NULL
) {
1869 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
1873 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1874 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1875 &conn
->sam_connect_handle
);
1876 if (!NT_STATUS_IS_OK(result
)) {
1877 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1878 "for domain %s Error was %s\n",
1879 domain
->name
, nt_errstr(result
) ));
1884 result
= rpccli_samr_open_domain(conn
->samr_pipe
,
1886 &conn
->sam_connect_handle
,
1887 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1889 &conn
->sam_domain_handle
);
1893 if (!NT_STATUS_IS_OK(result
)) {
1894 invalidate_cm_connection(conn
);
1898 *cli
= conn
->samr_pipe
;
1899 *sam_handle
= conn
->sam_domain_handle
;
1900 SAFE_FREE(machine_password
);
1901 SAFE_FREE(machine_account
);
1905 NTSTATUS
cm_connect_lsa(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
1906 struct rpc_pipe_client
**cli
, POLICY_HND
*lsa_policy
)
1908 struct winbindd_cm_conn
*conn
;
1909 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1911 struct dcinfo
*p_dcinfo
;
1913 result
= init_dc_connection(domain
);
1914 if (!NT_STATUS_IS_OK(result
))
1917 conn
= &domain
->conn
;
1919 if (conn
->lsa_pipe
!= NULL
) {
1923 pwd_get_cleartext(&conn
->cli
->pwd
, conn_pwd
);
1924 if ((conn
->cli
->user_name
[0] == '\0') ||
1925 (conn
->cli
->domain
[0] == '\0') ||
1926 (conn_pwd
[0] == '\0')) {
1927 DEBUG(10, ("cm_connect_lsa: No no user available for "
1928 "domain %s, trying schannel\n", conn
->cli
->domain
));
1932 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1933 * authenticated LSA pipe with sign & seal. */
1934 conn
->lsa_pipe
= cli_rpc_pipe_open_spnego_ntlmssp
1935 (conn
->cli
, PI_LSARPC
, PIPE_AUTH_LEVEL_PRIVACY
,
1936 conn
->cli
->domain
, conn
->cli
->user_name
, conn_pwd
, &result
);
1938 if (conn
->lsa_pipe
== NULL
) {
1939 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1940 "domain %s using NTLMSSP authenticated pipe: user "
1941 "%s\\%s. Error was %s. Trying schannel.\n",
1942 domain
->name
, conn
->cli
->domain
,
1943 conn
->cli
->user_name
, nt_errstr(result
)));
1947 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1948 "NTLMSSP authenticated pipe: user %s\\%s\n",
1949 domain
->name
, conn
->cli
->domain
, conn
->cli
->user_name
));
1951 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
1952 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1954 if (NT_STATUS_IS_OK(result
)) {
1958 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1961 cli_rpc_pipe_close(conn
->lsa_pipe
);
1965 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1967 if (!cm_get_schannel_dcinfo(domain
, &p_dcinfo
)) {
1968 /* If this call fails - conn->cli can now be NULL ! */
1969 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1970 "for domain %s, trying anon\n", domain
->name
));
1973 conn
->lsa_pipe
= cli_rpc_pipe_open_schannel_with_key
1974 (conn
->cli
, PI_LSARPC
, PIPE_AUTH_LEVEL_PRIVACY
,
1975 domain
->name
, p_dcinfo
, &result
);
1977 if (conn
->lsa_pipe
== NULL
) {
1978 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1979 "domain %s using schannel. Error was %s\n",
1980 domain
->name
, nt_errstr(result
) ));
1983 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1984 "schannel.\n", domain
->name
));
1986 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
1987 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1989 if (NT_STATUS_IS_OK(result
)) {
1993 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1996 cli_rpc_pipe_close(conn
->lsa_pipe
);
2000 conn
->lsa_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_LSARPC
,
2002 if (conn
->lsa_pipe
== NULL
) {
2003 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
2007 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2008 SEC_RIGHTS_MAXIMUM_ALLOWED
,
2011 if (!NT_STATUS_IS_OK(result
)) {
2012 invalidate_cm_connection(conn
);
2016 *cli
= conn
->lsa_pipe
;
2017 *lsa_policy
= conn
->lsa_policy
;
2021 /****************************************************************************
2022 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2023 session key stored in conn->netlogon_pipe->dc->sess_key.
2024 ****************************************************************************/
2026 NTSTATUS
cm_connect_netlogon(struct winbindd_domain
*domain
,
2027 struct rpc_pipe_client
**cli
)
2029 struct winbindd_cm_conn
*conn
;
2032 uint32 neg_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
2034 uint32 sec_chan_type
;
2035 const char *account_name
;
2036 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
2040 result
= init_dc_connection(domain
);
2041 if (!NT_STATUS_IS_OK(result
)) {
2045 conn
= &domain
->conn
;
2047 if (conn
->netlogon_pipe
!= NULL
) {
2048 *cli
= conn
->netlogon_pipe
;
2049 return NT_STATUS_OK
;
2052 netlogon_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_NETLOGON
,
2054 if (netlogon_pipe
== NULL
) {
2058 if ((!IS_DC
) && (!domain
->primary
)) {
2059 /* Clear the schannel request bit and drop down */
2060 neg_flags
&= ~NETLOGON_NEG_SCHANNEL
;
2064 if (lp_client_schannel() != False
) {
2065 neg_flags
|= NETLOGON_NEG_SCHANNEL
;
2068 if (!get_trust_pw_hash(domain
->name
, mach_pwd
, &account_name
,
2071 cli_rpc_pipe_close(netlogon_pipe
);
2072 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2075 result
= rpccli_netlogon_setup_creds(
2077 domain
->dcname
, /* server name. */
2078 domain
->name
, /* domain name */
2079 global_myname(), /* client name */
2080 account_name
, /* machine account */
2081 mach_pwd
, /* machine password */
2082 sec_chan_type
, /* from get_trust_pw */
2085 if (!NT_STATUS_IS_OK(result
)) {
2086 cli_rpc_pipe_close(netlogon_pipe
);
2090 if ((lp_client_schannel() == True
) &&
2091 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2092 DEBUG(3, ("Server did not offer schannel\n"));
2093 cli_rpc_pipe_close(netlogon_pipe
);
2094 return NT_STATUS_ACCESS_DENIED
;
2098 if ((lp_client_schannel() == False
) ||
2099 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2100 /* We're done - just keep the existing connection to NETLOGON
2102 conn
->netlogon_pipe
= netlogon_pipe
;
2103 *cli
= conn
->netlogon_pipe
;
2104 return NT_STATUS_OK
;
2107 /* Using the credentials from the first pipe, open a signed and sealed
2108 second netlogon pipe. The session key is stored in the schannel
2109 part of the new pipe auth struct.
2112 conn
->netlogon_pipe
=
2113 cli_rpc_pipe_open_schannel_with_key(conn
->cli
,
2115 PIPE_AUTH_LEVEL_PRIVACY
,
2120 /* We can now close the initial netlogon pipe. */
2121 cli_rpc_pipe_close(netlogon_pipe
);
2123 if (conn
->netlogon_pipe
== NULL
) {
2124 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2125 "was %s\n", nt_errstr(result
)));
2127 /* make sure we return something besides OK */
2128 return !NT_STATUS_IS_OK(result
) ? result
: NT_STATUS_PIPE_NOT_AVAILABLE
;
2131 *cli
= conn
->netlogon_pipe
;
2132 return NT_STATUS_OK
;