2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
63 #include "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "libsmb/libsmb.h"
73 #include "libsmb/clidgram.h"
76 #include "../libcli/security/security.h"
79 #include "auth/gensec/gensec.h"
80 #include "../libcli/smb/smbXcli_base.h"
81 #include "lib/param/loadparm.h"
84 #define DBGC_CLASS DBGC_WINBIND
88 struct sockaddr_storage ss
;
91 extern struct winbindd_methods reconnect_methods
;
92 extern bool override_logfile
;
94 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
);
95 static void set_dc_type_and_flags( struct winbindd_domain
*domain
);
96 static bool get_dcs(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
97 struct dc_name_ip
**dcs
, int *num_dcs
);
99 /****************************************************************
100 Child failed to find DC's. Reschedule check.
101 ****************************************************************/
103 static void msg_failed_to_go_online(struct messaging_context
*msg
,
106 struct server_id server_id
,
109 struct winbindd_domain
*domain
;
110 const char *domainname
= (const char *)data
->data
;
112 if (data
->data
== NULL
|| data
->length
== 0) {
116 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname
));
118 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
119 if (domain
->internal
) {
123 if (strequal(domain
->name
, domainname
)) {
124 if (domain
->online
) {
125 /* We're already online, ignore. */
126 DEBUG(5,("msg_fail_to_go_online: domain %s "
127 "already online.\n", domainname
));
131 /* Reschedule the online check. */
132 set_domain_offline(domain
);
138 /****************************************************************
139 Actually cause a reconnect from a message.
140 ****************************************************************/
142 static void msg_try_to_go_online(struct messaging_context
*msg
,
145 struct server_id server_id
,
148 struct winbindd_domain
*domain
;
149 const char *domainname
= (const char *)data
->data
;
151 if (data
->data
== NULL
|| data
->length
== 0) {
155 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname
));
157 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
158 if (domain
->internal
) {
162 if (strequal(domain
->name
, domainname
)) {
164 if (domain
->online
) {
165 /* We're already online, ignore. */
166 DEBUG(5,("msg_try_to_go_online: domain %s "
167 "already online.\n", domainname
));
171 /* This call takes care of setting the online
172 flag to true if we connected, or re-adding
173 the offline handler if false. Bypasses online
174 check so always does network calls. */
176 init_dc_connection_network(domain
);
182 /****************************************************************
183 Fork a child to try and contact a DC. Do this as contacting a
184 DC requires blocking lookups and we don't want to block our
186 ****************************************************************/
188 static bool fork_child_dc_connect(struct winbindd_domain
*domain
)
190 struct dc_name_ip
*dcs
= NULL
;
192 TALLOC_CTX
*mem_ctx
= NULL
;
193 pid_t parent_pid
= getpid();
197 if (domain
->dc_probe_pid
!= (pid_t
)-1) {
199 * We might already have a DC probe
200 * child working, check.
202 if (process_exists_by_pid(domain
->dc_probe_pid
)) {
203 DEBUG(10,("fork_child_dc_connect: pid %u already "
204 "checking for DC's.\n",
205 (unsigned int)domain
->dc_probe_pid
));
208 domain
->dc_probe_pid
= (pid_t
)-1;
211 domain
->dc_probe_pid
= fork();
213 if (domain
->dc_probe_pid
== (pid_t
)-1) {
214 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno
)));
218 if (domain
->dc_probe_pid
!= (pid_t
)0) {
220 messaging_register(winbind_messaging_context(), NULL
,
221 MSG_WINBIND_TRY_TO_GO_ONLINE
,
222 msg_try_to_go_online
);
223 messaging_register(winbind_messaging_context(), NULL
,
224 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
225 msg_failed_to_go_online
);
231 /* Leave messages blocked - we will never process one. */
233 if (!override_logfile
) {
234 if (asprintf(&lfile
, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
235 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
240 status
= winbindd_reinit_after_fork(NULL
, lfile
);
241 if (!NT_STATUS_IS_OK(status
)) {
242 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
244 messaging_send_buf(winbind_messaging_context(),
245 pid_to_procid(parent_pid
),
246 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
247 (const uint8_t *)domain
->name
,
248 strlen(domain
->name
)+1);
253 mem_ctx
= talloc_init("fork_child_dc_connect");
255 DEBUG(0,("talloc_init failed.\n"));
256 messaging_send_buf(winbind_messaging_context(),
257 pid_to_procid(parent_pid
),
258 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
259 (const uint8_t *)domain
->name
,
260 strlen(domain
->name
)+1);
264 if ((!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
)) || (num_dcs
== 0)) {
265 /* Still offline ? Can't find DC's. */
266 messaging_send_buf(winbind_messaging_context(),
267 pid_to_procid(parent_pid
),
268 MSG_WINBIND_FAILED_TO_GO_ONLINE
,
269 (const uint8_t *)domain
->name
,
270 strlen(domain
->name
)+1);
274 /* We got a DC. Send a message to our parent to get it to
275 try and do the same. */
277 messaging_send_buf(winbind_messaging_context(),
278 pid_to_procid(parent_pid
),
279 MSG_WINBIND_TRY_TO_GO_ONLINE
,
280 (const uint8_t *)domain
->name
,
281 strlen(domain
->name
)+1);
285 /****************************************************************
286 Handler triggered if we're offline to try and detect a DC.
287 ****************************************************************/
289 static void check_domain_online_handler(struct tevent_context
*ctx
,
290 struct tevent_timer
*te
,
294 struct winbindd_domain
*domain
=
295 (struct winbindd_domain
*)private_data
;
297 DEBUG(10,("check_domain_online_handler: called for domain "
298 "%s (online = %s)\n", domain
->name
,
299 domain
->online
? "True" : "False" ));
301 TALLOC_FREE(domain
->check_online_event
);
303 /* Are we still in "startup" mode ? */
305 if (domain
->startup
&& (time_mono(NULL
) > domain
->startup_time
+ 30)) {
306 /* No longer in "startup" mode. */
307 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
309 domain
->startup
= False
;
312 /* We've been told to stay offline, so stay
315 if (get_global_winbindd_state_offline()) {
316 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
321 /* Fork a child to test if it can contact a DC.
322 If it can then send ourselves a message to
323 cause a reconnect. */
325 fork_child_dc_connect(domain
);
328 /****************************************************************
329 If we're still offline setup the timeout check.
330 ****************************************************************/
332 static void calc_new_online_timeout_check(struct winbindd_domain
*domain
)
334 int wbr
= lp_winbind_reconnect_delay();
336 if (domain
->startup
) {
337 domain
->check_online_timeout
= 10;
338 } else if (domain
->check_online_timeout
< wbr
) {
339 domain
->check_online_timeout
= wbr
;
343 void winbind_msg_domain_offline(struct messaging_context
*msg_ctx
,
346 struct server_id server_id
,
349 const char *domain_name
= (const char *)data
->data
;
350 struct winbindd_domain
*domain
;
352 domain
= find_domain_from_name_noinit(domain_name
);
353 if (domain
== NULL
) {
357 domain
->online
= false;
359 DEBUG(10, ("Domain %s is marked as offline now.\n",
363 void winbind_msg_domain_online(struct messaging_context
*msg_ctx
,
366 struct server_id server_id
,
369 const char *domain_name
= (const char *)data
->data
;
370 struct winbindd_domain
*domain
;
372 domain
= find_domain_from_name_noinit(domain_name
);
373 if (domain
== NULL
) {
377 domain
->online
= true;
379 DEBUG(10, ("Domain %s is marked as online now.\n",
383 /****************************************************************
384 Set domain offline and also add handler to put us back online
386 ****************************************************************/
388 void set_domain_offline(struct winbindd_domain
*domain
)
390 DEBUG(10,("set_domain_offline: called for domain %s\n",
393 TALLOC_FREE(domain
->check_online_event
);
395 if (domain
->internal
) {
396 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
401 domain
->online
= False
;
403 /* Offline domains are always initialized. They're
404 re-initialized when they go back online. */
406 domain
->initialized
= True
;
408 /* We only add the timeout handler that checks and
409 allows us to go back online when we've not
410 been told to remain offline. */
412 if (get_global_winbindd_state_offline()) {
413 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
418 /* If we're in startup mode, check again in 10 seconds, not in
419 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
421 calc_new_online_timeout_check(domain
);
423 domain
->check_online_event
= tevent_add_timer(winbind_event_context(),
425 timeval_current_ofs(domain
->check_online_timeout
,0),
426 check_domain_online_handler
,
429 /* The above *has* to succeed for winbindd to work. */
430 if (!domain
->check_online_event
) {
431 smb_panic("set_domain_offline: failed to add online handler");
434 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
437 /* Send an offline message to the idmap child when our
438 primary domain goes offline */
440 if ( domain
->primary
) {
441 struct winbindd_child
*idmap
= idmap_child();
443 if ( idmap
->pid
!= 0 ) {
444 messaging_send_buf(winbind_messaging_context(),
445 pid_to_procid(idmap
->pid
),
447 (const uint8_t *)domain
->name
,
448 strlen(domain
->name
)+1);
455 /****************************************************************
456 Set domain online - if allowed.
457 ****************************************************************/
459 static void set_domain_online(struct winbindd_domain
*domain
)
461 DEBUG(10,("set_domain_online: called for domain %s\n",
464 if (domain
->internal
) {
465 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
470 if (get_global_winbindd_state_offline()) {
471 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
476 winbindd_set_locator_kdc_envs(domain
);
478 /* If we are waiting to get a krb5 ticket, trigger immediately. */
479 ccache_regain_all_now();
481 /* Ok, we're out of any startup mode now... */
482 domain
->startup
= False
;
484 if (domain
->online
== False
) {
485 /* We were offline - now we're online. We default to
486 using the MS-RPC backend if we started offline,
487 and if we're going online for the first time we
488 should really re-initialize the backends and the
489 checks to see if we're talking to an AD or NT domain.
492 domain
->initialized
= False
;
494 /* 'reconnect_methods' is the MS-RPC backend. */
495 if (domain
->backend
== &reconnect_methods
) {
496 domain
->backend
= NULL
;
500 /* Ensure we have no online timeout checks. */
501 domain
->check_online_timeout
= 0;
502 TALLOC_FREE(domain
->check_online_event
);
504 /* Ensure we ignore any pending child messages. */
505 messaging_deregister(winbind_messaging_context(),
506 MSG_WINBIND_TRY_TO_GO_ONLINE
, NULL
);
507 messaging_deregister(winbind_messaging_context(),
508 MSG_WINBIND_FAILED_TO_GO_ONLINE
, NULL
);
510 domain
->online
= True
;
512 /* Send an online message to the idmap child when our
513 primary domain comes online */
515 if ( domain
->primary
) {
516 struct winbindd_child
*idmap
= idmap_child();
518 if ( idmap
->pid
!= 0 ) {
519 messaging_send_buf(winbind_messaging_context(),
520 pid_to_procid(idmap
->pid
),
522 (const uint8_t *)domain
->name
,
523 strlen(domain
->name
)+1);
530 /****************************************************************
531 Requested to set a domain online.
532 ****************************************************************/
534 void set_domain_online_request(struct winbindd_domain
*domain
)
538 DEBUG(10,("set_domain_online_request: called for domain %s\n",
541 if (get_global_winbindd_state_offline()) {
542 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
547 if (domain
->internal
) {
548 DEBUG(10, ("set_domain_online_request: Internal domains are "
553 /* We've been told it's safe to go online and
554 try and connect to a DC. But I don't believe it
555 because network manager seems to lie.
556 Wait at least 5 seconds. Heuristics suck... */
561 /* Go into "startup" mode again. */
562 domain
->startup_time
= time_mono(NULL
);
563 domain
->startup
= True
;
567 if (!domain
->check_online_event
) {
568 /* If we've come from being globally offline we
569 don't have a check online event handler set.
570 We need to add one now we're trying to go
573 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
577 TALLOC_FREE(domain
->check_online_event
);
579 domain
->check_online_event
= tevent_add_timer(winbind_event_context(),
582 check_domain_online_handler
,
585 /* The above *has* to succeed for winbindd to work. */
586 if (!domain
->check_online_event
) {
587 smb_panic("set_domain_online_request: failed to add online handler");
591 /****************************************************************
592 Add -ve connection cache entries for domain and realm.
593 ****************************************************************/
595 static void winbind_add_failed_connection_entry(
596 const struct winbindd_domain
*domain
,
600 add_failed_connection_entry(domain
->name
, server
, result
);
601 /* If this was the saf name for the last thing we talked to,
603 saf_delete(domain
->name
);
604 if (domain
->alt_name
!= NULL
) {
605 add_failed_connection_entry(domain
->alt_name
, server
, result
);
606 saf_delete(domain
->alt_name
);
608 winbindd_unset_locator_kdc_env(domain
);
611 /* Choose between anonymous or authenticated connections. We need to use
612 an authenticated connection if DCs have the RestrictAnonymous registry
613 entry set > 0, or the "Additional restrictions for anonymous
614 connections" set in the win2k Local Security Policy.
616 Caller to free() result in domain, username, password
619 static void cm_get_ipc_userpass(char **username
, char **domain
, char **password
)
621 *username
= (char *)secrets_fetch(SECRETS_AUTH_USER
, NULL
);
622 *domain
= (char *)secrets_fetch(SECRETS_AUTH_DOMAIN
, NULL
);
623 *password
= (char *)secrets_fetch(SECRETS_AUTH_PASSWORD
, NULL
);
625 if (*username
&& **username
) {
627 if (!*domain
|| !**domain
)
628 *domain
= smb_xstrdup(lp_workgroup());
630 if (!*password
|| !**password
)
631 *password
= smb_xstrdup("");
633 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
634 *domain
, *username
));
637 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
638 *username
= smb_xstrdup("");
639 *domain
= smb_xstrdup("");
640 *password
= smb_xstrdup("");
644 static bool get_dc_name_via_netlogon(struct winbindd_domain
*domain
,
646 struct sockaddr_storage
*dc_ss
)
648 struct winbindd_domain
*our_domain
= NULL
;
649 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
653 unsigned int orig_timeout
;
654 const char *tmp
= NULL
;
656 struct dcerpc_binding_handle
*b
;
658 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
665 if (domain
->primary
) {
669 our_domain
= find_our_domain();
671 if ((mem_ctx
= talloc_init("get_dc_name_via_netlogon")) == NULL
) {
675 result
= cm_connect_netlogon(our_domain
, &netlogon_pipe
);
676 if (!NT_STATUS_IS_OK(result
)) {
677 talloc_destroy(mem_ctx
);
681 b
= netlogon_pipe
->binding_handle
;
683 /* This call can take a long time - allow the server to time out.
684 35 seconds should do it. */
686 orig_timeout
= rpccli_set_timeout(netlogon_pipe
, 35000);
688 if (our_domain
->active_directory
) {
689 struct netr_DsRGetDCNameInfo
*domain_info
= NULL
;
691 result
= dcerpc_netr_DsRGetDCName(b
,
700 if (NT_STATUS_IS_OK(result
) && W_ERROR_IS_OK(werr
)) {
702 mem_ctx
, domain_info
->dc_unc
);
704 DEBUG(0, ("talloc_strdup failed\n"));
705 talloc_destroy(mem_ctx
);
708 if (domain
->alt_name
== NULL
) {
709 domain
->alt_name
= talloc_strdup(domain
,
710 domain_info
->domain_name
);
711 if (domain
->alt_name
== NULL
) {
712 DEBUG(0, ("talloc_strdup failed\n"));
713 talloc_destroy(mem_ctx
);
717 if (domain
->forest_name
== NULL
) {
718 domain
->forest_name
= talloc_strdup(domain
,
719 domain_info
->forest_name
);
720 if (domain
->forest_name
== NULL
) {
721 DEBUG(0, ("talloc_strdup failed\n"));
722 talloc_destroy(mem_ctx
);
728 result
= dcerpc_netr_GetAnyDCName(b
, mem_ctx
,
735 /* And restore our original timeout. */
736 rpccli_set_timeout(netlogon_pipe
, orig_timeout
);
738 if (!NT_STATUS_IS_OK(result
)) {
739 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
741 talloc_destroy(mem_ctx
);
745 if (!W_ERROR_IS_OK(werr
)) {
746 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
748 talloc_destroy(mem_ctx
);
752 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
753 p
= strip_hostname(tmp
);
757 talloc_destroy(mem_ctx
);
759 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname
));
761 if (!resolve_name(dcname
, dc_ss
, 0x20, true)) {
769 * Helper function to assemble trust password and account name
771 static NTSTATUS
get_trust_creds(const struct winbindd_domain
*domain
,
772 char **machine_password
,
773 char **machine_account
,
774 char **machine_krb5_principal
)
776 const char *account_name
;
777 const char *name
= NULL
;
779 /* If we are a DC and this is not our own domain */
784 struct winbindd_domain
*our_domain
= find_our_domain();
787 return NT_STATUS_INVALID_SERVER_STATE
;
789 name
= our_domain
->name
;
792 if (!get_trust_pw_clear(name
, machine_password
,
793 &account_name
, NULL
))
795 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
798 if ((machine_account
!= NULL
) &&
799 (asprintf(machine_account
, "%s$", account_name
) == -1))
801 return NT_STATUS_NO_MEMORY
;
804 /* For now assume our machine account only exists in our domain */
806 if (machine_krb5_principal
!= NULL
)
808 struct winbindd_domain
*our_domain
= find_our_domain();
811 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
814 if (asprintf(machine_krb5_principal
, "%s$@%s",
815 account_name
, our_domain
->alt_name
) == -1)
817 return NT_STATUS_NO_MEMORY
;
820 if (!strupper_m(*machine_krb5_principal
)) {
821 SAFE_FREE(*machine_krb5_principal
);
822 return NT_STATUS_INVALID_PARAMETER
;
829 /************************************************************************
830 Given a fd with a just-connected TCP connection to a DC, open a connection
832 ************************************************************************/
834 static NTSTATUS
cm_prepare_connection(const struct winbindd_domain
*domain
,
836 const char *controller
,
837 struct cli_state
**cli
,
840 bool try_spnego
= false;
841 bool try_ipc_auth
= false;
842 char *machine_password
= NULL
;
843 char *machine_krb5_principal
= NULL
;
844 char *machine_account
= NULL
;
845 char *ipc_username
= NULL
;
846 char *ipc_domain
= NULL
;
847 char *ipc_password
= NULL
;
849 uint16_t sec_mode
= 0;
851 struct named_mutex
*mutex
;
853 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
855 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
856 controller
, domain
->name
));
860 mutex
= grab_named_mutex(talloc_tos(), controller
,
861 WINBIND_SERVER_MUTEX_WAIT_TIME
);
864 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
866 result
= NT_STATUS_POSSIBLE_DEADLOCK
;
870 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
872 *cli
= cli_state_create(NULL
, sockfd
,
873 controller
, domain
->alt_name
,
874 SMB_SIGNING_DEFAULT
, flags
);
877 DEBUG(1, ("Could not cli_initialize\n"));
878 result
= NT_STATUS_NO_MEMORY
;
882 cli_set_timeout(*cli
, 10000); /* 10 seconds */
884 result
= smbXcli_negprot((*cli
)->conn
, (*cli
)->timeout
,
885 lp_cli_minprotocol(),
886 lp_cli_maxprotocol());
888 if (!NT_STATUS_IS_OK(result
)) {
889 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result
)));
893 if (smbXcli_conn_protocol((*cli
)->conn
) >= PROTOCOL_NT1
&&
894 smb1cli_conn_capabilities((*cli
)->conn
) & CAP_EXTENDED_SECURITY
) {
896 } else if (smbXcli_conn_protocol((*cli
)->conn
) >= PROTOCOL_SMB2_02
) {
900 if (!is_dc_trusted_domain_situation(domain
->name
) && try_spnego
) {
901 result
= get_trust_creds(domain
, &machine_password
,
903 &machine_krb5_principal
);
904 if (!NT_STATUS_IS_OK(result
)) {
908 if (lp_security() == SEC_ADS
) {
910 /* Try a krb5 session */
912 (*cli
)->use_kerberos
= True
;
913 DEBUG(5, ("connecting to %s from %s with kerberos principal "
914 "[%s] and realm [%s]\n", controller
, lp_netbios_name(),
915 machine_krb5_principal
, domain
->alt_name
));
917 winbindd_set_locator_kdc_envs(domain
);
919 result
= cli_session_setup(*cli
,
920 machine_krb5_principal
,
922 strlen(machine_password
)+1,
924 strlen(machine_password
)+1,
927 if (!NT_STATUS_IS_OK(result
)) {
928 DEBUG(4,("failed kerberos session setup with %s\n",
932 if (NT_STATUS_IS_OK(result
)) {
933 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
934 result
= cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
935 if (!NT_STATUS_IS_OK(result
)) {
938 goto session_setup_done
;
942 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
943 (*cli
)->use_kerberos
= False
;
945 DEBUG(5, ("connecting to %s from %s with username "
946 "[%s]\\[%s]\n", controller
, lp_netbios_name(),
947 lp_workgroup(), machine_account
));
949 result
= cli_session_setup(*cli
,
952 strlen(machine_password
)+1,
954 strlen(machine_password
)+1,
956 if (!NT_STATUS_IS_OK(result
)) {
957 DEBUG(4, ("authenticated session setup failed with %s\n",
961 if (NT_STATUS_IS_OK(result
)) {
962 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
963 result
= cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
964 if (!NT_STATUS_IS_OK(result
)) {
967 goto session_setup_done
;
971 /* Fall back to non-kerberos session setup with auth_user */
973 (*cli
)->use_kerberos
= False
;
975 cm_get_ipc_userpass(&ipc_username
, &ipc_domain
, &ipc_password
);
977 sec_mode
= smb1cli_conn_server_security_mode((*cli
)->conn
);
979 try_ipc_auth
= false;
982 } else if (sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) {
986 if (try_ipc_auth
&& (strlen(ipc_username
) > 0)) {
988 /* Only try authenticated if we have a username */
990 DEBUG(5, ("connecting to %s from %s with username "
991 "[%s]\\[%s]\n", controller
, lp_netbios_name(),
992 ipc_domain
, ipc_username
));
994 if (NT_STATUS_IS_OK(cli_session_setup(
996 ipc_password
, strlen(ipc_password
)+1,
997 ipc_password
, strlen(ipc_password
)+1,
999 /* Successful logon with given username. */
1000 result
= cli_init_creds(*cli
, ipc_username
, ipc_domain
, ipc_password
);
1001 if (!NT_STATUS_IS_OK(result
)) {
1004 goto session_setup_done
;
1006 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
1007 ipc_domain
, ipc_username
));
1013 /* Fall back to anonymous connection, this might fail later */
1014 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
1015 "connection for DC %s\n",
1018 result
= cli_session_setup(*cli
, "", NULL
, 0, NULL
, 0, "");
1019 if (NT_STATUS_IS_OK(result
)) {
1020 DEBUG(5, ("Connected anonymously\n"));
1021 result
= cli_init_creds(*cli
, "", "", "");
1022 if (!NT_STATUS_IS_OK(result
)) {
1025 goto session_setup_done
;
1028 /* We can't session setup */
1034 * This should be a short term hack until
1035 * dynamic re-authentication is implemented.
1037 * See Bug 9175 - winbindd doesn't recover from
1038 * NT_STATUS_NETWORK_SESSION_EXPIRED
1040 if (smbXcli_conn_protocol((*cli
)->conn
) >= PROTOCOL_SMB2_02
) {
1041 smbXcli_session_set_disconnect_expired((*cli
)->smb2
.session
);
1044 /* cache the server name for later connections */
1046 saf_store(domain
->name
, controller
);
1047 if (domain
->alt_name
&& (*cli
)->use_kerberos
) {
1048 saf_store(domain
->alt_name
, controller
);
1051 winbindd_set_locator_kdc_envs(domain
);
1053 result
= cli_tree_connect(*cli
, "IPC$", "IPC", "", 0);
1055 if (!NT_STATUS_IS_OK(result
)) {
1056 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result
)));
1063 /* set the domain if empty; needed for schannel connections */
1064 if ( !(*cli
)->domain
[0] ) {
1065 result
= cli_set_domain((*cli
), domain
->name
);
1066 if (!NT_STATUS_IS_OK(result
)) {
1067 SAFE_FREE(ipc_username
);
1068 SAFE_FREE(ipc_domain
);
1069 SAFE_FREE(ipc_password
);
1074 result
= NT_STATUS_OK
;
1078 SAFE_FREE(machine_account
);
1079 SAFE_FREE(machine_password
);
1080 SAFE_FREE(machine_krb5_principal
);
1081 SAFE_FREE(ipc_username
);
1082 SAFE_FREE(ipc_domain
);
1083 SAFE_FREE(ipc_password
);
1085 if (!NT_STATUS_IS_OK(result
)) {
1086 winbind_add_failed_connection_entry(domain
, controller
, result
);
1087 if ((*cli
) != NULL
) {
1096 /*******************************************************************
1097 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1100 Keeps the list unique by not adding duplicate entries.
1102 @param[in] mem_ctx talloc memory context to allocate from
1103 @param[in] domain_name domain of the DC
1104 @param[in] dcname name of the DC to add to the list
1105 @param[in] pss Internet address and port pair to add to the list
1106 @param[in,out] dcs array of dc_name_ip structures to add to
1107 @param[in,out] num_dcs number of dcs returned in the dcs array
1108 @return true if the list was added to, false otherwise
1109 *******************************************************************/
1111 static bool add_one_dc_unique(TALLOC_CTX
*mem_ctx
, const char *domain_name
,
1112 const char *dcname
, struct sockaddr_storage
*pss
,
1113 struct dc_name_ip
**dcs
, int *num
)
1117 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name
, dcname
))) {
1118 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname
));
1122 /* Make sure there's no duplicates in the list */
1123 for (i
=0; i
<*num
; i
++)
1125 (struct sockaddr
*)(void *)&(*dcs
)[i
].ss
,
1126 (struct sockaddr
*)(void *)pss
))
1129 *dcs
= talloc_realloc(mem_ctx
, *dcs
, struct dc_name_ip
, (*num
)+1);
1134 fstrcpy((*dcs
)[*num
].name
, dcname
);
1135 (*dcs
)[*num
].ss
= *pss
;
1140 static bool add_sockaddr_to_array(TALLOC_CTX
*mem_ctx
,
1141 struct sockaddr_storage
*pss
, uint16 port
,
1142 struct sockaddr_storage
**addrs
, int *num
)
1144 *addrs
= talloc_realloc(mem_ctx
, *addrs
, struct sockaddr_storage
, (*num
)+1);
1146 if (*addrs
== NULL
) {
1151 (*addrs
)[*num
] = *pss
;
1152 set_sockaddr_port((struct sockaddr
*)&(*addrs
)[*num
], port
);
1158 /*******************************************************************
1159 convert an ip to a name
1160 *******************************************************************/
1162 static bool dcip_to_name(TALLOC_CTX
*mem_ctx
,
1163 const struct winbindd_domain
*domain
,
1164 struct sockaddr_storage
*pss
,
1167 struct ip_service ip_list
;
1168 uint32_t nt_version
= NETLOGON_NT_VERSION_1
;
1170 const char *dc_name
;
1177 /* For active directory servers, try to get the ldap server name.
1178 None of these failures should be considered critical for now */
1180 if (lp_security() == SEC_ADS
) {
1182 ADS_STATUS ads_status
;
1183 char addr
[INET6_ADDRSTRLEN
];
1185 print_sockaddr(addr
, sizeof(addr
), pss
);
1187 ads
= ads_init(domain
->alt_name
, domain
->name
, addr
);
1188 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
1190 ads_status
= ads_connect(ads
);
1191 if (ADS_ERR_OK(ads_status
)) {
1192 /* We got a cldap packet. */
1193 *name
= talloc_strdup(mem_ctx
,
1194 ads
->config
.ldap_server_name
);
1195 if (*name
== NULL
) {
1198 namecache_store(*name
, 0x20, 1, &ip_list
);
1200 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads
->config
.flags
));
1202 if (domain
->primary
&& (ads
->config
.flags
& NBT_SERVER_KDC
)) {
1203 if (ads_closest_dc(ads
)) {
1204 char *sitename
= sitename_fetch(mem_ctx
, ads
->config
.realm
);
1206 /* We're going to use this KDC for this realm/domain.
1207 If we are using sites, then force the krb5 libs
1210 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1216 TALLOC_FREE(sitename
);
1218 /* use an off site KDC */
1219 create_local_private_krb5_conf_for_domain(domain
->alt_name
,
1225 winbindd_set_locator_kdc_envs(domain
);
1227 /* Ensure we contact this DC also. */
1228 saf_store(domain
->name
, *name
);
1229 saf_store(domain
->alt_name
, *name
);
1232 ads_destroy( &ads
);
1236 ads_destroy( &ads
);
1241 status
= nbt_getdc(winbind_messaging_context(), 10, pss
, domain
->name
,
1242 &domain
->sid
, nt_version
, mem_ctx
, &nt_version
,
1244 if (NT_STATUS_IS_OK(status
)) {
1245 *name
= talloc_strdup(mem_ctx
, dc_name
);
1246 if (*name
== NULL
) {
1249 namecache_store(*name
, 0x20, 1, &ip_list
);
1253 /* try node status request */
1255 if (name_status_find(domain
->name
, 0x1c, 0x20, pss
, nbtname
) ) {
1256 namecache_store(nbtname
, 0x20, 1, &ip_list
);
1259 *name
= talloc_strdup(mem_ctx
, nbtname
);
1260 if (*name
== NULL
) {
1270 /*******************************************************************
1271 Retrieve a list of IP addresses for domain controllers.
1273 The array is sorted in the preferred connection order.
1275 @param[in] mem_ctx talloc memory context to allocate from
1276 @param[in] domain domain to retrieve DCs for
1277 @param[out] dcs array of dcs that will be returned
1278 @param[out] num_dcs number of dcs returned in the dcs array
1280 *******************************************************************/
1282 static bool get_dcs(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
1283 struct dc_name_ip
**dcs
, int *num_dcs
)
1286 struct sockaddr_storage ss
;
1287 struct ip_service
*ip_list
= NULL
;
1288 int iplist_size
= 0;
1291 enum security_types sec
= (enum security_types
)lp_security();
1293 is_our_domain
= strequal(domain
->name
, lp_workgroup());
1295 /* If not our domain, get the preferred DC, by asking our primary DC */
1297 && get_dc_name_via_netlogon(domain
, dcname
, &ss
)
1298 && add_one_dc_unique(mem_ctx
, domain
->name
, dcname
, &ss
, dcs
,
1301 char addr
[INET6_ADDRSTRLEN
];
1302 print_sockaddr(addr
, sizeof(addr
), &ss
);
1303 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1308 if (sec
== SEC_ADS
) {
1309 char *sitename
= NULL
;
1311 /* We need to make sure we know the local site before
1312 doing any DNS queries, as this will restrict the
1313 get_sorted_dc_list() call below to only fetching
1314 DNS records for the correct site. */
1316 /* Find any DC to get the site record.
1317 We deliberately don't care about the
1320 get_dc_name(domain
->name
, domain
->alt_name
, dcname
, &ss
);
1322 sitename
= sitename_fetch(mem_ctx
, domain
->alt_name
);
1325 /* Do the site-specific AD dns lookup first. */
1326 get_sorted_dc_list(domain
->alt_name
, sitename
, &ip_list
,
1327 &iplist_size
, True
);
1329 /* Add ips to the DC array. We don't look up the name
1330 of the DC in this function, but we fill in the char*
1331 of the ip now to make the failed connection cache
1333 for ( i
=0; i
<iplist_size
; i
++ ) {
1334 char addr
[INET6_ADDRSTRLEN
];
1335 print_sockaddr(addr
, sizeof(addr
),
1337 add_one_dc_unique(mem_ctx
,
1346 TALLOC_FREE(sitename
);
1350 /* Now we add DCs from the main AD DNS lookup. */
1351 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
,
1352 &iplist_size
, True
);
1354 for ( i
=0; i
<iplist_size
; i
++ ) {
1355 char addr
[INET6_ADDRSTRLEN
];
1356 print_sockaddr(addr
, sizeof(addr
),
1358 add_one_dc_unique(mem_ctx
,
1370 /* Try standard netbios queries if no ADS and fall back to DNS queries
1371 * if alt_name is available */
1372 if (*num_dcs
== 0) {
1373 get_sorted_dc_list(domain
->name
, NULL
, &ip_list
, &iplist_size
,
1375 if (iplist_size
== 0) {
1376 if (domain
->alt_name
!= NULL
) {
1377 get_sorted_dc_list(domain
->alt_name
, NULL
, &ip_list
,
1378 &iplist_size
, true);
1382 for ( i
=0; i
<iplist_size
; i
++ ) {
1383 char addr
[INET6_ADDRSTRLEN
];
1384 print_sockaddr(addr
, sizeof(addr
),
1386 add_one_dc_unique(mem_ctx
,
1401 /*******************************************************************
1402 Find and make a connection to a DC in the given domain.
1404 @param[in] mem_ctx talloc memory context to allocate from
1405 @param[in] domain domain to find a dc in
1406 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1407 @param[out] pss DC Internet address and port
1408 @param[out] fd fd of the open socket connected to the newly found dc
1409 @return true when a DC connection is made, false otherwise
1410 *******************************************************************/
1412 static bool find_new_dc(TALLOC_CTX
*mem_ctx
,
1413 struct winbindd_domain
*domain
,
1414 char **dcname
, struct sockaddr_storage
*pss
, int *fd
)
1416 struct dc_name_ip
*dcs
= NULL
;
1419 const char **dcnames
= NULL
;
1420 int num_dcnames
= 0;
1422 struct sockaddr_storage
*addrs
= NULL
;
1433 if (!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
) || (num_dcs
== 0))
1436 for (i
=0; i
<num_dcs
; i
++) {
1438 if (!add_string_to_array(mem_ctx
, dcs
[i
].name
,
1439 &dcnames
, &num_dcnames
)) {
1442 if (!add_sockaddr_to_array(mem_ctx
, &dcs
[i
].ss
, TCP_SMB_PORT
,
1443 &addrs
, &num_addrs
)) {
1448 if ((num_dcnames
== 0) || (num_dcnames
!= num_addrs
))
1451 if ((addrs
== NULL
) || (dcnames
== NULL
))
1454 status
= smbsock_any_connect(addrs
, dcnames
, NULL
, NULL
, NULL
,
1455 num_addrs
, 0, 10, fd
, &fd_index
, NULL
);
1456 if (!NT_STATUS_IS_OK(status
)) {
1457 for (i
=0; i
<num_dcs
; i
++) {
1458 char ab
[INET6_ADDRSTRLEN
];
1459 print_sockaddr(ab
, sizeof(ab
), &dcs
[i
].ss
);
1460 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1461 "domain %s address %s. Error was %s\n",
1462 domain
->name
, ab
, nt_errstr(status
) ));
1463 winbind_add_failed_connection_entry(domain
,
1464 dcs
[i
].name
, NT_STATUS_UNSUCCESSFUL
);
1469 *pss
= addrs
[fd_index
];
1471 if (*dcnames
[fd_index
] != '\0' && !is_ipaddress(dcnames
[fd_index
])) {
1472 /* Ok, we've got a name for the DC */
1473 *dcname
= talloc_strdup(mem_ctx
, dcnames
[fd_index
]);
1474 if (*dcname
== NULL
) {
1480 /* Try to figure out the name */
1481 if (dcip_to_name(mem_ctx
, domain
, pss
, dcname
)) {
1485 /* We can not continue without the DC's name */
1486 winbind_add_failed_connection_entry(domain
, dcs
[fd_index
].name
,
1487 NT_STATUS_UNSUCCESSFUL
);
1489 /* Throw away all arrays as we're doing this again. */
1493 TALLOC_FREE(dcnames
);
1505 static char *current_dc_key(TALLOC_CTX
*mem_ctx
, const char *domain_name
)
1507 return talloc_asprintf_strupper_m(mem_ctx
, "CURRENT_DCNAME/%s",
1511 static void store_current_dc_in_gencache(const char *domain_name
,
1512 const char *dc_name
,
1513 struct cli_state
*cli
)
1515 char addr
[INET6_ADDRSTRLEN
];
1519 if (!cli_state_is_connected(cli
)) {
1523 print_sockaddr(addr
, sizeof(addr
),
1524 smbXcli_conn_remote_sockaddr(cli
->conn
));
1526 key
= current_dc_key(talloc_tos(), domain_name
);
1531 value
= talloc_asprintf(talloc_tos(), "%s %s", addr
, dc_name
);
1532 if (value
== NULL
) {
1536 gencache_set(key
, value
, 0x7fffffff);
1542 bool fetch_current_dc_from_gencache(TALLOC_CTX
*mem_ctx
,
1543 const char *domain_name
,
1544 char **p_dc_name
, char **p_dc_ip
)
1546 char *key
, *value
, *p
;
1548 char *dc_name
= NULL
;
1551 key
= current_dc_key(talloc_tos(), domain_name
);
1555 if (!gencache_get(key
, mem_ctx
, &value
, NULL
)) {
1558 p
= strchr(value
, ' ');
1562 dc_ip
= talloc_strndup(mem_ctx
, value
, p
- value
);
1563 if (dc_ip
== NULL
) {
1566 dc_name
= talloc_strdup(mem_ctx
, p
+1);
1567 if (dc_name
== NULL
) {
1571 if (p_dc_ip
!= NULL
) {
1575 if (p_dc_name
!= NULL
) {
1576 *p_dc_name
= dc_name
;
1581 TALLOC_FREE(dc_name
);
1588 static NTSTATUS
cm_open_connection(struct winbindd_domain
*domain
,
1589 struct winbindd_cm_conn
*new_conn
)
1591 TALLOC_CTX
*mem_ctx
;
1593 char *saf_servername
;
1596 if ((mem_ctx
= talloc_init("cm_open_connection")) == NULL
) {
1597 set_domain_offline(domain
);
1598 return NT_STATUS_NO_MEMORY
;
1601 saf_servername
= saf_fetch(mem_ctx
, domain
->name
);
1603 /* we have to check the server affinity cache here since
1604 later we select a DC based on response time and not preference */
1606 /* Check the negative connection cache
1607 before talking to it. It going down may have
1608 triggered the reconnection. */
1610 if ( saf_servername
&& NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, saf_servername
))) {
1612 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1613 saf_servername
, domain
->name
));
1615 /* convert an ip address to a name */
1616 if (is_ipaddress( saf_servername
) ) {
1617 char *dcname
= NULL
;
1618 struct sockaddr_storage ss
;
1620 if (!interpret_string_addr(&ss
, saf_servername
,
1622 TALLOC_FREE(mem_ctx
);
1623 return NT_STATUS_UNSUCCESSFUL
;
1625 if (dcip_to_name(mem_ctx
, domain
, &ss
, &dcname
)) {
1626 domain
->dcname
= talloc_strdup(domain
,
1628 if (domain
->dcname
== NULL
) {
1629 TALLOC_FREE(mem_ctx
);
1630 return NT_STATUS_NO_MEMORY
;
1633 winbind_add_failed_connection_entry(
1634 domain
, saf_servername
,
1635 NT_STATUS_UNSUCCESSFUL
);
1638 domain
->dcname
= talloc_strdup(domain
, saf_servername
);
1639 if (domain
->dcname
== NULL
) {
1640 TALLOC_FREE(mem_ctx
);
1641 return NT_STATUS_NO_MEMORY
;
1646 for (retries
= 0; retries
< 3; retries
++) {
1649 char *dcname
= NULL
;
1651 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1653 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1654 domain
->dcname
? domain
->dcname
: "", domain
->name
));
1656 if (domain
->dcname
!= NULL
1657 && NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, domain
->dcname
))
1658 && (resolve_name(domain
->dcname
, &domain
->dcaddr
, 0x20, true)))
1662 status
= smbsock_connect(&domain
->dcaddr
, 0,
1665 if (!NT_STATUS_IS_OK(status
)) {
1671 !find_new_dc(mem_ctx
, domain
, &dcname
, &domain
->dcaddr
, &fd
))
1673 /* This is the one place where we will
1674 set the global winbindd offline state
1675 to true, if a "WINBINDD_OFFLINE" entry
1676 is found in the winbindd cache. */
1677 set_global_winbindd_state_offline();
1680 if (dcname
!= NULL
) {
1681 talloc_free(domain
->dcname
);
1683 domain
->dcname
= talloc_move(domain
, &dcname
);
1684 if (domain
->dcname
== NULL
) {
1685 result
= NT_STATUS_NO_MEMORY
;
1690 new_conn
->cli
= NULL
;
1692 result
= cm_prepare_connection(domain
, fd
, domain
->dcname
,
1693 &new_conn
->cli
, &retry
);
1694 if (!NT_STATUS_IS_OK(result
)) {
1695 /* Don't leak the smb connection socket */
1703 if (NT_STATUS_IS_OK(result
)) {
1705 winbindd_set_locator_kdc_envs(domain
);
1707 if (domain
->online
== False
) {
1708 /* We're changing state from offline to online. */
1709 set_global_winbindd_state_online();
1711 set_domain_online(domain
);
1714 * Much as I hate global state, this seems to be the point
1715 * where we can be certain that we have a proper connection to
1716 * a DC. wbinfo --dc-info needs that information, store it in
1717 * gencache with a looong timeout. This will need revisiting
1718 * once we start to connect to multiple DCs, wbcDcInfo is
1719 * already prepared for that.
1721 store_current_dc_in_gencache(domain
->name
, domain
->dcname
,
1724 /* Ensure we setup the retry handler. */
1725 set_domain_offline(domain
);
1728 talloc_destroy(mem_ctx
);
1732 /* Close down all open pipes on a connection. */
1734 void invalidate_cm_connection(struct winbindd_cm_conn
*conn
)
1738 /* We're closing down a possibly dead
1739 connection. Don't have impossibly long (10s) timeouts. */
1742 cli_set_timeout(conn
->cli
, 1000); /* 1 second. */
1745 if (conn
->samr_pipe
!= NULL
) {
1746 if (is_valid_policy_hnd(&conn
->sam_connect_handle
)) {
1747 dcerpc_samr_Close(conn
->samr_pipe
->binding_handle
,
1749 &conn
->sam_connect_handle
,
1752 TALLOC_FREE(conn
->samr_pipe
);
1753 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1755 cli_set_timeout(conn
->cli
, 500);
1759 if (conn
->lsa_pipe
!= NULL
) {
1760 if (is_valid_policy_hnd(&conn
->lsa_policy
)) {
1761 dcerpc_lsa_Close(conn
->lsa_pipe
->binding_handle
,
1766 TALLOC_FREE(conn
->lsa_pipe
);
1767 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1769 cli_set_timeout(conn
->cli
, 500);
1773 if (conn
->lsa_pipe_tcp
!= NULL
) {
1774 if (is_valid_policy_hnd(&conn
->lsa_policy
)) {
1775 dcerpc_lsa_Close(conn
->lsa_pipe_tcp
->binding_handle
,
1780 TALLOC_FREE(conn
->lsa_pipe_tcp
);
1781 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1783 cli_set_timeout(conn
->cli
, 500);
1787 if (conn
->netlogon_pipe
!= NULL
) {
1788 TALLOC_FREE(conn
->netlogon_pipe
);
1789 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1791 cli_set_timeout(conn
->cli
, 500);
1796 cli_shutdown(conn
->cli
);
1802 void close_conns_after_fork(void)
1804 struct winbindd_domain
*domain
;
1805 struct winbindd_cli_state
*cli_state
;
1807 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
1809 * first close the low level SMB TCP connection
1810 * so that we don't generate any SMBclose
1811 * requests in invalidate_cm_connection()
1813 if (cli_state_is_connected(domain
->conn
.cli
)) {
1814 smbXcli_conn_disconnect(domain
->conn
.cli
->conn
, NT_STATUS_OK
);
1817 invalidate_cm_connection(&domain
->conn
);
1820 for (cli_state
= winbindd_client_list();
1822 cli_state
= cli_state
->next
) {
1823 if (cli_state
->sock
>= 0) {
1824 close(cli_state
->sock
);
1825 cli_state
->sock
= -1;
1830 static bool connection_ok(struct winbindd_domain
*domain
)
1834 ok
= cli_state_is_connected(domain
->conn
.cli
);
1836 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1837 domain
->dcname
, domain
->name
));
1841 if (domain
->online
== False
) {
1842 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain
->name
));
1849 /* Initialize a new connection up to the RPC BIND.
1850 Bypass online status check so always does network calls. */
1852 static NTSTATUS
init_dc_connection_network(struct winbindd_domain
*domain
)
1856 /* Internal connections never use the network. */
1857 if (domain
->internal
) {
1858 domain
->initialized
= True
;
1859 return NT_STATUS_OK
;
1862 if (connection_ok(domain
)) {
1863 if (!domain
->initialized
) {
1864 set_dc_type_and_flags(domain
);
1866 return NT_STATUS_OK
;
1869 invalidate_cm_connection(&domain
->conn
);
1871 result
= cm_open_connection(domain
, &domain
->conn
);
1873 if (NT_STATUS_IS_OK(result
) && !domain
->initialized
) {
1874 set_dc_type_and_flags(domain
);
1880 NTSTATUS
init_dc_connection(struct winbindd_domain
*domain
)
1882 if (domain
->internal
) {
1883 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1886 if (domain
->initialized
&& !domain
->online
) {
1887 /* We check for online status elsewhere. */
1888 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
1891 return init_dc_connection_network(domain
);
1894 static NTSTATUS
init_dc_connection_rpc(struct winbindd_domain
*domain
)
1898 status
= init_dc_connection(domain
);
1899 if (!NT_STATUS_IS_OK(status
)) {
1903 if (!domain
->internal
&& domain
->conn
.cli
== NULL
) {
1904 /* happens for trusted domains without inbound trust */
1905 return NT_STATUS_TRUSTED_DOMAIN_FAILURE
;
1908 return NT_STATUS_OK
;
1911 /******************************************************************************
1912 Set the trust flags (direction and forest location) for a domain
1913 ******************************************************************************/
1915 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain
*domain
)
1917 struct winbindd_domain
*our_domain
;
1918 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1920 struct netr_DomainTrustList trusts
;
1922 uint32 flags
= (NETR_TRUST_FLAG_IN_FOREST
|
1923 NETR_TRUST_FLAG_OUTBOUND
|
1924 NETR_TRUST_FLAG_INBOUND
);
1925 struct rpc_pipe_client
*cli
;
1926 TALLOC_CTX
*mem_ctx
= NULL
;
1927 struct dcerpc_binding_handle
*b
;
1929 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain
->name
));
1931 /* Our primary domain doesn't need to worry about trust flags.
1932 Force it to go through the network setup */
1933 if ( domain
->primary
) {
1937 our_domain
= find_our_domain();
1939 if ( !connection_ok(our_domain
) ) {
1940 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1944 /* This won't work unless our domain is AD */
1946 if ( !our_domain
->active_directory
) {
1950 /* Use DsEnumerateDomainTrusts to get us the trust direction
1953 result
= cm_connect_netlogon(our_domain
, &cli
);
1955 if (!NT_STATUS_IS_OK(result
)) {
1956 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1957 "a connection to %s for PIPE_NETLOGON (%s)\n",
1958 domain
->name
, nt_errstr(result
)));
1962 b
= cli
->binding_handle
;
1964 if ( (mem_ctx
= talloc_init("set_dc_type_and_flags_trustinfo")) == NULL
) {
1965 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1969 result
= dcerpc_netr_DsrEnumerateDomainTrusts(b
, mem_ctx
,
1974 if (!NT_STATUS_IS_OK(result
)) {
1975 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1976 "failed to query trusted domain list: %s\n",
1977 nt_errstr(result
)));
1978 talloc_destroy(mem_ctx
);
1981 if (!W_ERROR_IS_OK(werr
)) {
1982 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1983 "failed to query trusted domain list: %s\n",
1985 talloc_destroy(mem_ctx
);
1989 /* Now find the domain name and get the flags */
1991 for ( i
=0; i
<trusts
.count
; i
++ ) {
1992 if ( strequal( domain
->name
, trusts
.array
[i
].netbios_name
) ) {
1993 domain
->domain_flags
= trusts
.array
[i
].trust_flags
;
1994 domain
->domain_type
= trusts
.array
[i
].trust_type
;
1995 domain
->domain_trust_attribs
= trusts
.array
[i
].trust_attributes
;
1997 if ( domain
->domain_type
== NETR_TRUST_TYPE_UPLEVEL
)
1998 domain
->active_directory
= True
;
2000 /* This flag is only set if the domain is *our*
2001 primary domain and the primary domain is in
2004 domain
->native_mode
= (domain
->domain_flags
& NETR_TRUST_FLAG_NATIVE
);
2006 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2007 "native mode.\n", domain
->name
,
2008 domain
->native_mode
? "" : "NOT "));
2010 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2011 "running active directory.\n", domain
->name
,
2012 domain
->active_directory
? "" : "NOT "));
2014 domain
->can_do_ncacn_ip_tcp
= domain
->active_directory
;
2015 domain
->can_do_validation6
= domain
->active_directory
;
2017 domain
->initialized
= True
;
2023 talloc_destroy( mem_ctx
);
2025 return domain
->initialized
;
2028 /******************************************************************************
2029 We can 'sense' certain things about the DC by it's replies to certain
2032 This tells us if this particular remote server is Active Directory, and if it
2034 ******************************************************************************/
2036 static void set_dc_type_and_flags_connect( struct winbindd_domain
*domain
)
2038 NTSTATUS status
, result
;
2040 TALLOC_CTX
*mem_ctx
= NULL
;
2041 struct rpc_pipe_client
*cli
= NULL
;
2042 struct policy_handle pol
;
2043 union dssetup_DsRoleInfo info
;
2044 union lsa_PolicyInformation
*lsa_info
= NULL
;
2046 if (!connection_ok(domain
)) {
2050 mem_ctx
= talloc_init("set_dc_type_and_flags on domain %s\n",
2053 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2057 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain
->name
));
2059 status
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
2063 if (!NT_STATUS_IS_OK(status
)) {
2064 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2065 "PI_DSSETUP on domain %s: (%s)\n",
2066 domain
->name
, nt_errstr(status
)));
2068 /* if this is just a non-AD domain we need to continue
2069 * identifying so that we can in the end return with
2070 * domain->initialized = True - gd */
2075 status
= dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli
->binding_handle
, mem_ctx
,
2076 DS_ROLE_BASIC_INFORMATION
,
2081 if (NT_STATUS_IS_OK(status
)) {
2082 result
= werror_to_ntstatus(werr
);
2084 if (!NT_STATUS_IS_OK(status
)) {
2085 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2086 "on domain %s failed: (%s)\n",
2087 domain
->name
, nt_errstr(status
)));
2089 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2090 * every opcode on the DSSETUP pipe, continue with
2091 * no_dssetup mode here as well to get domain->initialized
2094 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
2098 TALLOC_FREE(mem_ctx
);
2102 if ((info
.basic
.flags
& DS_ROLE_PRIMARY_DS_RUNNING
) &&
2103 !(info
.basic
.flags
& DS_ROLE_PRIMARY_DS_MIXED_MODE
)) {
2104 domain
->native_mode
= True
;
2106 domain
->native_mode
= False
;
2110 status
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
,
2111 &ndr_table_lsarpc
, &cli
);
2113 if (!NT_STATUS_IS_OK(status
)) {
2114 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2115 "PI_LSARPC on domain %s: (%s)\n",
2116 domain
->name
, nt_errstr(status
)));
2118 TALLOC_FREE(mem_ctx
);
2122 status
= rpccli_lsa_open_policy2(cli
, mem_ctx
, True
,
2123 SEC_FLAG_MAXIMUM_ALLOWED
, &pol
);
2125 if (NT_STATUS_IS_OK(status
)) {
2126 /* This particular query is exactly what Win2k clients use
2127 to determine that the DC is active directory */
2128 status
= dcerpc_lsa_QueryInfoPolicy2(cli
->binding_handle
, mem_ctx
,
2130 LSA_POLICY_INFO_DNS
,
2135 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2136 domain
->active_directory
= True
;
2138 if (lsa_info
->dns
.name
.string
) {
2139 talloc_free(domain
->name
);
2140 domain
->name
= talloc_strdup(domain
,
2141 lsa_info
->dns
.name
.string
);
2142 if (domain
->name
== NULL
) {
2147 if (lsa_info
->dns
.dns_domain
.string
) {
2148 talloc_free(domain
->alt_name
);
2150 talloc_strdup(domain
,
2151 lsa_info
->dns
.dns_domain
.string
);
2152 if (domain
->alt_name
== NULL
) {
2157 /* See if we can set some domain trust flags about
2160 if (lsa_info
->dns
.dns_forest
.string
) {
2161 talloc_free(domain
->forest_name
);
2162 domain
->forest_name
=
2163 talloc_strdup(domain
,
2164 lsa_info
->dns
.dns_forest
.string
);
2165 if (domain
->forest_name
== NULL
) {
2169 if (strequal(domain
->forest_name
, domain
->alt_name
)) {
2170 domain
->domain_flags
|= NETR_TRUST_FLAG_TREEROOT
;
2174 if (lsa_info
->dns
.sid
) {
2175 sid_copy(&domain
->sid
, lsa_info
->dns
.sid
);
2178 domain
->active_directory
= False
;
2180 status
= rpccli_lsa_open_policy(cli
, mem_ctx
, True
,
2181 SEC_FLAG_MAXIMUM_ALLOWED
,
2184 if (!NT_STATUS_IS_OK(status
)) {
2188 status
= dcerpc_lsa_QueryInfoPolicy(cli
->binding_handle
, mem_ctx
,
2190 LSA_POLICY_INFO_ACCOUNT_DOMAIN
,
2193 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2195 if (lsa_info
->account_domain
.name
.string
) {
2196 talloc_free(domain
->name
);
2198 talloc_strdup(domain
,
2199 lsa_info
->account_domain
.name
.string
);
2202 if (lsa_info
->account_domain
.sid
) {
2203 sid_copy(&domain
->sid
, lsa_info
->account_domain
.sid
);
2209 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2210 domain
->name
, domain
->native_mode
? "" : "NOT "));
2212 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2213 domain
->name
, domain
->active_directory
? "" : "NOT "));
2215 domain
->can_do_ncacn_ip_tcp
= domain
->active_directory
;
2216 domain
->can_do_validation6
= domain
->active_directory
;
2220 TALLOC_FREE(mem_ctx
);
2222 domain
->initialized
= True
;
2225 /**********************************************************************
2226 Set the domain_flags (trust attributes, domain operating modes, etc...
2227 ***********************************************************************/
2229 static void set_dc_type_and_flags( struct winbindd_domain
*domain
)
2231 /* we always have to contact our primary domain */
2233 if ( domain
->primary
) {
2234 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2235 "primary domain\n"));
2236 set_dc_type_and_flags_connect( domain
);
2240 /* Use our DC to get the information if possible */
2242 if ( !set_dc_type_and_flags_trustinfo( domain
) ) {
2243 /* Otherwise, fallback to contacting the
2245 set_dc_type_and_flags_connect( domain
);
2253 /**********************************************************************
2254 ***********************************************************************/
2256 static NTSTATUS
cm_get_schannel_creds(struct winbindd_domain
*domain
,
2257 struct netlogon_creds_CredentialState
**ppdc
)
2259 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2260 struct rpc_pipe_client
*netlogon_pipe
;
2262 if (lp_client_schannel() == False
) {
2263 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2266 result
= cm_connect_netlogon(domain
, &netlogon_pipe
);
2267 if (!NT_STATUS_IS_OK(result
)) {
2271 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2274 if (!domain
->conn
.netlogon_pipe
->dc
) {
2275 return NT_STATUS_INTERNAL_ERROR
; /* This shouldn't happen. */
2278 *ppdc
= domain
->conn
.netlogon_pipe
->dc
;
2279 return NT_STATUS_OK
;
2282 NTSTATUS
cm_connect_sam(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
2283 struct rpc_pipe_client
**cli
, struct policy_handle
*sam_handle
)
2285 struct winbindd_cm_conn
*conn
;
2286 NTSTATUS status
, result
;
2287 struct netlogon_creds_CredentialState
*p_creds
;
2288 char *machine_password
= NULL
;
2289 char *machine_account
= NULL
;
2290 const char *domain_name
= NULL
;
2292 if (sid_check_is_our_sam(&domain
->sid
)) {
2293 return open_internal_samr_conn(mem_ctx
, domain
, cli
, sam_handle
);
2296 status
= init_dc_connection_rpc(domain
);
2297 if (!NT_STATUS_IS_OK(status
)) {
2301 conn
= &domain
->conn
;
2303 if (rpccli_is_connected(conn
->samr_pipe
)) {
2307 TALLOC_FREE(conn
->samr_pipe
);
2310 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2311 * sign and sealed pipe using the machine account password by
2312 * preference. If we can't - try schannel, if that fails, try
2316 if ((conn
->cli
->user_name
[0] == '\0') ||
2317 (conn
->cli
->domain
[0] == '\0') ||
2318 (conn
->cli
->password
== NULL
|| conn
->cli
->password
[0] == '\0'))
2320 status
= get_trust_creds(domain
, &machine_password
,
2321 &machine_account
, NULL
);
2322 if (!NT_STATUS_IS_OK(status
)) {
2323 DEBUG(10, ("cm_connect_sam: No no user available for "
2324 "domain %s, trying schannel\n", conn
->cli
->domain
));
2327 domain_name
= domain
->name
;
2329 machine_password
= SMB_STRDUP(conn
->cli
->password
);
2330 machine_account
= SMB_STRDUP(conn
->cli
->user_name
);
2331 domain_name
= conn
->cli
->domain
;
2334 if (!machine_password
|| !machine_account
) {
2335 status
= NT_STATUS_NO_MEMORY
;
2339 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2340 authenticated SAMR pipe with sign & seal. */
2341 status
= cli_rpc_pipe_open_spnego(conn
->cli
,
2345 DCERPC_AUTH_LEVEL_PRIVACY
,
2346 smbXcli_conn_remote_name(conn
->cli
->conn
),
2352 if (!NT_STATUS_IS_OK(status
)) {
2353 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2354 "pipe for domain %s using NTLMSSP "
2355 "authenticated pipe: user %s\\%s. Error was "
2356 "%s\n", domain
->name
, domain_name
,
2357 machine_account
, nt_errstr(status
)));
2361 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2362 "domain %s using NTLMSSP authenticated "
2363 "pipe: user %s\\%s\n", domain
->name
,
2364 domain_name
, machine_account
));
2366 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2367 conn
->samr_pipe
->desthost
,
2368 SEC_FLAG_MAXIMUM_ALLOWED
,
2369 &conn
->sam_connect_handle
,
2371 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2374 if (NT_STATUS_IS_OK(status
)) {
2378 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2379 "failed for domain %s, error was %s. Trying schannel\n",
2380 domain
->name
, nt_errstr(status
) ));
2381 TALLOC_FREE(conn
->samr_pipe
);
2385 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2387 status
= cm_get_schannel_creds(domain
, &p_creds
);
2388 if (!NT_STATUS_IS_OK(status
)) {
2389 /* If this call fails - conn->cli can now be NULL ! */
2390 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2391 "for domain %s (error %s), trying anon\n",
2393 nt_errstr(status
) ));
2396 status
= cli_rpc_pipe_open_schannel_with_key
2397 (conn
->cli
, &ndr_table_samr
, NCACN_NP
,
2398 DCERPC_AUTH_LEVEL_PRIVACY
,
2399 domain
->name
, &p_creds
, &conn
->samr_pipe
);
2401 if (!NT_STATUS_IS_OK(status
)) {
2402 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2403 "domain %s using schannel. Error was %s\n",
2404 domain
->name
, nt_errstr(status
) ));
2407 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2408 "schannel.\n", domain
->name
));
2410 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2411 conn
->samr_pipe
->desthost
,
2412 SEC_FLAG_MAXIMUM_ALLOWED
,
2413 &conn
->sam_connect_handle
,
2415 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
2418 if (NT_STATUS_IS_OK(status
)) {
2421 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2422 "for domain %s, error was %s. Trying anonymous\n",
2423 domain
->name
, nt_errstr(status
) ));
2424 TALLOC_FREE(conn
->samr_pipe
);
2428 /* Finally fall back to anonymous. */
2429 status
= cli_rpc_pipe_open_noauth(conn
->cli
, &ndr_table_samr
,
2432 if (!NT_STATUS_IS_OK(status
)) {
2436 status
= dcerpc_samr_Connect2(conn
->samr_pipe
->binding_handle
, mem_ctx
,
2437 conn
->samr_pipe
->desthost
,
2438 SEC_FLAG_MAXIMUM_ALLOWED
,
2439 &conn
->sam_connect_handle
,
2441 if (!NT_STATUS_IS_OK(status
)) {
2442 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2443 "for domain %s Error was %s\n",
2444 domain
->name
, nt_errstr(status
) ));
2447 if (!NT_STATUS_IS_OK(result
)) {
2449 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2450 "for domain %s Error was %s\n",
2451 domain
->name
, nt_errstr(result
)));
2456 status
= dcerpc_samr_OpenDomain(conn
->samr_pipe
->binding_handle
,
2458 &conn
->sam_connect_handle
,
2459 SEC_FLAG_MAXIMUM_ALLOWED
,
2461 &conn
->sam_domain_handle
,
2463 if (!NT_STATUS_IS_OK(status
)) {
2470 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
2472 * if we got access denied, we might just have no access rights
2473 * to talk to the remote samr server server (e.g. when we are a
2474 * PDC and we are connecting a w2k8 pdc via an interdomain
2475 * trust). In that case do not invalidate the whole connection
2478 TALLOC_FREE(conn
->samr_pipe
);
2479 ZERO_STRUCT(conn
->sam_domain_handle
);
2481 } else if (!NT_STATUS_IS_OK(status
)) {
2482 invalidate_cm_connection(conn
);
2486 *cli
= conn
->samr_pipe
;
2487 *sam_handle
= conn
->sam_domain_handle
;
2488 SAFE_FREE(machine_password
);
2489 SAFE_FREE(machine_account
);
2493 /**********************************************************************
2494 open an schanneld ncacn_ip_tcp connection to LSA
2495 ***********************************************************************/
2497 NTSTATUS
cm_connect_lsa_tcp(struct winbindd_domain
*domain
,
2498 TALLOC_CTX
*mem_ctx
,
2499 struct rpc_pipe_client
**cli
)
2501 struct winbindd_cm_conn
*conn
;
2502 struct netlogon_creds_CredentialState
*creds
;
2505 DEBUG(10,("cm_connect_lsa_tcp\n"));
2507 status
= init_dc_connection_rpc(domain
);
2508 if (!NT_STATUS_IS_OK(status
)) {
2512 conn
= &domain
->conn
;
2514 if (conn
->lsa_pipe_tcp
&&
2515 conn
->lsa_pipe_tcp
->transport
->transport
== NCACN_IP_TCP
&&
2516 conn
->lsa_pipe_tcp
->auth
->auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
&&
2517 rpccli_is_connected(conn
->lsa_pipe_tcp
)) {
2521 TALLOC_FREE(conn
->lsa_pipe_tcp
);
2523 status
= cm_get_schannel_creds(domain
, &creds
);
2524 if (!NT_STATUS_IS_OK(status
)) {
2528 status
= cli_rpc_pipe_open_schannel_with_key(conn
->cli
,
2531 DCERPC_AUTH_LEVEL_PRIVACY
,
2534 &conn
->lsa_pipe_tcp
);
2535 if (!NT_STATUS_IS_OK(status
)) {
2536 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2537 nt_errstr(status
)));
2542 if (!NT_STATUS_IS_OK(status
)) {
2543 TALLOC_FREE(conn
->lsa_pipe_tcp
);
2547 *cli
= conn
->lsa_pipe_tcp
;
2552 NTSTATUS
cm_connect_lsa(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
2553 struct rpc_pipe_client
**cli
, struct policy_handle
*lsa_policy
)
2555 struct winbindd_cm_conn
*conn
;
2556 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2557 struct netlogon_creds_CredentialState
*p_creds
;
2559 result
= init_dc_connection_rpc(domain
);
2560 if (!NT_STATUS_IS_OK(result
))
2563 conn
= &domain
->conn
;
2565 if (rpccli_is_connected(conn
->lsa_pipe
)) {
2569 TALLOC_FREE(conn
->lsa_pipe
);
2571 if ((conn
->cli
->user_name
[0] == '\0') ||
2572 (conn
->cli
->domain
[0] == '\0') ||
2573 (conn
->cli
->password
== NULL
|| conn
->cli
->password
[0] == '\0')) {
2574 DEBUG(10, ("cm_connect_lsa: No no user available for "
2575 "domain %s, trying schannel\n", conn
->cli
->domain
));
2579 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2580 * authenticated LSA pipe with sign & seal. */
2581 result
= cli_rpc_pipe_open_spnego
2582 (conn
->cli
, &ndr_table_lsarpc
, NCACN_NP
,
2584 DCERPC_AUTH_LEVEL_PRIVACY
,
2585 smbXcli_conn_remote_name(conn
->cli
->conn
),
2586 conn
->cli
->domain
, conn
->cli
->user_name
, conn
->cli
->password
,
2589 if (!NT_STATUS_IS_OK(result
)) {
2590 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2591 "domain %s using NTLMSSP authenticated pipe: user "
2592 "%s\\%s. Error was %s. Trying schannel.\n",
2593 domain
->name
, conn
->cli
->domain
,
2594 conn
->cli
->user_name
, nt_errstr(result
)));
2598 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2599 "NTLMSSP authenticated pipe: user %s\\%s\n",
2600 domain
->name
, conn
->cli
->domain
, conn
->cli
->user_name
));
2602 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2603 SEC_FLAG_MAXIMUM_ALLOWED
,
2605 if (NT_STATUS_IS_OK(result
)) {
2609 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2612 TALLOC_FREE(conn
->lsa_pipe
);
2616 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2618 result
= cm_get_schannel_creds(domain
, &p_creds
);
2619 if (!NT_STATUS_IS_OK(result
)) {
2620 /* If this call fails - conn->cli can now be NULL ! */
2621 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2622 "for domain %s (error %s), trying anon\n",
2624 nt_errstr(result
) ));
2627 result
= cli_rpc_pipe_open_schannel_with_key
2628 (conn
->cli
, &ndr_table_lsarpc
, NCACN_NP
,
2629 DCERPC_AUTH_LEVEL_PRIVACY
,
2630 domain
->name
, &p_creds
, &conn
->lsa_pipe
);
2632 if (!NT_STATUS_IS_OK(result
)) {
2633 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2634 "domain %s using schannel. Error was %s\n",
2635 domain
->name
, nt_errstr(result
) ));
2638 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2639 "schannel.\n", domain
->name
));
2641 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2642 SEC_FLAG_MAXIMUM_ALLOWED
,
2644 if (NT_STATUS_IS_OK(result
)) {
2648 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2651 TALLOC_FREE(conn
->lsa_pipe
);
2655 result
= cli_rpc_pipe_open_noauth(conn
->cli
,
2658 if (!NT_STATUS_IS_OK(result
)) {
2659 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
2663 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
2664 SEC_FLAG_MAXIMUM_ALLOWED
,
2667 if (!NT_STATUS_IS_OK(result
)) {
2668 invalidate_cm_connection(conn
);
2672 *cli
= conn
->lsa_pipe
;
2673 *lsa_policy
= conn
->lsa_policy
;
2677 /****************************************************************************
2678 Open a LSA connection to a DC, suiteable for LSA lookup calls.
2679 ****************************************************************************/
2681 NTSTATUS
cm_connect_lsat(struct winbindd_domain
*domain
,
2682 TALLOC_CTX
*mem_ctx
,
2683 struct rpc_pipe_client
**cli
,
2684 struct policy_handle
*lsa_policy
)
2688 if (domain
->can_do_ncacn_ip_tcp
) {
2689 status
= cm_connect_lsa_tcp(domain
, mem_ctx
, cli
);
2690 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) ||
2691 NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
) ||
2692 NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
)) {
2693 invalidate_cm_connection(&domain
->conn
);
2694 status
= cm_connect_lsa_tcp(domain
, mem_ctx
, cli
);
2696 if (NT_STATUS_IS_OK(status
)) {
2701 * we tried twice to connect via ncan_ip_tcp and schannel and
2702 * failed - maybe it is a trusted domain we can't connect to ?
2703 * do not try tcp next time - gd
2705 domain
->can_do_ncacn_ip_tcp
= false;
2708 status
= cm_connect_lsa(domain
, mem_ctx
, cli
, lsa_policy
);
2713 /****************************************************************************
2714 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2715 session key stored in conn->netlogon_pipe->dc->sess_key.
2716 ****************************************************************************/
2718 NTSTATUS
cm_connect_netlogon(struct winbindd_domain
*domain
,
2719 struct rpc_pipe_client
**cli
)
2721 struct winbindd_cm_conn
*conn
;
2724 uint32_t neg_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
| NETLOGON_NEG_SUPPORTS_AES
;
2725 uint8_t mach_pwd
[16];
2726 enum netr_SchannelType sec_chan_type
;
2727 const char *account_name
;
2728 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
2732 result
= init_dc_connection_rpc(domain
);
2733 if (!NT_STATUS_IS_OK(result
)) {
2737 conn
= &domain
->conn
;
2739 if (rpccli_is_connected(conn
->netlogon_pipe
)) {
2740 *cli
= conn
->netlogon_pipe
;
2741 return NT_STATUS_OK
;
2744 TALLOC_FREE(conn
->netlogon_pipe
);
2746 result
= cli_rpc_pipe_open_noauth(conn
->cli
,
2747 &ndr_table_netlogon
,
2749 if (!NT_STATUS_IS_OK(result
)) {
2753 if ((!IS_DC
) && (!domain
->primary
)) {
2754 /* Clear the schannel request bit and drop down */
2755 neg_flags
&= ~NETLOGON_NEG_SCHANNEL
;
2759 if (lp_client_schannel() != False
) {
2760 neg_flags
|= NETLOGON_NEG_SCHANNEL
;
2763 if (!get_trust_pw_hash(domain
->name
, mach_pwd
, &account_name
,
2766 TALLOC_FREE(netlogon_pipe
);
2767 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
2770 result
= rpccli_netlogon_setup_creds(
2772 domain
->dcname
, /* server name. */
2773 domain
->name
, /* domain name */
2774 lp_netbios_name(), /* client name */
2775 account_name
, /* machine account */
2776 mach_pwd
, /* machine password */
2777 sec_chan_type
, /* from get_trust_pw */
2780 if (!NT_STATUS_IS_OK(result
)) {
2781 TALLOC_FREE(netlogon_pipe
);
2785 if ((lp_client_schannel() == True
) &&
2786 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2787 DEBUG(3, ("Server did not offer schannel\n"));
2788 TALLOC_FREE(netlogon_pipe
);
2789 return NT_STATUS_ACCESS_DENIED
;
2793 if ((lp_client_schannel() == False
) ||
2794 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
2796 * NetSamLogonEx only works for schannel
2798 domain
->can_do_samlogon_ex
= False
;
2800 /* We're done - just keep the existing connection to NETLOGON
2802 conn
->netlogon_pipe
= netlogon_pipe
;
2803 *cli
= conn
->netlogon_pipe
;
2804 return NT_STATUS_OK
;
2807 /* Using the credentials from the first pipe, open a signed and sealed
2808 second netlogon pipe. The session key is stored in the schannel
2809 part of the new pipe auth struct.
2812 result
= cli_rpc_pipe_open_schannel_with_key(
2813 conn
->cli
, &ndr_table_netlogon
, NCACN_NP
,
2814 DCERPC_AUTH_LEVEL_PRIVACY
, domain
->name
, &netlogon_pipe
->dc
,
2815 &conn
->netlogon_pipe
);
2817 /* We can now close the initial netlogon pipe. */
2818 TALLOC_FREE(netlogon_pipe
);
2820 if (!NT_STATUS_IS_OK(result
)) {
2821 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2822 "was %s\n", nt_errstr(result
)));
2824 invalidate_cm_connection(conn
);
2829 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2830 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2831 * supported). We used to only try SamLogonEx for AD, but
2832 * Samba DCs can also do it. And because we don't distinguish
2833 * between Samba and NT4, always try it once.
2835 domain
->can_do_samlogon_ex
= true;
2837 *cli
= conn
->netlogon_pipe
;
2838 return NT_STATUS_OK
;
2841 void winbind_msg_ip_dropped(struct messaging_context
*msg_ctx
,
2844 struct server_id server_id
,
2847 struct winbindd_domain
*domain
;
2848 char *freeit
= NULL
;
2852 || (data
->data
== NULL
)
2853 || (data
->length
== 0)
2854 || (data
->data
[data
->length
-1] != '\0')) {
2855 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2860 addr
= (char *)data
->data
;
2861 DEBUG(10, ("IP %s dropped\n", addr
));
2863 if (!is_ipaddress(addr
)) {
2866 * Some code sends us ip addresses with the /netmask
2869 slash
= strchr(addr
, '/');
2870 if (slash
== NULL
) {
2871 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2875 freeit
= talloc_strndup(talloc_tos(), addr
, slash
-addr
);
2876 if (freeit
== NULL
) {
2877 DEBUG(1, ("talloc failed\n"));
2881 DEBUG(10, ("Stripped /netmask to IP %s\n", addr
));
2884 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
2885 char sockaddr
[INET6_ADDRSTRLEN
];
2887 if (!cli_state_is_connected(domain
->conn
.cli
)) {
2891 print_sockaddr(sockaddr
, sizeof(sockaddr
),
2892 smbXcli_conn_local_sockaddr(domain
->conn
.cli
->conn
));
2894 if (strequal(sockaddr
, addr
)) {
2895 smbXcli_conn_disconnect(domain
->conn
.cli
->conn
, NT_STATUS_OK
);
2898 TALLOC_FREE(freeit
);