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/cli_netlogon.h"
65 #include "../librpc/gen_ndr/cli_samr.h"
66 #include "../librpc/gen_ndr/cli_lsa.h"
67 #include "../librpc/gen_ndr/cli_dssetup.h"
68 #include "libads/sitename_cache.h"
69 #include "librpc/gen_ndr/messaging.h"
72 #define DBGC_CLASS DBGC_WINBIND
76 struct sockaddr_storage ss;
79 extern struct winbindd_methods reconnect_methods;
80 extern bool override_logfile;
82 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
83 static void set_dc_type_and_flags( struct winbindd_domain *domain );
84 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
85 struct dc_name_ip **dcs, int *num_dcs);
87 /****************************************************************
88 Child failed to find DC's. Reschedule check.
89 ****************************************************************/
91 static void msg_failed_to_go_online(struct messaging_context *msg,
94 struct server_id server_id,
97 struct winbindd_domain *domain;
98 const char *domainname = (const char *)data->data;
100 if (data->data == NULL || data->length == 0) {
104 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
106 for (domain = domain_list(); domain; domain = domain->next) {
107 if (domain->internal) {
111 if (strequal(domain->name, domainname)) {
112 if (domain->online) {
113 /* We're already online, ignore. */
114 DEBUG(5,("msg_fail_to_go_online: domain %s "
115 "already online.\n", domainname));
119 /* Reschedule the online check. */
120 set_domain_offline(domain);
126 /****************************************************************
127 Actually cause a reconnect from a message.
128 ****************************************************************/
130 static void msg_try_to_go_online(struct messaging_context *msg,
133 struct server_id server_id,
136 struct winbindd_domain *domain;
137 const char *domainname = (const char *)data->data;
139 if (data->data == NULL || data->length == 0) {
143 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
145 for (domain = domain_list(); domain; domain = domain->next) {
146 if (domain->internal) {
150 if (strequal(domain->name, domainname)) {
152 if (domain->online) {
153 /* We're already online, ignore. */
154 DEBUG(5,("msg_try_to_go_online: domain %s "
155 "already online.\n", domainname));
159 /* This call takes care of setting the online
160 flag to true if we connected, or re-adding
161 the offline handler if false. Bypasses online
162 check so always does network calls. */
164 init_dc_connection_network(domain);
170 /****************************************************************
171 Fork a child to try and contact a DC. Do this as contacting a
172 DC requires blocking lookups and we don't want to block our
174 ****************************************************************/
176 static bool fork_child_dc_connect(struct winbindd_domain *domain)
178 struct dc_name_ip *dcs = NULL;
180 TALLOC_CTX *mem_ctx = NULL;
181 pid_t parent_pid = sys_getpid();
184 if (domain->dc_probe_pid != (pid_t)-1) {
186 * We might already have a DC probe
187 * child working, check.
189 if (process_exists_by_pid(domain->dc_probe_pid)) {
190 DEBUG(10,("fork_child_dc_connect: pid %u already "
191 "checking for DC's.\n",
192 (unsigned int)domain->dc_probe_pid));
195 domain->dc_probe_pid = (pid_t)-1;
198 domain->dc_probe_pid = sys_fork();
200 if (domain->dc_probe_pid == (pid_t)-1) {
201 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
205 if (domain->dc_probe_pid != (pid_t)0) {
207 messaging_register(winbind_messaging_context(), NULL,
208 MSG_WINBIND_TRY_TO_GO_ONLINE,
209 msg_try_to_go_online);
210 messaging_register(winbind_messaging_context(), NULL,
211 MSG_WINBIND_FAILED_TO_GO_ONLINE,
212 msg_failed_to_go_online);
218 /* Leave messages blocked - we will never process one. */
220 if (!override_logfile) {
221 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
222 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
227 if (!winbindd_reinit_after_fork(lfile)) {
228 messaging_send_buf(winbind_messaging_context(),
229 pid_to_procid(parent_pid),
230 MSG_WINBIND_FAILED_TO_GO_ONLINE,
231 (uint8 *)domain->name,
232 strlen(domain->name)+1);
237 mem_ctx = talloc_init("fork_child_dc_connect");
239 DEBUG(0,("talloc_init failed.\n"));
240 messaging_send_buf(winbind_messaging_context(),
241 pid_to_procid(parent_pid),
242 MSG_WINBIND_FAILED_TO_GO_ONLINE,
243 (uint8 *)domain->name,
244 strlen(domain->name)+1);
248 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
249 /* Still offline ? Can't find DC's. */
250 messaging_send_buf(winbind_messaging_context(),
251 pid_to_procid(parent_pid),
252 MSG_WINBIND_FAILED_TO_GO_ONLINE,
253 (uint8 *)domain->name,
254 strlen(domain->name)+1);
258 /* We got a DC. Send a message to our parent to get it to
259 try and do the same. */
261 messaging_send_buf(winbind_messaging_context(),
262 pid_to_procid(parent_pid),
263 MSG_WINBIND_TRY_TO_GO_ONLINE,
264 (uint8 *)domain->name,
265 strlen(domain->name)+1);
269 /****************************************************************
270 Handler triggered if we're offline to try and detect a DC.
271 ****************************************************************/
273 static void check_domain_online_handler(struct event_context *ctx,
274 struct timed_event *te,
278 struct winbindd_domain *domain =
279 (struct winbindd_domain *)private_data;
281 DEBUG(10,("check_domain_online_handler: called for domain "
282 "%s (online = %s)\n", domain->name,
283 domain->online ? "True" : "False" ));
285 TALLOC_FREE(domain->check_online_event);
287 /* Are we still in "startup" mode ? */
289 if (domain->startup && (now.tv_sec > domain->startup_time + 30)) {
290 /* No longer in "startup" mode. */
291 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
293 domain->startup = False;
296 /* We've been told to stay offline, so stay
299 if (get_global_winbindd_state_offline()) {
300 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
305 /* Fork a child to test if it can contact a DC.
306 If it can then send ourselves a message to
307 cause a reconnect. */
309 fork_child_dc_connect(domain);
312 /****************************************************************
313 If we're still offline setup the timeout check.
314 ****************************************************************/
316 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
318 int wbr = lp_winbind_reconnect_delay();
320 if (domain->startup) {
321 domain->check_online_timeout = 10;
322 } else if (domain->check_online_timeout < wbr) {
323 domain->check_online_timeout = wbr;
327 /****************************************************************
328 Set domain offline and also add handler to put us back online
330 ****************************************************************/
332 void set_domain_offline(struct winbindd_domain *domain)
334 DEBUG(10,("set_domain_offline: called for domain %s\n",
337 TALLOC_FREE(domain->check_online_event);
339 if (domain->internal) {
340 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
345 domain->online = False;
347 /* Offline domains are always initialized. They're
348 re-initialized when they go back online. */
350 domain->initialized = True;
352 /* We only add the timeout handler that checks and
353 allows us to go back online when we've not
354 been told to remain offline. */
356 if (get_global_winbindd_state_offline()) {
357 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
362 /* If we're in startup mode, check again in 10 seconds, not in
363 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
365 calc_new_online_timeout_check(domain);
367 domain->check_online_event = event_add_timed(winbind_event_context(),
369 timeval_current_ofs(domain->check_online_timeout,0),
370 check_domain_online_handler,
373 /* The above *has* to succeed for winbindd to work. */
374 if (!domain->check_online_event) {
375 smb_panic("set_domain_offline: failed to add online handler");
378 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
381 /* Send an offline message to the idmap child when our
382 primary domain goes offline */
384 if ( domain->primary ) {
385 struct winbindd_child *idmap = idmap_child();
387 if ( idmap->pid != 0 ) {
388 messaging_send_buf(winbind_messaging_context(),
389 pid_to_procid(idmap->pid),
391 (uint8 *)domain->name,
392 strlen(domain->name)+1);
399 /****************************************************************
400 Set domain online - if allowed.
401 ****************************************************************/
403 static void set_domain_online(struct winbindd_domain *domain)
405 DEBUG(10,("set_domain_online: called for domain %s\n",
408 if (domain->internal) {
409 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
414 if (get_global_winbindd_state_offline()) {
415 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
420 winbindd_set_locator_kdc_envs(domain);
422 /* If we are waiting to get a krb5 ticket, trigger immediately. */
423 ccache_regain_all_now();
425 /* Ok, we're out of any startup mode now... */
426 domain->startup = False;
428 if (domain->online == False) {
429 /* We were offline - now we're online. We default to
430 using the MS-RPC backend if we started offline,
431 and if we're going online for the first time we
432 should really re-initialize the backends and the
433 checks to see if we're talking to an AD or NT domain.
436 domain->initialized = False;
438 /* 'reconnect_methods' is the MS-RPC backend. */
439 if (domain->backend == &reconnect_methods) {
440 domain->backend = NULL;
444 /* Ensure we have no online timeout checks. */
445 domain->check_online_timeout = 0;
446 TALLOC_FREE(domain->check_online_event);
448 /* Ensure we ignore any pending child messages. */
449 messaging_deregister(winbind_messaging_context(),
450 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
451 messaging_deregister(winbind_messaging_context(),
452 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
454 domain->online = True;
456 /* Send an online message to the idmap child when our
457 primary domain comes online */
459 if ( domain->primary ) {
460 struct winbindd_child *idmap = idmap_child();
462 if ( idmap->pid != 0 ) {
463 messaging_send_buf(winbind_messaging_context(),
464 pid_to_procid(idmap->pid),
466 (uint8 *)domain->name,
467 strlen(domain->name)+1);
474 /****************************************************************
475 Requested to set a domain online.
476 ****************************************************************/
478 void set_domain_online_request(struct winbindd_domain *domain)
482 DEBUG(10,("set_domain_online_request: called for domain %s\n",
485 if (get_global_winbindd_state_offline()) {
486 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
491 if (domain->internal) {
492 DEBUG(10, ("set_domain_online_request: Internal domains are "
497 /* We've been told it's safe to go online and
498 try and connect to a DC. But I don't believe it
499 because network manager seems to lie.
500 Wait at least 5 seconds. Heuristics suck... */
505 /* Go into "startup" mode again. */
506 domain->startup_time = tev.tv_sec;
507 domain->startup = True;
511 if (!domain->check_online_event) {
512 /* If we've come from being globally offline we
513 don't have a check online event handler set.
514 We need to add one now we're trying to go
517 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
521 TALLOC_FREE(domain->check_online_event);
523 domain->check_online_event = event_add_timed(winbind_event_context(),
526 check_domain_online_handler,
529 /* The above *has* to succeed for winbindd to work. */
530 if (!domain->check_online_event) {
531 smb_panic("set_domain_online_request: failed to add online handler");
535 /****************************************************************
536 Add -ve connection cache entries for domain and realm.
537 ****************************************************************/
539 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
543 add_failed_connection_entry(domain->name, server, result);
544 /* If this was the saf name for the last thing we talked to,
546 saf_delete(domain->name);
547 if (*domain->alt_name) {
548 add_failed_connection_entry(domain->alt_name, server, result);
549 saf_delete(domain->alt_name);
551 winbindd_unset_locator_kdc_env(domain);
554 /* Choose between anonymous or authenticated connections. We need to use
555 an authenticated connection if DCs have the RestrictAnonymous registry
556 entry set > 0, or the "Additional restrictions for anonymous
557 connections" set in the win2k Local Security Policy.
559 Caller to free() result in domain, username, password
562 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
564 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
565 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
566 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
568 if (*username && **username) {
570 if (!*domain || !**domain)
571 *domain = smb_xstrdup(lp_workgroup());
573 if (!*password || !**password)
574 *password = smb_xstrdup("");
576 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
577 *domain, *username));
580 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
581 *username = smb_xstrdup("");
582 *domain = smb_xstrdup("");
583 *password = smb_xstrdup("");
587 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
589 struct sockaddr_storage *dc_ss)
591 struct winbindd_domain *our_domain = NULL;
592 struct rpc_pipe_client *netlogon_pipe = NULL;
596 unsigned int orig_timeout;
597 const char *tmp = NULL;
600 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
607 if (domain->primary) {
611 our_domain = find_our_domain();
613 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
617 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
618 if (!NT_STATUS_IS_OK(result)) {
619 talloc_destroy(mem_ctx);
623 /* This call can take a long time - allow the server to time out.
624 35 seconds should do it. */
626 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
628 if (our_domain->active_directory) {
629 struct netr_DsRGetDCNameInfo *domain_info = NULL;
631 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
640 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
642 mem_ctx, domain_info->dc_unc);
644 DEBUG(0, ("talloc_strdup failed\n"));
645 talloc_destroy(mem_ctx);
648 if (strlen(domain->alt_name) == 0) {
649 fstrcpy(domain->alt_name,
650 domain_info->domain_name);
652 if (strlen(domain->forest_name) == 0) {
653 fstrcpy(domain->forest_name,
654 domain_info->forest_name);
658 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
665 /* And restore our original timeout. */
666 rpccli_set_timeout(netlogon_pipe, orig_timeout);
668 if (!NT_STATUS_IS_OK(result)) {
669 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
671 talloc_destroy(mem_ctx);
675 if (!W_ERROR_IS_OK(werr)) {
676 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
678 talloc_destroy(mem_ctx);
682 /* rpccli_netr_GetAnyDCName gives us a name with \\ */
683 p = strip_hostname(tmp);
687 talloc_destroy(mem_ctx);
689 DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
691 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
699 * Helper function to assemble trust password and account name
701 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
702 char **machine_password,
703 char **machine_account,
704 char **machine_krb5_principal)
706 const char *account_name;
707 const char *name = NULL;
709 /* If we are a DC and this is not our own domain */
714 struct winbindd_domain *our_domain = find_our_domain();
717 return NT_STATUS_INVALID_SERVER_STATE;
719 name = our_domain->name;
722 if (!get_trust_pw_clear(name, machine_password,
723 &account_name, NULL))
725 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
728 if ((machine_account != NULL) &&
729 (asprintf(machine_account, "%s$", account_name) == -1))
731 return NT_STATUS_NO_MEMORY;
734 /* For now assume our machine account only exists in our domain */
736 if (machine_krb5_principal != NULL)
738 struct winbindd_domain *our_domain = find_our_domain();
741 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
744 if (asprintf(machine_krb5_principal, "%s$@%s",
745 account_name, our_domain->alt_name) == -1)
747 return NT_STATUS_NO_MEMORY;
750 strupper_m(*machine_krb5_principal);
756 /************************************************************************
757 Given a fd with a just-connected TCP connection to a DC, open a connection
759 ************************************************************************/
761 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
763 const char *controller,
764 struct cli_state **cli,
767 char *machine_password = NULL;
768 char *machine_krb5_principal = NULL;
769 char *machine_account = NULL;
770 char *ipc_username = NULL;
771 char *ipc_domain = NULL;
772 char *ipc_password = NULL;
774 struct named_mutex *mutex;
776 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
778 struct sockaddr peeraddr;
779 socklen_t peeraddr_len;
781 struct sockaddr_in *peeraddr_in =
782 (struct sockaddr_in *)(void *)&peeraddr;
784 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
785 controller, domain->name ));
789 mutex = grab_named_mutex(talloc_tos(), controller,
790 WINBIND_SERVER_MUTEX_WAIT_TIME);
792 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
794 result = NT_STATUS_POSSIBLE_DEADLOCK;
798 if ((*cli = cli_initialise()) == NULL) {
799 DEBUG(1, ("Could not cli_initialize\n"));
800 result = NT_STATUS_NO_MEMORY;
804 (*cli)->timeout = 10000; /* 10 seconds */
806 fstrcpy((*cli)->desthost, controller);
807 (*cli)->use_kerberos = True;
809 peeraddr_len = sizeof(peeraddr);
811 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
812 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
814 result = NT_STATUS_UNSUCCESSFUL;
818 if ((peeraddr_len != sizeof(struct sockaddr_in))
820 && (peeraddr_len != sizeof(struct sockaddr_in6))
823 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
825 result = NT_STATUS_UNSUCCESSFUL;
829 if ((peeraddr_in->sin_family != PF_INET)
831 && (peeraddr_in->sin_family != PF_INET6)
834 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
835 peeraddr_in->sin_family));
836 result = NT_STATUS_UNSUCCESSFUL;
840 if (ntohs(peeraddr_in->sin_port) == 139) {
841 struct nmb_name calling;
842 struct nmb_name called;
844 make_nmb_name(&calling, global_myname(), 0x0);
845 make_nmb_name(&called, "*SMBSERVER", 0x20);
847 if (!cli_session_request(*cli, &calling, &called)) {
848 DEBUG(8, ("cli_session_request failed for %s\n",
850 result = NT_STATUS_UNSUCCESSFUL;
855 result = cli_negprot(*cli);
857 if (!NT_STATUS_IS_OK(result)) {
858 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
862 if (!is_dc_trusted_domain_situation(domain->name) &&
863 (*cli)->protocol >= PROTOCOL_NT1 &&
864 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
866 ADS_STATUS ads_status;
868 result = get_trust_creds(domain, &machine_password,
870 &machine_krb5_principal);
871 if (!NT_STATUS_IS_OK(result)) {
875 if (lp_security() == SEC_ADS) {
877 /* Try a krb5 session */
879 (*cli)->use_kerberos = True;
880 DEBUG(5, ("connecting to %s from %s with kerberos principal "
881 "[%s] and realm [%s]\n", controller, global_myname(),
882 machine_krb5_principal, domain->alt_name));
884 winbindd_set_locator_kdc_envs(domain);
886 ads_status = cli_session_setup_spnego(*cli,
887 machine_krb5_principal,
892 if (!ADS_ERR_OK(ads_status)) {
893 DEBUG(4,("failed kerberos session setup with %s\n",
894 ads_errstr(ads_status)));
897 result = ads_ntstatus(ads_status);
898 if (NT_STATUS_IS_OK(result)) {
899 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
900 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
901 if (!NT_STATUS_IS_OK(result)) {
904 goto session_setup_done;
908 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
909 (*cli)->use_kerberos = False;
911 DEBUG(5, ("connecting to %s from %s with username "
912 "[%s]\\[%s]\n", controller, global_myname(),
913 lp_workgroup(), machine_account));
915 ads_status = cli_session_setup_spnego(*cli,
920 if (!ADS_ERR_OK(ads_status)) {
921 DEBUG(4, ("authenticated session setup failed with %s\n",
922 ads_errstr(ads_status)));
925 result = ads_ntstatus(ads_status);
926 if (NT_STATUS_IS_OK(result)) {
927 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
928 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
929 if (!NT_STATUS_IS_OK(result)) {
932 goto session_setup_done;
936 /* Fall back to non-kerberos session setup with auth_user */
938 (*cli)->use_kerberos = False;
940 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
942 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
943 (strlen(ipc_username) > 0)) {
945 /* Only try authenticated if we have a username */
947 DEBUG(5, ("connecting to %s from %s with username "
948 "[%s]\\[%s]\n", controller, global_myname(),
949 ipc_domain, ipc_username));
951 if (NT_STATUS_IS_OK(cli_session_setup(
953 ipc_password, strlen(ipc_password)+1,
954 ipc_password, strlen(ipc_password)+1,
956 /* Successful logon with given username. */
957 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
958 if (!NT_STATUS_IS_OK(result)) {
961 goto session_setup_done;
963 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
964 ipc_domain, ipc_username ));
970 /* Fall back to anonymous connection, this might fail later */
971 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
972 "connection for DC %s\n",
975 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
977 DEBUG(5, ("Connected anonymously\n"));
978 result = cli_init_creds(*cli, "", "", "");
979 if (!NT_STATUS_IS_OK(result)) {
982 goto session_setup_done;
985 result = cli_nt_error(*cli);
987 if (NT_STATUS_IS_OK(result))
988 result = NT_STATUS_UNSUCCESSFUL;
990 /* We can't session setup */
996 /* cache the server name for later connections */
998 saf_store( domain->name, (*cli)->desthost );
999 if (domain->alt_name && (*cli)->use_kerberos) {
1000 saf_store( domain->alt_name, (*cli)->desthost );
1003 winbindd_set_locator_kdc_envs(domain);
1005 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
1007 if (!NT_STATUS_IS_OK(result)) {
1008 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1015 /* set the domain if empty; needed for schannel connections */
1016 if ( !(*cli)->domain[0] ) {
1017 result = cli_set_domain((*cli), domain->name);
1018 if (!NT_STATUS_IS_OK(result)) {
1023 result = NT_STATUS_OK;
1027 SAFE_FREE(machine_account);
1028 SAFE_FREE(machine_password);
1029 SAFE_FREE(machine_krb5_principal);
1030 SAFE_FREE(ipc_username);
1031 SAFE_FREE(ipc_domain);
1032 SAFE_FREE(ipc_password);
1034 if (!NT_STATUS_IS_OK(result)) {
1035 winbind_add_failed_connection_entry(domain, controller, result);
1036 if ((*cli) != NULL) {
1045 /*******************************************************************
1046 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1049 Keeps the list unique by not adding duplicate entries.
1051 @param[in] mem_ctx talloc memory context to allocate from
1052 @param[in] domain_name domain of the DC
1053 @param[in] dcname name of the DC to add to the list
1054 @param[in] pss Internet address and port pair to add to the list
1055 @param[in,out] dcs array of dc_name_ip structures to add to
1056 @param[in,out] num_dcs number of dcs returned in the dcs array
1057 @return true if the list was added to, false otherwise
1058 *******************************************************************/
1060 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1061 const char *dcname, struct sockaddr_storage *pss,
1062 struct dc_name_ip **dcs, int *num)
1066 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1067 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1071 /* Make sure there's no duplicates in the list */
1072 for (i=0; i<*num; i++)
1074 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1075 (struct sockaddr *)(void *)pss))
1078 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1083 fstrcpy((*dcs)[*num].name, dcname);
1084 (*dcs)[*num].ss = *pss;
1089 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1090 struct sockaddr_storage *pss, uint16 port,
1091 struct sockaddr_storage **addrs, int *num)
1093 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1095 if (*addrs == NULL) {
1100 (*addrs)[*num] = *pss;
1101 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1107 /*******************************************************************
1108 convert an ip to a name
1109 *******************************************************************/
1111 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1112 const struct winbindd_domain *domain,
1113 struct sockaddr_storage *pss,
1116 struct ip_service ip_list;
1117 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1123 /* For active directory servers, try to get the ldap server name.
1124 None of these failures should be considered critical for now */
1126 if (lp_security() == SEC_ADS) {
1128 ADS_STATUS ads_status;
1129 char addr[INET6_ADDRSTRLEN];
1131 print_sockaddr(addr, sizeof(addr), pss);
1133 ads = ads_init(domain->alt_name, domain->name, addr);
1134 ads->auth.flags |= ADS_AUTH_NO_BIND;
1136 ads_status = ads_connect(ads);
1137 if (ADS_ERR_OK(ads_status)) {
1138 /* We got a cldap packet. */
1139 fstrcpy(name, ads->config.ldap_server_name);
1140 namecache_store(name, 0x20, 1, &ip_list);
1142 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1144 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1145 if (ads_closest_dc(ads)) {
1146 char *sitename = sitename_fetch(ads->config.realm);
1148 /* We're going to use this KDC for this realm/domain.
1149 If we are using sites, then force the krb5 libs
1152 create_local_private_krb5_conf_for_domain(domain->alt_name,
1158 SAFE_FREE(sitename);
1160 /* use an off site KDC */
1161 create_local_private_krb5_conf_for_domain(domain->alt_name,
1167 winbindd_set_locator_kdc_envs(domain);
1169 /* Ensure we contact this DC also. */
1170 saf_store( domain->name, name);
1171 saf_store( domain->alt_name, name);
1174 ads_destroy( &ads );
1178 ads_destroy( &ads );
1182 /* try GETDC requests next */
1184 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1185 pss, domain->name, &domain->sid,
1187 const char *dc_name = NULL;
1190 for (i=0; i<5; i++) {
1191 if (receive_getdc_response(mem_ctx, pss, domain->name,
1194 fstrcpy(name, dc_name);
1195 namecache_store(name, 0x20, 1, &ip_list);
1202 /* try node status request */
1204 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1205 namecache_store(name, 0x20, 1, &ip_list);
1211 /*******************************************************************
1212 Retrieve a list of IP addresses for domain controllers.
1214 The array is sorted in the preferred connection order.
1216 @param[in] mem_ctx talloc memory context to allocate from
1217 @param[in] domain domain to retrieve DCs for
1218 @param[out] dcs array of dcs that will be returned
1219 @param[out] num_dcs number of dcs returned in the dcs array
1221 *******************************************************************/
1223 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1224 struct dc_name_ip **dcs, int *num_dcs)
1227 struct sockaddr_storage ss;
1228 struct ip_service *ip_list = NULL;
1229 int iplist_size = 0;
1232 enum security_types sec = (enum security_types)lp_security();
1234 is_our_domain = strequal(domain->name, lp_workgroup());
1236 /* If not our domain, get the preferred DC, by asking our primary DC */
1238 && get_dc_name_via_netlogon(domain, dcname, &ss)
1239 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1242 char addr[INET6_ADDRSTRLEN];
1243 print_sockaddr(addr, sizeof(addr), &ss);
1244 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1249 if (sec == SEC_ADS) {
1250 char *sitename = NULL;
1252 /* We need to make sure we know the local site before
1253 doing any DNS queries, as this will restrict the
1254 get_sorted_dc_list() call below to only fetching
1255 DNS records for the correct site. */
1257 /* Find any DC to get the site record.
1258 We deliberately don't care about the
1261 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1263 sitename = sitename_fetch(domain->alt_name);
1266 /* Do the site-specific AD dns lookup first. */
1267 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1268 &iplist_size, True);
1270 /* Add ips to the DC array. We don't look up the name
1271 of the DC in this function, but we fill in the char*
1272 of the ip now to make the failed connection cache
1274 for ( i=0; i<iplist_size; i++ ) {
1275 char addr[INET6_ADDRSTRLEN];
1276 print_sockaddr(addr, sizeof(addr),
1278 add_one_dc_unique(mem_ctx,
1287 SAFE_FREE(sitename);
1291 /* Now we add DCs from the main AD DNS lookup. */
1292 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1293 &iplist_size, True);
1295 for ( i=0; i<iplist_size; i++ ) {
1296 char addr[INET6_ADDRSTRLEN];
1297 print_sockaddr(addr, sizeof(addr),
1299 add_one_dc_unique(mem_ctx,
1311 /* Try standard netbios queries if no ADS */
1312 if (*num_dcs == 0) {
1313 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1316 for ( i=0; i<iplist_size; i++ ) {
1317 char addr[INET6_ADDRSTRLEN];
1318 print_sockaddr(addr, sizeof(addr),
1320 add_one_dc_unique(mem_ctx,
1335 /*******************************************************************
1336 Find and make a connection to a DC in the given domain.
1338 @param[in] mem_ctx talloc memory context to allocate from
1339 @param[in] domain domain to find a dc in
1340 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1341 @param[out] pss DC Internet address and port
1342 @param[out] fd fd of the open socket connected to the newly found dc
1343 @return true when a DC connection is made, false otherwise
1344 *******************************************************************/
1346 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1347 struct winbindd_domain *domain,
1348 fstring dcname, struct sockaddr_storage *pss, int *fd)
1350 struct dc_name_ip *dcs = NULL;
1353 const char **dcnames = NULL;
1354 int num_dcnames = 0;
1356 struct sockaddr_storage *addrs = NULL;
1364 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1367 for (i=0; i<num_dcs; i++) {
1369 if (!add_string_to_array(mem_ctx, dcs[i].name,
1370 &dcnames, &num_dcnames)) {
1373 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1374 &addrs, &num_addrs)) {
1378 if (!add_string_to_array(mem_ctx, dcs[i].name,
1379 &dcnames, &num_dcnames)) {
1382 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1383 &addrs, &num_addrs)) {
1388 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1391 if ((addrs == NULL) || (dcnames == NULL))
1394 /* 5 second timeout. */
1395 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1396 for (i=0; i<num_dcs; i++) {
1397 char ab[INET6_ADDRSTRLEN];
1398 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1399 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1400 "domain %s address %s. Error was %s\n",
1401 domain->name, ab, strerror(errno) ));
1402 winbind_add_failed_connection_entry(domain,
1403 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1408 *pss = addrs[fd_index];
1410 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1411 /* Ok, we've got a name for the DC */
1412 fstrcpy(dcname, dcnames[fd_index]);
1416 /* Try to figure out the name */
1417 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1421 /* We can not continue without the DC's name */
1422 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1423 NT_STATUS_UNSUCCESSFUL);
1425 /* Throw away all arrays as we're doing this again. */
1429 TALLOC_FREE(dcnames);
1441 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1442 struct winbindd_cm_conn *new_conn)
1444 TALLOC_CTX *mem_ctx;
1446 char *saf_servername = saf_fetch( domain->name );
1449 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1450 SAFE_FREE(saf_servername);
1451 set_domain_offline(domain);
1452 return NT_STATUS_NO_MEMORY;
1455 /* we have to check the server affinity cache here since
1456 later we selecte a DC based on response time and not preference */
1458 /* Check the negative connection cache
1459 before talking to it. It going down may have
1460 triggered the reconnection. */
1462 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1464 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1465 saf_servername, domain->name ));
1467 /* convert an ip address to a name */
1468 if (is_ipaddress( saf_servername ) ) {
1470 struct sockaddr_storage ss;
1472 if (!interpret_string_addr(&ss, saf_servername,
1474 return NT_STATUS_UNSUCCESSFUL;
1476 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1477 fstrcpy( domain->dcname, saf_name );
1479 winbind_add_failed_connection_entry(
1480 domain, saf_servername,
1481 NT_STATUS_UNSUCCESSFUL);
1484 fstrcpy( domain->dcname, saf_servername );
1487 SAFE_FREE( saf_servername );
1490 for (retries = 0; retries < 3; retries++) {
1494 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1496 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1497 domain->dcname, domain->name ));
1500 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1501 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1503 struct sockaddr_storage *addrs = NULL;
1507 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1508 set_domain_offline(domain);
1509 talloc_destroy(mem_ctx);
1510 return NT_STATUS_NO_MEMORY;
1512 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1513 set_domain_offline(domain);
1514 talloc_destroy(mem_ctx);
1515 return NT_STATUS_NO_MEMORY;
1518 /* 5 second timeout. */
1519 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1525 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1527 /* This is the one place where we will
1528 set the global winbindd offline state
1529 to true, if a "WINBINDD_OFFLINE" entry
1530 is found in the winbindd cache. */
1531 set_global_winbindd_state_offline();
1535 new_conn->cli = NULL;
1537 result = cm_prepare_connection(domain, fd, domain->dcname,
1538 &new_conn->cli, &retry);
1544 if (NT_STATUS_IS_OK(result)) {
1546 winbindd_set_locator_kdc_envs(domain);
1548 if (domain->online == False) {
1549 /* We're changing state from offline to online. */
1550 set_global_winbindd_state_online();
1552 set_domain_online(domain);
1554 /* Ensure we setup the retry handler. */
1555 set_domain_offline(domain);
1558 talloc_destroy(mem_ctx);
1562 /* Close down all open pipes on a connection. */
1564 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1566 /* We're closing down a possibly dead
1567 connection. Don't have impossibly long (10s) timeouts. */
1570 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1573 if (conn->samr_pipe != NULL) {
1574 TALLOC_FREE(conn->samr_pipe);
1575 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1577 cli_set_timeout(conn->cli, 500);
1581 if (conn->lsa_pipe != NULL) {
1582 TALLOC_FREE(conn->lsa_pipe);
1583 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1585 cli_set_timeout(conn->cli, 500);
1589 if (conn->lsa_pipe_tcp != NULL) {
1590 TALLOC_FREE(conn->lsa_pipe_tcp);
1591 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1593 cli_set_timeout(conn->cli, 500);
1597 if (conn->netlogon_pipe != NULL) {
1598 TALLOC_FREE(conn->netlogon_pipe);
1599 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1601 cli_set_timeout(conn->cli, 500);
1606 cli_shutdown(conn->cli);
1612 void close_conns_after_fork(void)
1614 struct winbindd_domain *domain;
1616 for (domain = domain_list(); domain; domain = domain->next) {
1617 struct cli_state *cli = domain->conn.cli;
1620 * first close the low level SMB TCP connection
1621 * so that we don't generate any SMBclose
1622 * requests in invalidate_cm_connection()
1624 if (cli && cli->fd != -1) {
1625 close(domain->conn.cli->fd);
1626 domain->conn.cli->fd = -1;
1629 invalidate_cm_connection(&domain->conn);
1633 static bool connection_ok(struct winbindd_domain *domain)
1637 ok = cli_state_is_connected(domain->conn.cli);
1639 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1640 domain->dcname, domain->name));
1644 if (domain->online == False) {
1645 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1652 /* Initialize a new connection up to the RPC BIND.
1653 Bypass online status check so always does network calls. */
1655 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1659 /* Internal connections never use the network. */
1660 if (domain->internal) {
1661 domain->initialized = True;
1662 return NT_STATUS_OK;
1665 if (!winbindd_can_contact_domain(domain)) {
1666 invalidate_cm_connection(&domain->conn);
1667 domain->initialized = True;
1668 return NT_STATUS_OK;
1671 if (connection_ok(domain)) {
1672 if (!domain->initialized) {
1673 set_dc_type_and_flags(domain);
1675 return NT_STATUS_OK;
1678 invalidate_cm_connection(&domain->conn);
1680 result = cm_open_connection(domain, &domain->conn);
1682 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1683 set_dc_type_and_flags(domain);
1689 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1691 if (domain->internal) {
1692 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1695 if (domain->initialized && !domain->online) {
1696 /* We check for online status elsewhere. */
1697 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1700 return init_dc_connection_network(domain);
1703 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1707 status = init_dc_connection(domain);
1708 if (!NT_STATUS_IS_OK(status)) {
1712 if (!domain->internal && domain->conn.cli == NULL) {
1713 /* happens for trusted domains without inbound trust */
1714 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1717 return NT_STATUS_OK;
1720 /******************************************************************************
1721 Set the trust flags (direction and forest location) for a domain
1722 ******************************************************************************/
1724 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1726 struct winbindd_domain *our_domain;
1727 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1728 struct netr_DomainTrustList trusts;
1730 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1731 NETR_TRUST_FLAG_OUTBOUND |
1732 NETR_TRUST_FLAG_INBOUND);
1733 struct rpc_pipe_client *cli;
1734 TALLOC_CTX *mem_ctx = NULL;
1736 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1738 /* Our primary domain doesn't need to worry about trust flags.
1739 Force it to go through the network setup */
1740 if ( domain->primary ) {
1744 our_domain = find_our_domain();
1746 if ( !connection_ok(our_domain) ) {
1747 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1751 /* This won't work unless our domain is AD */
1753 if ( !our_domain->active_directory ) {
1757 /* Use DsEnumerateDomainTrusts to get us the trust direction
1760 result = cm_connect_netlogon(our_domain, &cli);
1762 if (!NT_STATUS_IS_OK(result)) {
1763 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1764 "a connection to %s for PIPE_NETLOGON (%s)\n",
1765 domain->name, nt_errstr(result)));
1769 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1770 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1774 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1779 if (!NT_STATUS_IS_OK(result)) {
1780 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1781 "failed to query trusted domain list: %s\n",
1782 nt_errstr(result)));
1783 talloc_destroy(mem_ctx);
1787 /* Now find the domain name and get the flags */
1789 for ( i=0; i<trusts.count; i++ ) {
1790 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1791 domain->domain_flags = trusts.array[i].trust_flags;
1792 domain->domain_type = trusts.array[i].trust_type;
1793 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1795 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1796 domain->active_directory = True;
1798 /* This flag is only set if the domain is *our*
1799 primary domain and the primary domain is in
1802 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1804 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1805 "native mode.\n", domain->name,
1806 domain->native_mode ? "" : "NOT "));
1808 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1809 "running active directory.\n", domain->name,
1810 domain->active_directory ? "" : "NOT "));
1813 domain->initialized = True;
1819 talloc_destroy( mem_ctx );
1821 return domain->initialized;
1824 /******************************************************************************
1825 We can 'sense' certain things about the DC by it's replies to certain
1828 This tells us if this particular remote server is Active Directory, and if it
1830 ******************************************************************************/
1832 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1836 TALLOC_CTX *mem_ctx = NULL;
1837 struct rpc_pipe_client *cli = NULL;
1838 struct policy_handle pol;
1839 union dssetup_DsRoleInfo info;
1840 union lsa_PolicyInformation *lsa_info = NULL;
1842 if (!connection_ok(domain)) {
1846 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1849 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1853 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1855 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1856 &ndr_table_dssetup.syntax_id,
1859 if (!NT_STATUS_IS_OK(result)) {
1860 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1861 "PI_DSSETUP on domain %s: (%s)\n",
1862 domain->name, nt_errstr(result)));
1864 /* if this is just a non-AD domain we need to continue
1865 * identifying so that we can in the end return with
1866 * domain->initialized = True - gd */
1871 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1872 DS_ROLE_BASIC_INFORMATION,
1877 if (!NT_STATUS_IS_OK(result)) {
1878 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1879 "on domain %s failed: (%s)\n",
1880 domain->name, nt_errstr(result)));
1882 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1883 * every opcode on the DSSETUP pipe, continue with
1884 * no_dssetup mode here as well to get domain->initialized
1887 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1891 TALLOC_FREE(mem_ctx);
1895 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1896 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1897 domain->native_mode = True;
1899 domain->native_mode = False;
1903 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1904 &ndr_table_lsarpc.syntax_id, &cli);
1906 if (!NT_STATUS_IS_OK(result)) {
1907 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1908 "PI_LSARPC on domain %s: (%s)\n",
1909 domain->name, nt_errstr(result)));
1911 TALLOC_FREE(mem_ctx);
1915 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1916 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1918 if (NT_STATUS_IS_OK(result)) {
1919 /* This particular query is exactly what Win2k clients use
1920 to determine that the DC is active directory */
1921 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1923 LSA_POLICY_INFO_DNS,
1927 if (NT_STATUS_IS_OK(result)) {
1928 domain->active_directory = True;
1930 if (lsa_info->dns.name.string) {
1931 fstrcpy(domain->name, lsa_info->dns.name.string);
1934 if (lsa_info->dns.dns_domain.string) {
1935 fstrcpy(domain->alt_name,
1936 lsa_info->dns.dns_domain.string);
1939 /* See if we can set some domain trust flags about
1942 if (lsa_info->dns.dns_forest.string) {
1943 fstrcpy(domain->forest_name,
1944 lsa_info->dns.dns_forest.string);
1946 if (strequal(domain->forest_name, domain->alt_name)) {
1947 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1951 if (lsa_info->dns.sid) {
1952 sid_copy(&domain->sid, lsa_info->dns.sid);
1955 domain->active_directory = False;
1957 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1958 SEC_FLAG_MAXIMUM_ALLOWED,
1961 if (!NT_STATUS_IS_OK(result)) {
1965 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1967 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1970 if (NT_STATUS_IS_OK(result)) {
1972 if (lsa_info->account_domain.name.string) {
1973 fstrcpy(domain->name,
1974 lsa_info->account_domain.name.string);
1977 if (lsa_info->account_domain.sid) {
1978 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1984 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1985 domain->name, domain->native_mode ? "" : "NOT "));
1987 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1988 domain->name, domain->active_directory ? "" : "NOT "));
1990 domain->can_do_ncacn_ip_tcp = domain->active_directory;
1994 TALLOC_FREE(mem_ctx);
1996 domain->initialized = True;
1999 /**********************************************************************
2000 Set the domain_flags (trust attributes, domain operating modes, etc...
2001 ***********************************************************************/
2003 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2005 /* we always have to contact our primary domain */
2007 if ( domain->primary ) {
2008 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2009 "primary domain\n"));
2010 set_dc_type_and_flags_connect( domain );
2014 /* Use our DC to get the information if possible */
2016 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2017 /* Otherwise, fallback to contacting the
2019 set_dc_type_and_flags_connect( domain );
2027 /**********************************************************************
2028 ***********************************************************************/
2030 static bool cm_get_schannel_creds(struct winbindd_domain *domain,
2031 struct netlogon_creds_CredentialState **ppdc)
2034 struct rpc_pipe_client *netlogon_pipe;
2036 if (lp_client_schannel() == False) {
2040 result = cm_connect_netlogon(domain, &netlogon_pipe);
2041 if (!NT_STATUS_IS_OK(result)) {
2045 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2048 if (!domain->conn.netlogon_pipe->dc) {
2052 *ppdc = domain->conn.netlogon_pipe->dc;
2056 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2057 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2059 struct winbindd_cm_conn *conn;
2060 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2061 struct netlogon_creds_CredentialState *p_creds;
2062 char *machine_password = NULL;
2063 char *machine_account = NULL;
2064 char *domain_name = NULL;
2066 result = init_dc_connection_rpc(domain);
2067 if (!NT_STATUS_IS_OK(result)) {
2071 conn = &domain->conn;
2073 if (rpccli_is_connected(conn->samr_pipe)) {
2077 TALLOC_FREE(conn->samr_pipe);
2080 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2081 * sign and sealed pipe using the machine account password by
2082 * preference. If we can't - try schannel, if that fails, try
2086 if ((conn->cli->user_name[0] == '\0') ||
2087 (conn->cli->domain[0] == '\0') ||
2088 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2090 result = get_trust_creds(domain, &machine_password,
2091 &machine_account, NULL);
2092 if (!NT_STATUS_IS_OK(result)) {
2093 DEBUG(10, ("cm_connect_sam: No no user available for "
2094 "domain %s, trying schannel\n", conn->cli->domain));
2097 domain_name = domain->name;
2099 machine_password = SMB_STRDUP(conn->cli->password);
2100 machine_account = SMB_STRDUP(conn->cli->user_name);
2101 domain_name = conn->cli->domain;
2104 if (!machine_password || !machine_account) {
2105 result = NT_STATUS_NO_MEMORY;
2109 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2110 authenticated SAMR pipe with sign & seal. */
2111 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2112 &ndr_table_samr.syntax_id,
2114 DCERPC_AUTH_LEVEL_PRIVACY,
2120 if (!NT_STATUS_IS_OK(result)) {
2121 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2122 "pipe for domain %s using NTLMSSP "
2123 "authenticated pipe: user %s\\%s. Error was "
2124 "%s\n", domain->name, domain_name,
2125 machine_account, nt_errstr(result)));
2129 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2130 "domain %s using NTLMSSP authenticated "
2131 "pipe: user %s\\%s\n", domain->name,
2132 domain_name, machine_account));
2134 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2135 conn->samr_pipe->desthost,
2136 SEC_FLAG_MAXIMUM_ALLOWED,
2137 &conn->sam_connect_handle);
2138 if (NT_STATUS_IS_OK(result)) {
2141 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2142 "failed for domain %s, error was %s. Trying schannel\n",
2143 domain->name, nt_errstr(result) ));
2144 TALLOC_FREE(conn->samr_pipe);
2148 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2150 if (!cm_get_schannel_creds(domain, &p_creds)) {
2151 /* If this call fails - conn->cli can now be NULL ! */
2152 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2153 "for domain %s, trying anon\n", domain->name));
2156 result = cli_rpc_pipe_open_schannel_with_key
2157 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2158 DCERPC_AUTH_LEVEL_PRIVACY,
2159 domain->name, &p_creds, &conn->samr_pipe);
2161 if (!NT_STATUS_IS_OK(result)) {
2162 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2163 "domain %s using schannel. Error was %s\n",
2164 domain->name, nt_errstr(result) ));
2167 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2168 "schannel.\n", domain->name ));
2170 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2171 conn->samr_pipe->desthost,
2172 SEC_FLAG_MAXIMUM_ALLOWED,
2173 &conn->sam_connect_handle);
2174 if (NT_STATUS_IS_OK(result)) {
2177 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2178 "for domain %s, error was %s. Trying anonymous\n",
2179 domain->name, nt_errstr(result) ));
2180 TALLOC_FREE(conn->samr_pipe);
2184 /* Finally fall back to anonymous. */
2185 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2188 if (!NT_STATUS_IS_OK(result)) {
2192 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2193 conn->samr_pipe->desthost,
2194 SEC_FLAG_MAXIMUM_ALLOWED,
2195 &conn->sam_connect_handle);
2196 if (!NT_STATUS_IS_OK(result)) {
2197 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2198 "for domain %s Error was %s\n",
2199 domain->name, nt_errstr(result) ));
2204 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2206 &conn->sam_connect_handle,
2207 SEC_FLAG_MAXIMUM_ALLOWED,
2209 &conn->sam_domain_handle);
2213 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2215 * if we got access denied, we might just have no access rights
2216 * to talk to the remote samr server server (e.g. when we are a
2217 * PDC and we are connecting a w2k8 pdc via an interdomain
2218 * trust). In that case do not invalidate the whole connection
2221 TALLOC_FREE(conn->samr_pipe);
2222 ZERO_STRUCT(conn->sam_domain_handle);
2224 } else if (!NT_STATUS_IS_OK(result)) {
2225 invalidate_cm_connection(conn);
2229 *cli = conn->samr_pipe;
2230 *sam_handle = conn->sam_domain_handle;
2231 SAFE_FREE(machine_password);
2232 SAFE_FREE(machine_account);
2236 /**********************************************************************
2237 open an schanneld ncacn_ip_tcp connection to LSA
2238 ***********************************************************************/
2240 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2241 TALLOC_CTX *mem_ctx,
2242 struct rpc_pipe_client **cli)
2244 struct winbindd_cm_conn *conn;
2247 DEBUG(10,("cm_connect_lsa_tcp\n"));
2249 status = init_dc_connection_rpc(domain);
2250 if (!NT_STATUS_IS_OK(status)) {
2254 conn = &domain->conn;
2256 if (conn->lsa_pipe_tcp &&
2257 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2258 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2259 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2263 TALLOC_FREE(conn->lsa_pipe_tcp);
2265 status = cli_rpc_pipe_open_schannel(conn->cli,
2266 &ndr_table_lsarpc.syntax_id,
2268 DCERPC_AUTH_LEVEL_PRIVACY,
2270 &conn->lsa_pipe_tcp);
2271 if (!NT_STATUS_IS_OK(status)) {
2272 DEBUG(10,("cli_rpc_pipe_open_schannel failed: %s\n",
2273 nt_errstr(status)));
2278 if (!NT_STATUS_IS_OK(status)) {
2279 TALLOC_FREE(conn->lsa_pipe_tcp);
2283 *cli = conn->lsa_pipe_tcp;
2288 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2289 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2291 struct winbindd_cm_conn *conn;
2292 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2293 struct netlogon_creds_CredentialState *p_creds;
2295 result = init_dc_connection_rpc(domain);
2296 if (!NT_STATUS_IS_OK(result))
2299 conn = &domain->conn;
2301 if (rpccli_is_connected(conn->lsa_pipe)) {
2305 TALLOC_FREE(conn->lsa_pipe);
2307 if ((conn->cli->user_name[0] == '\0') ||
2308 (conn->cli->domain[0] == '\0') ||
2309 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2310 DEBUG(10, ("cm_connect_lsa: No no user available for "
2311 "domain %s, trying schannel\n", conn->cli->domain));
2315 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2316 * authenticated LSA pipe with sign & seal. */
2317 result = cli_rpc_pipe_open_spnego_ntlmssp
2318 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2319 DCERPC_AUTH_LEVEL_PRIVACY,
2320 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2323 if (!NT_STATUS_IS_OK(result)) {
2324 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2325 "domain %s using NTLMSSP authenticated pipe: user "
2326 "%s\\%s. Error was %s. Trying schannel.\n",
2327 domain->name, conn->cli->domain,
2328 conn->cli->user_name, nt_errstr(result)));
2332 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2333 "NTLMSSP authenticated pipe: user %s\\%s\n",
2334 domain->name, conn->cli->domain, conn->cli->user_name ));
2336 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2337 SEC_FLAG_MAXIMUM_ALLOWED,
2339 if (NT_STATUS_IS_OK(result)) {
2343 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2346 TALLOC_FREE(conn->lsa_pipe);
2350 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2352 if (!cm_get_schannel_creds(domain, &p_creds)) {
2353 /* If this call fails - conn->cli can now be NULL ! */
2354 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2355 "for domain %s, trying anon\n", domain->name));
2358 result = cli_rpc_pipe_open_schannel_with_key
2359 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2360 DCERPC_AUTH_LEVEL_PRIVACY,
2361 domain->name, &p_creds, &conn->lsa_pipe);
2363 if (!NT_STATUS_IS_OK(result)) {
2364 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2365 "domain %s using schannel. Error was %s\n",
2366 domain->name, nt_errstr(result) ));
2369 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2370 "schannel.\n", domain->name ));
2372 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2373 SEC_FLAG_MAXIMUM_ALLOWED,
2375 if (NT_STATUS_IS_OK(result)) {
2379 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2382 TALLOC_FREE(conn->lsa_pipe);
2386 result = cli_rpc_pipe_open_noauth(conn->cli,
2387 &ndr_table_lsarpc.syntax_id,
2389 if (!NT_STATUS_IS_OK(result)) {
2390 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2394 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2395 SEC_FLAG_MAXIMUM_ALLOWED,
2398 if (!NT_STATUS_IS_OK(result)) {
2399 invalidate_cm_connection(conn);
2403 *cli = conn->lsa_pipe;
2404 *lsa_policy = conn->lsa_policy;
2408 /****************************************************************************
2409 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2410 session key stored in conn->netlogon_pipe->dc->sess_key.
2411 ****************************************************************************/
2413 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2414 struct rpc_pipe_client **cli)
2416 struct winbindd_cm_conn *conn;
2419 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2421 enum netr_SchannelType sec_chan_type;
2422 const char *account_name;
2423 struct rpc_pipe_client *netlogon_pipe = NULL;
2427 result = init_dc_connection_rpc(domain);
2428 if (!NT_STATUS_IS_OK(result)) {
2432 conn = &domain->conn;
2434 if (rpccli_is_connected(conn->netlogon_pipe)) {
2435 *cli = conn->netlogon_pipe;
2436 return NT_STATUS_OK;
2439 TALLOC_FREE(conn->netlogon_pipe);
2441 result = cli_rpc_pipe_open_noauth(conn->cli,
2442 &ndr_table_netlogon.syntax_id,
2444 if (!NT_STATUS_IS_OK(result)) {
2448 if ((!IS_DC) && (!domain->primary)) {
2449 /* Clear the schannel request bit and drop down */
2450 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2454 if (lp_client_schannel() != False) {
2455 neg_flags |= NETLOGON_NEG_SCHANNEL;
2458 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2461 TALLOC_FREE(netlogon_pipe);
2462 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2465 result = rpccli_netlogon_setup_creds(
2467 domain->dcname, /* server name. */
2468 domain->name, /* domain name */
2469 global_myname(), /* client name */
2470 account_name, /* machine account */
2471 mach_pwd, /* machine password */
2472 sec_chan_type, /* from get_trust_pw */
2475 if (!NT_STATUS_IS_OK(result)) {
2476 TALLOC_FREE(netlogon_pipe);
2480 if ((lp_client_schannel() == True) &&
2481 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2482 DEBUG(3, ("Server did not offer schannel\n"));
2483 TALLOC_FREE(netlogon_pipe);
2484 return NT_STATUS_ACCESS_DENIED;
2488 if ((lp_client_schannel() == False) ||
2489 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2491 * NetSamLogonEx only works for schannel
2493 domain->can_do_samlogon_ex = False;
2495 /* We're done - just keep the existing connection to NETLOGON
2497 conn->netlogon_pipe = netlogon_pipe;
2498 *cli = conn->netlogon_pipe;
2499 return NT_STATUS_OK;
2502 /* Using the credentials from the first pipe, open a signed and sealed
2503 second netlogon pipe. The session key is stored in the schannel
2504 part of the new pipe auth struct.
2507 result = cli_rpc_pipe_open_schannel_with_key(
2508 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2509 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2510 &conn->netlogon_pipe);
2512 /* We can now close the initial netlogon pipe. */
2513 TALLOC_FREE(netlogon_pipe);
2515 if (!NT_STATUS_IS_OK(result)) {
2516 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2517 "was %s\n", nt_errstr(result)));
2519 invalidate_cm_connection(conn);
2524 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2525 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2526 * supported). We used to only try SamLogonEx for AD, but
2527 * Samba DCs can also do it. And because we don't distinguish
2528 * between Samba and NT4, always try it once.
2530 domain->can_do_samlogon_ex = true;
2532 *cli = conn->netlogon_pipe;
2533 return NT_STATUS_OK;