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 (peeraddr_len != sizeof(struct sockaddr_in)) ||
813 (peeraddr_in->sin_family != PF_INET))
815 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
816 result = NT_STATUS_UNSUCCESSFUL;
820 if (ntohs(peeraddr_in->sin_port) == 139) {
821 struct nmb_name calling;
822 struct nmb_name called;
824 make_nmb_name(&calling, global_myname(), 0x0);
825 make_nmb_name(&called, "*SMBSERVER", 0x20);
827 if (!cli_session_request(*cli, &calling, &called)) {
828 DEBUG(8, ("cli_session_request failed for %s\n",
830 result = NT_STATUS_UNSUCCESSFUL;
835 result = cli_negprot(*cli);
837 if (!NT_STATUS_IS_OK(result)) {
838 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
842 if (!is_dc_trusted_domain_situation(domain->name) &&
843 (*cli)->protocol >= PROTOCOL_NT1 &&
844 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
846 ADS_STATUS ads_status;
848 result = get_trust_creds(domain, &machine_password,
850 &machine_krb5_principal);
851 if (!NT_STATUS_IS_OK(result)) {
855 if (lp_security() == SEC_ADS) {
857 /* Try a krb5 session */
859 (*cli)->use_kerberos = True;
860 DEBUG(5, ("connecting to %s from %s with kerberos principal "
861 "[%s] and realm [%s]\n", controller, global_myname(),
862 machine_krb5_principal, domain->alt_name));
864 winbindd_set_locator_kdc_envs(domain);
866 ads_status = cli_session_setup_spnego(*cli,
867 machine_krb5_principal,
872 if (!ADS_ERR_OK(ads_status)) {
873 DEBUG(4,("failed kerberos session setup with %s\n",
874 ads_errstr(ads_status)));
877 result = ads_ntstatus(ads_status);
878 if (NT_STATUS_IS_OK(result)) {
879 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
880 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
881 if (!NT_STATUS_IS_OK(result)) {
884 goto session_setup_done;
888 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
889 (*cli)->use_kerberos = False;
891 DEBUG(5, ("connecting to %s from %s with username "
892 "[%s]\\[%s]\n", controller, global_myname(),
893 lp_workgroup(), machine_account));
895 ads_status = cli_session_setup_spnego(*cli,
900 if (!ADS_ERR_OK(ads_status)) {
901 DEBUG(4, ("authenticated session setup failed with %s\n",
902 ads_errstr(ads_status)));
905 result = ads_ntstatus(ads_status);
906 if (NT_STATUS_IS_OK(result)) {
907 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
908 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
909 if (!NT_STATUS_IS_OK(result)) {
912 goto session_setup_done;
916 /* Fall back to non-kerberos session setup with auth_user */
918 (*cli)->use_kerberos = False;
920 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
922 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
923 (strlen(ipc_username) > 0)) {
925 /* Only try authenticated if we have a username */
927 DEBUG(5, ("connecting to %s from %s with username "
928 "[%s]\\[%s]\n", controller, global_myname(),
929 ipc_domain, ipc_username));
931 if (NT_STATUS_IS_OK(cli_session_setup(
933 ipc_password, strlen(ipc_password)+1,
934 ipc_password, strlen(ipc_password)+1,
936 /* Successful logon with given username. */
937 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
938 if (!NT_STATUS_IS_OK(result)) {
941 goto session_setup_done;
943 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
944 ipc_domain, ipc_username ));
950 /* Fall back to anonymous connection, this might fail later */
951 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
952 "connection for DC %s\n",
955 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
957 DEBUG(5, ("Connected anonymously\n"));
958 result = cli_init_creds(*cli, "", "", "");
959 if (!NT_STATUS_IS_OK(result)) {
962 goto session_setup_done;
965 result = cli_nt_error(*cli);
967 if (NT_STATUS_IS_OK(result))
968 result = NT_STATUS_UNSUCCESSFUL;
970 /* We can't session setup */
976 /* cache the server name for later connections */
978 saf_store( domain->name, (*cli)->desthost );
979 if (domain->alt_name && (*cli)->use_kerberos) {
980 saf_store( domain->alt_name, (*cli)->desthost );
983 winbindd_set_locator_kdc_envs(domain);
985 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
987 if (!NT_STATUS_IS_OK(result)) {
988 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
995 /* set the domain if empty; needed for schannel connections */
996 if ( !(*cli)->domain[0] ) {
997 result = cli_set_domain((*cli), domain->name);
998 if (!NT_STATUS_IS_OK(result)) {
1003 result = NT_STATUS_OK;
1007 SAFE_FREE(machine_account);
1008 SAFE_FREE(machine_password);
1009 SAFE_FREE(machine_krb5_principal);
1010 SAFE_FREE(ipc_username);
1011 SAFE_FREE(ipc_domain);
1012 SAFE_FREE(ipc_password);
1014 if (!NT_STATUS_IS_OK(result)) {
1015 winbind_add_failed_connection_entry(domain, controller, result);
1016 if ((*cli) != NULL) {
1025 /*******************************************************************
1026 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1029 Keeps the list unique by not adding duplicate entries.
1031 @param[in] mem_ctx talloc memory context to allocate from
1032 @param[in] domain_name domain of the DC
1033 @param[in] dcname name of the DC to add to the list
1034 @param[in] pss Internet address and port pair to add to the list
1035 @param[in,out] dcs array of dc_name_ip structures to add to
1036 @param[in,out] num_dcs number of dcs returned in the dcs array
1037 @return true if the list was added to, false otherwise
1038 *******************************************************************/
1040 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1041 const char *dcname, struct sockaddr_storage *pss,
1042 struct dc_name_ip **dcs, int *num)
1046 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1047 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1051 /* Make sure there's no duplicates in the list */
1052 for (i=0; i<*num; i++)
1054 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1055 (struct sockaddr *)(void *)pss))
1058 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1063 fstrcpy((*dcs)[*num].name, dcname);
1064 (*dcs)[*num].ss = *pss;
1069 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1070 struct sockaddr_storage *pss, uint16 port,
1071 struct sockaddr_storage **addrs, int *num)
1073 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1075 if (*addrs == NULL) {
1080 (*addrs)[*num] = *pss;
1081 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1087 /*******************************************************************
1088 convert an ip to a name
1089 *******************************************************************/
1091 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1092 const struct winbindd_domain *domain,
1093 struct sockaddr_storage *pss,
1096 struct ip_service ip_list;
1097 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1103 /* For active directory servers, try to get the ldap server name.
1104 None of these failures should be considered critical for now */
1106 if (lp_security() == SEC_ADS) {
1108 ADS_STATUS ads_status;
1109 char addr[INET6_ADDRSTRLEN];
1111 print_sockaddr(addr, sizeof(addr), pss);
1113 ads = ads_init(domain->alt_name, domain->name, addr);
1114 ads->auth.flags |= ADS_AUTH_NO_BIND;
1116 ads_status = ads_connect(ads);
1117 if (ADS_ERR_OK(ads_status)) {
1118 /* We got a cldap packet. */
1119 fstrcpy(name, ads->config.ldap_server_name);
1120 namecache_store(name, 0x20, 1, &ip_list);
1122 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1124 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1125 if (ads_closest_dc(ads)) {
1126 char *sitename = sitename_fetch(ads->config.realm);
1128 /* We're going to use this KDC for this realm/domain.
1129 If we are using sites, then force the krb5 libs
1132 create_local_private_krb5_conf_for_domain(domain->alt_name,
1137 SAFE_FREE(sitename);
1139 /* use an off site KDC */
1140 create_local_private_krb5_conf_for_domain(domain->alt_name,
1145 winbindd_set_locator_kdc_envs(domain);
1147 /* Ensure we contact this DC also. */
1148 saf_store( domain->name, name);
1149 saf_store( domain->alt_name, name);
1152 ads_destroy( &ads );
1156 ads_destroy( &ads );
1160 /* try GETDC requests next */
1162 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1163 pss, domain->name, &domain->sid,
1165 const char *dc_name = NULL;
1168 for (i=0; i<5; i++) {
1169 if (receive_getdc_response(mem_ctx, pss, domain->name,
1172 fstrcpy(name, dc_name);
1173 namecache_store(name, 0x20, 1, &ip_list);
1180 /* try node status request */
1182 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1183 namecache_store(name, 0x20, 1, &ip_list);
1189 /*******************************************************************
1190 Retrieve a list of IP addresses for domain controllers.
1192 The array is sorted in the preferred connection order.
1194 @param[in] mem_ctx talloc memory context to allocate from
1195 @param[in] domain domain to retrieve DCs for
1196 @param[out] dcs array of dcs that will be returned
1197 @param[out] num_dcs number of dcs returned in the dcs array
1199 *******************************************************************/
1201 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1202 struct dc_name_ip **dcs, int *num_dcs)
1205 struct sockaddr_storage ss;
1206 struct ip_service *ip_list = NULL;
1207 int iplist_size = 0;
1210 enum security_types sec = (enum security_types)lp_security();
1212 is_our_domain = strequal(domain->name, lp_workgroup());
1214 /* If not our domain, get the preferred DC, by asking our primary DC */
1216 && get_dc_name_via_netlogon(domain, dcname, &ss)
1217 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1220 char addr[INET6_ADDRSTRLEN];
1221 print_sockaddr(addr, sizeof(addr), &ss);
1222 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1227 if (sec == SEC_ADS) {
1228 char *sitename = NULL;
1230 /* We need to make sure we know the local site before
1231 doing any DNS queries, as this will restrict the
1232 get_sorted_dc_list() call below to only fetching
1233 DNS records for the correct site. */
1235 /* Find any DC to get the site record.
1236 We deliberately don't care about the
1239 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1241 sitename = sitename_fetch(domain->alt_name);
1244 /* Do the site-specific AD dns lookup first. */
1245 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1246 &iplist_size, True);
1248 /* Add ips to the DC array. We don't look up the name
1249 of the DC in this function, but we fill in the char*
1250 of the ip now to make the failed connection cache
1252 for ( i=0; i<iplist_size; i++ ) {
1253 char addr[INET6_ADDRSTRLEN];
1254 print_sockaddr(addr, sizeof(addr),
1256 add_one_dc_unique(mem_ctx,
1265 SAFE_FREE(sitename);
1269 /* Now we add DCs from the main AD DNS lookup. */
1270 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1271 &iplist_size, True);
1273 for ( i=0; i<iplist_size; i++ ) {
1274 char addr[INET6_ADDRSTRLEN];
1275 print_sockaddr(addr, sizeof(addr),
1277 add_one_dc_unique(mem_ctx,
1289 /* Try standard netbios queries if no ADS */
1290 if (*num_dcs == 0) {
1291 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1294 for ( i=0; i<iplist_size; i++ ) {
1295 char addr[INET6_ADDRSTRLEN];
1296 print_sockaddr(addr, sizeof(addr),
1298 add_one_dc_unique(mem_ctx,
1313 /*******************************************************************
1314 Find and make a connection to a DC in the given domain.
1316 @param[in] mem_ctx talloc memory context to allocate from
1317 @param[in] domain domain to find a dc in
1318 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1319 @param[out] pss DC Internet address and port
1320 @param[out] fd fd of the open socket connected to the newly found dc
1321 @return true when a DC connection is made, false otherwise
1322 *******************************************************************/
1324 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1325 struct winbindd_domain *domain,
1326 fstring dcname, struct sockaddr_storage *pss, int *fd)
1328 struct dc_name_ip *dcs = NULL;
1331 const char **dcnames = NULL;
1332 int num_dcnames = 0;
1334 struct sockaddr_storage *addrs = NULL;
1342 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1345 for (i=0; i<num_dcs; i++) {
1347 if (!add_string_to_array(mem_ctx, dcs[i].name,
1348 &dcnames, &num_dcnames)) {
1351 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1352 &addrs, &num_addrs)) {
1356 if (!add_string_to_array(mem_ctx, dcs[i].name,
1357 &dcnames, &num_dcnames)) {
1360 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1361 &addrs, &num_addrs)) {
1366 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1369 if ((addrs == NULL) || (dcnames == NULL))
1372 /* 5 second timeout. */
1373 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1374 for (i=0; i<num_dcs; i++) {
1375 char ab[INET6_ADDRSTRLEN];
1376 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1377 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1378 "domain %s address %s. Error was %s\n",
1379 domain->name, ab, strerror(errno) ));
1380 winbind_add_failed_connection_entry(domain,
1381 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1386 *pss = addrs[fd_index];
1388 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1389 /* Ok, we've got a name for the DC */
1390 fstrcpy(dcname, dcnames[fd_index]);
1394 /* Try to figure out the name */
1395 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1399 /* We can not continue without the DC's name */
1400 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1401 NT_STATUS_UNSUCCESSFUL);
1403 /* Throw away all arrays as we're doing this again. */
1407 TALLOC_FREE(dcnames);
1419 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1420 struct winbindd_cm_conn *new_conn)
1422 TALLOC_CTX *mem_ctx;
1424 char *saf_servername = saf_fetch( domain->name );
1427 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1428 SAFE_FREE(saf_servername);
1429 set_domain_offline(domain);
1430 return NT_STATUS_NO_MEMORY;
1433 /* we have to check the server affinity cache here since
1434 later we selecte a DC based on response time and not preference */
1436 /* Check the negative connection cache
1437 before talking to it. It going down may have
1438 triggered the reconnection. */
1440 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1442 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1443 saf_servername, domain->name ));
1445 /* convert an ip address to a name */
1446 if (is_ipaddress( saf_servername ) ) {
1448 struct sockaddr_storage ss;
1450 if (!interpret_string_addr(&ss, saf_servername,
1452 return NT_STATUS_UNSUCCESSFUL;
1454 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1455 fstrcpy( domain->dcname, saf_name );
1457 winbind_add_failed_connection_entry(
1458 domain, saf_servername,
1459 NT_STATUS_UNSUCCESSFUL);
1462 fstrcpy( domain->dcname, saf_servername );
1465 SAFE_FREE( saf_servername );
1468 for (retries = 0; retries < 3; retries++) {
1472 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1474 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1475 domain->dcname, domain->name ));
1478 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1479 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1481 struct sockaddr_storage *addrs = NULL;
1485 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1486 set_domain_offline(domain);
1487 talloc_destroy(mem_ctx);
1488 return NT_STATUS_NO_MEMORY;
1490 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1491 set_domain_offline(domain);
1492 talloc_destroy(mem_ctx);
1493 return NT_STATUS_NO_MEMORY;
1496 /* 5 second timeout. */
1497 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1503 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1505 /* This is the one place where we will
1506 set the global winbindd offline state
1507 to true, if a "WINBINDD_OFFLINE" entry
1508 is found in the winbindd cache. */
1509 set_global_winbindd_state_offline();
1513 new_conn->cli = NULL;
1515 result = cm_prepare_connection(domain, fd, domain->dcname,
1516 &new_conn->cli, &retry);
1522 if (NT_STATUS_IS_OK(result)) {
1524 winbindd_set_locator_kdc_envs(domain);
1526 if (domain->online == False) {
1527 /* We're changing state from offline to online. */
1528 set_global_winbindd_state_online();
1530 set_domain_online(domain);
1532 /* Ensure we setup the retry handler. */
1533 set_domain_offline(domain);
1536 talloc_destroy(mem_ctx);
1540 /* Close down all open pipes on a connection. */
1542 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1544 /* We're closing down a possibly dead
1545 connection. Don't have impossibly long (10s) timeouts. */
1548 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1551 if (conn->samr_pipe != NULL) {
1552 TALLOC_FREE(conn->samr_pipe);
1553 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1555 cli_set_timeout(conn->cli, 500);
1559 if (conn->lsa_pipe != NULL) {
1560 TALLOC_FREE(conn->lsa_pipe);
1561 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1563 cli_set_timeout(conn->cli, 500);
1567 if (conn->lsa_pipe_tcp != NULL) {
1568 TALLOC_FREE(conn->lsa_pipe_tcp);
1569 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1571 cli_set_timeout(conn->cli, 500);
1575 if (conn->netlogon_pipe != NULL) {
1576 TALLOC_FREE(conn->netlogon_pipe);
1577 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1579 cli_set_timeout(conn->cli, 500);
1584 cli_shutdown(conn->cli);
1590 void close_conns_after_fork(void)
1592 struct winbindd_domain *domain;
1594 for (domain = domain_list(); domain; domain = domain->next) {
1595 struct cli_state *cli = domain->conn.cli;
1598 * first close the low level SMB TCP connection
1599 * so that we don't generate any SMBclose
1600 * requests in invalidate_cm_connection()
1602 if (cli && cli->fd != -1) {
1603 close(domain->conn.cli->fd);
1604 domain->conn.cli->fd = -1;
1607 invalidate_cm_connection(&domain->conn);
1611 static bool connection_ok(struct winbindd_domain *domain)
1615 ok = cli_state_is_connected(domain->conn.cli);
1617 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1618 domain->dcname, domain->name));
1622 if (domain->online == False) {
1623 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1630 /* Initialize a new connection up to the RPC BIND.
1631 Bypass online status check so always does network calls. */
1633 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1637 /* Internal connections never use the network. */
1638 if (domain->internal) {
1639 domain->initialized = True;
1640 return NT_STATUS_OK;
1643 if (!winbindd_can_contact_domain(domain)) {
1644 invalidate_cm_connection(&domain->conn);
1645 domain->initialized = True;
1646 return NT_STATUS_OK;
1649 if (connection_ok(domain)) {
1650 if (!domain->initialized) {
1651 set_dc_type_and_flags(domain);
1653 return NT_STATUS_OK;
1656 invalidate_cm_connection(&domain->conn);
1658 result = cm_open_connection(domain, &domain->conn);
1660 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1661 set_dc_type_and_flags(domain);
1667 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1669 if (domain->internal) {
1670 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1673 if (domain->initialized && !domain->online) {
1674 /* We check for online status elsewhere. */
1675 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1678 return init_dc_connection_network(domain);
1681 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1685 status = init_dc_connection(domain);
1686 if (!NT_STATUS_IS_OK(status)) {
1690 if (!domain->internal && domain->conn.cli == NULL) {
1691 /* happens for trusted domains without inbound trust */
1692 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1695 return NT_STATUS_OK;
1698 /******************************************************************************
1699 Set the trust flags (direction and forest location) for a domain
1700 ******************************************************************************/
1702 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1704 struct winbindd_domain *our_domain;
1705 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1706 struct netr_DomainTrustList trusts;
1708 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1709 NETR_TRUST_FLAG_OUTBOUND |
1710 NETR_TRUST_FLAG_INBOUND);
1711 struct rpc_pipe_client *cli;
1712 TALLOC_CTX *mem_ctx = NULL;
1714 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1716 /* Our primary domain doesn't need to worry about trust flags.
1717 Force it to go through the network setup */
1718 if ( domain->primary ) {
1722 our_domain = find_our_domain();
1724 if ( !connection_ok(our_domain) ) {
1725 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1729 /* This won't work unless our domain is AD */
1731 if ( !our_domain->active_directory ) {
1735 /* Use DsEnumerateDomainTrusts to get us the trust direction
1738 result = cm_connect_netlogon(our_domain, &cli);
1740 if (!NT_STATUS_IS_OK(result)) {
1741 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1742 "a connection to %s for PIPE_NETLOGON (%s)\n",
1743 domain->name, nt_errstr(result)));
1747 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1748 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1752 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1757 if (!NT_STATUS_IS_OK(result)) {
1758 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1759 "failed to query trusted domain list: %s\n",
1760 nt_errstr(result)));
1761 talloc_destroy(mem_ctx);
1765 /* Now find the domain name and get the flags */
1767 for ( i=0; i<trusts.count; i++ ) {
1768 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1769 domain->domain_flags = trusts.array[i].trust_flags;
1770 domain->domain_type = trusts.array[i].trust_type;
1771 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1773 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1774 domain->active_directory = True;
1776 /* This flag is only set if the domain is *our*
1777 primary domain and the primary domain is in
1780 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1782 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1783 "native mode.\n", domain->name,
1784 domain->native_mode ? "" : "NOT "));
1786 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1787 "running active directory.\n", domain->name,
1788 domain->active_directory ? "" : "NOT "));
1791 domain->initialized = True;
1797 talloc_destroy( mem_ctx );
1799 return domain->initialized;
1802 /******************************************************************************
1803 We can 'sense' certain things about the DC by it's replies to certain
1806 This tells us if this particular remote server is Active Directory, and if it
1808 ******************************************************************************/
1810 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1814 TALLOC_CTX *mem_ctx = NULL;
1815 struct rpc_pipe_client *cli = NULL;
1816 struct policy_handle pol;
1817 union dssetup_DsRoleInfo info;
1818 union lsa_PolicyInformation *lsa_info = NULL;
1820 if (!connection_ok(domain)) {
1824 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1827 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1831 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1833 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1834 &ndr_table_dssetup.syntax_id,
1837 if (!NT_STATUS_IS_OK(result)) {
1838 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1839 "PI_DSSETUP on domain %s: (%s)\n",
1840 domain->name, nt_errstr(result)));
1842 /* if this is just a non-AD domain we need to continue
1843 * identifying so that we can in the end return with
1844 * domain->initialized = True - gd */
1849 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1850 DS_ROLE_BASIC_INFORMATION,
1855 if (!NT_STATUS_IS_OK(result)) {
1856 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1857 "on domain %s failed: (%s)\n",
1858 domain->name, nt_errstr(result)));
1860 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1861 * every opcode on the DSSETUP pipe, continue with
1862 * no_dssetup mode here as well to get domain->initialized
1865 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1869 TALLOC_FREE(mem_ctx);
1873 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1874 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1875 domain->native_mode = True;
1877 domain->native_mode = False;
1881 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1882 &ndr_table_lsarpc.syntax_id, &cli);
1884 if (!NT_STATUS_IS_OK(result)) {
1885 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1886 "PI_LSARPC on domain %s: (%s)\n",
1887 domain->name, nt_errstr(result)));
1889 TALLOC_FREE(mem_ctx);
1893 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1894 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1896 if (NT_STATUS_IS_OK(result)) {
1897 /* This particular query is exactly what Win2k clients use
1898 to determine that the DC is active directory */
1899 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1901 LSA_POLICY_INFO_DNS,
1905 if (NT_STATUS_IS_OK(result)) {
1906 domain->active_directory = True;
1908 if (lsa_info->dns.name.string) {
1909 fstrcpy(domain->name, lsa_info->dns.name.string);
1912 if (lsa_info->dns.dns_domain.string) {
1913 fstrcpy(domain->alt_name,
1914 lsa_info->dns.dns_domain.string);
1917 /* See if we can set some domain trust flags about
1920 if (lsa_info->dns.dns_forest.string) {
1921 fstrcpy(domain->forest_name,
1922 lsa_info->dns.dns_forest.string);
1924 if (strequal(domain->forest_name, domain->alt_name)) {
1925 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1929 if (lsa_info->dns.sid) {
1930 sid_copy(&domain->sid, lsa_info->dns.sid);
1933 domain->active_directory = False;
1935 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1936 SEC_FLAG_MAXIMUM_ALLOWED,
1939 if (!NT_STATUS_IS_OK(result)) {
1943 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1945 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1948 if (NT_STATUS_IS_OK(result)) {
1950 if (lsa_info->account_domain.name.string) {
1951 fstrcpy(domain->name,
1952 lsa_info->account_domain.name.string);
1955 if (lsa_info->account_domain.sid) {
1956 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1962 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1963 domain->name, domain->native_mode ? "" : "NOT "));
1965 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1966 domain->name, domain->active_directory ? "" : "NOT "));
1968 domain->can_do_ncacn_ip_tcp = domain->active_directory;
1972 TALLOC_FREE(mem_ctx);
1974 domain->initialized = True;
1977 /**********************************************************************
1978 Set the domain_flags (trust attributes, domain operating modes, etc...
1979 ***********************************************************************/
1981 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1983 /* we always have to contact our primary domain */
1985 if ( domain->primary ) {
1986 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1987 "primary domain\n"));
1988 set_dc_type_and_flags_connect( domain );
1992 /* Use our DC to get the information if possible */
1994 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1995 /* Otherwise, fallback to contacting the
1997 set_dc_type_and_flags_connect( domain );
2005 /**********************************************************************
2006 ***********************************************************************/
2008 static bool cm_get_schannel_creds(struct winbindd_domain *domain,
2009 struct netlogon_creds_CredentialState **ppdc)
2012 struct rpc_pipe_client *netlogon_pipe;
2014 if (lp_client_schannel() == False) {
2018 result = cm_connect_netlogon(domain, &netlogon_pipe);
2019 if (!NT_STATUS_IS_OK(result)) {
2023 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2026 if (!domain->conn.netlogon_pipe->dc) {
2030 *ppdc = domain->conn.netlogon_pipe->dc;
2034 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2035 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2037 struct winbindd_cm_conn *conn;
2038 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2039 struct netlogon_creds_CredentialState *p_creds;
2040 char *machine_password = NULL;
2041 char *machine_account = NULL;
2042 char *domain_name = NULL;
2044 result = init_dc_connection_rpc(domain);
2045 if (!NT_STATUS_IS_OK(result)) {
2049 conn = &domain->conn;
2051 if (rpccli_is_connected(conn->samr_pipe)) {
2055 TALLOC_FREE(conn->samr_pipe);
2058 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2059 * sign and sealed pipe using the machine account password by
2060 * preference. If we can't - try schannel, if that fails, try
2064 if ((conn->cli->user_name[0] == '\0') ||
2065 (conn->cli->domain[0] == '\0') ||
2066 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2068 result = get_trust_creds(domain, &machine_password,
2069 &machine_account, NULL);
2070 if (!NT_STATUS_IS_OK(result)) {
2071 DEBUG(10, ("cm_connect_sam: No no user available for "
2072 "domain %s, trying schannel\n", conn->cli->domain));
2075 domain_name = domain->name;
2077 machine_password = SMB_STRDUP(conn->cli->password);
2078 machine_account = SMB_STRDUP(conn->cli->user_name);
2079 domain_name = conn->cli->domain;
2082 if (!machine_password || !machine_account) {
2083 result = NT_STATUS_NO_MEMORY;
2087 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2088 authenticated SAMR pipe with sign & seal. */
2089 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2090 &ndr_table_samr.syntax_id,
2092 DCERPC_AUTH_LEVEL_PRIVACY,
2098 if (!NT_STATUS_IS_OK(result)) {
2099 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2100 "pipe for domain %s using NTLMSSP "
2101 "authenticated pipe: user %s\\%s. Error was "
2102 "%s\n", domain->name, domain_name,
2103 machine_account, nt_errstr(result)));
2107 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2108 "domain %s using NTLMSSP authenticated "
2109 "pipe: user %s\\%s\n", domain->name,
2110 domain_name, machine_account));
2112 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2113 conn->samr_pipe->desthost,
2114 SEC_FLAG_MAXIMUM_ALLOWED,
2115 &conn->sam_connect_handle);
2116 if (NT_STATUS_IS_OK(result)) {
2119 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2120 "failed for domain %s, error was %s. Trying schannel\n",
2121 domain->name, nt_errstr(result) ));
2122 TALLOC_FREE(conn->samr_pipe);
2126 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2128 if (!cm_get_schannel_creds(domain, &p_creds)) {
2129 /* If this call fails - conn->cli can now be NULL ! */
2130 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2131 "for domain %s, trying anon\n", domain->name));
2134 result = cli_rpc_pipe_open_schannel_with_key
2135 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2136 DCERPC_AUTH_LEVEL_PRIVACY,
2137 domain->name, &p_creds, &conn->samr_pipe);
2139 if (!NT_STATUS_IS_OK(result)) {
2140 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2141 "domain %s using schannel. Error was %s\n",
2142 domain->name, nt_errstr(result) ));
2145 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2146 "schannel.\n", domain->name ));
2148 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2149 conn->samr_pipe->desthost,
2150 SEC_FLAG_MAXIMUM_ALLOWED,
2151 &conn->sam_connect_handle);
2152 if (NT_STATUS_IS_OK(result)) {
2155 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2156 "for domain %s, error was %s. Trying anonymous\n",
2157 domain->name, nt_errstr(result) ));
2158 TALLOC_FREE(conn->samr_pipe);
2162 /* Finally fall back to anonymous. */
2163 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2166 if (!NT_STATUS_IS_OK(result)) {
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)) {
2175 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2176 "for domain %s Error was %s\n",
2177 domain->name, nt_errstr(result) ));
2182 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2184 &conn->sam_connect_handle,
2185 SEC_FLAG_MAXIMUM_ALLOWED,
2187 &conn->sam_domain_handle);
2191 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2193 * if we got access denied, we might just have no access rights
2194 * to talk to the remote samr server server (e.g. when we are a
2195 * PDC and we are connecting a w2k8 pdc via an interdomain
2196 * trust). In that case do not invalidate the whole connection
2199 TALLOC_FREE(conn->samr_pipe);
2200 ZERO_STRUCT(conn->sam_domain_handle);
2202 } else if (!NT_STATUS_IS_OK(result)) {
2203 invalidate_cm_connection(conn);
2207 *cli = conn->samr_pipe;
2208 *sam_handle = conn->sam_domain_handle;
2209 SAFE_FREE(machine_password);
2210 SAFE_FREE(machine_account);
2214 /**********************************************************************
2215 open an schanneld ncacn_ip_tcp connection to LSA
2216 ***********************************************************************/
2218 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2219 TALLOC_CTX *mem_ctx,
2220 struct rpc_pipe_client **cli)
2222 struct winbindd_cm_conn *conn;
2225 DEBUG(10,("cm_connect_lsa_tcp\n"));
2227 status = init_dc_connection_rpc(domain);
2228 if (!NT_STATUS_IS_OK(status)) {
2232 conn = &domain->conn;
2234 if (conn->lsa_pipe_tcp &&
2235 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2236 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2237 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2241 TALLOC_FREE(conn->lsa_pipe_tcp);
2243 status = cli_rpc_pipe_open_schannel(conn->cli,
2244 &ndr_table_lsarpc.syntax_id,
2246 DCERPC_AUTH_LEVEL_PRIVACY,
2248 &conn->lsa_pipe_tcp);
2249 if (!NT_STATUS_IS_OK(status)) {
2250 DEBUG(10,("cli_rpc_pipe_open_schannel failed: %s\n",
2251 nt_errstr(status)));
2256 if (!NT_STATUS_IS_OK(status)) {
2257 TALLOC_FREE(conn->lsa_pipe_tcp);
2261 *cli = conn->lsa_pipe_tcp;
2266 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2267 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2269 struct winbindd_cm_conn *conn;
2270 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2271 struct netlogon_creds_CredentialState *p_creds;
2273 result = init_dc_connection_rpc(domain);
2274 if (!NT_STATUS_IS_OK(result))
2277 conn = &domain->conn;
2279 if (rpccli_is_connected(conn->lsa_pipe)) {
2283 TALLOC_FREE(conn->lsa_pipe);
2285 if ((conn->cli->user_name[0] == '\0') ||
2286 (conn->cli->domain[0] == '\0') ||
2287 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2288 DEBUG(10, ("cm_connect_lsa: No no user available for "
2289 "domain %s, trying schannel\n", conn->cli->domain));
2293 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2294 * authenticated LSA pipe with sign & seal. */
2295 result = cli_rpc_pipe_open_spnego_ntlmssp
2296 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2297 DCERPC_AUTH_LEVEL_PRIVACY,
2298 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2301 if (!NT_STATUS_IS_OK(result)) {
2302 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2303 "domain %s using NTLMSSP authenticated pipe: user "
2304 "%s\\%s. Error was %s. Trying schannel.\n",
2305 domain->name, conn->cli->domain,
2306 conn->cli->user_name, nt_errstr(result)));
2310 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2311 "NTLMSSP authenticated pipe: user %s\\%s\n",
2312 domain->name, conn->cli->domain, conn->cli->user_name ));
2314 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2315 SEC_FLAG_MAXIMUM_ALLOWED,
2317 if (NT_STATUS_IS_OK(result)) {
2321 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2324 TALLOC_FREE(conn->lsa_pipe);
2328 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2330 if (!cm_get_schannel_creds(domain, &p_creds)) {
2331 /* If this call fails - conn->cli can now be NULL ! */
2332 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2333 "for domain %s, trying anon\n", domain->name));
2336 result = cli_rpc_pipe_open_schannel_with_key
2337 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2338 DCERPC_AUTH_LEVEL_PRIVACY,
2339 domain->name, &p_creds, &conn->lsa_pipe);
2341 if (!NT_STATUS_IS_OK(result)) {
2342 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2343 "domain %s using schannel. Error was %s\n",
2344 domain->name, nt_errstr(result) ));
2347 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2348 "schannel.\n", domain->name ));
2350 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2351 SEC_FLAG_MAXIMUM_ALLOWED,
2353 if (NT_STATUS_IS_OK(result)) {
2357 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2360 TALLOC_FREE(conn->lsa_pipe);
2364 result = cli_rpc_pipe_open_noauth(conn->cli,
2365 &ndr_table_lsarpc.syntax_id,
2367 if (!NT_STATUS_IS_OK(result)) {
2368 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2372 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2373 SEC_FLAG_MAXIMUM_ALLOWED,
2376 if (!NT_STATUS_IS_OK(result)) {
2377 invalidate_cm_connection(conn);
2381 *cli = conn->lsa_pipe;
2382 *lsa_policy = conn->lsa_policy;
2386 /****************************************************************************
2387 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2388 session key stored in conn->netlogon_pipe->dc->sess_key.
2389 ****************************************************************************/
2391 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2392 struct rpc_pipe_client **cli)
2394 struct winbindd_cm_conn *conn;
2397 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2399 enum netr_SchannelType sec_chan_type;
2400 const char *account_name;
2401 struct rpc_pipe_client *netlogon_pipe = NULL;
2405 result = init_dc_connection_rpc(domain);
2406 if (!NT_STATUS_IS_OK(result)) {
2410 conn = &domain->conn;
2412 if (rpccli_is_connected(conn->netlogon_pipe)) {
2413 *cli = conn->netlogon_pipe;
2414 return NT_STATUS_OK;
2417 TALLOC_FREE(conn->netlogon_pipe);
2419 result = cli_rpc_pipe_open_noauth(conn->cli,
2420 &ndr_table_netlogon.syntax_id,
2422 if (!NT_STATUS_IS_OK(result)) {
2426 if ((!IS_DC) && (!domain->primary)) {
2427 /* Clear the schannel request bit and drop down */
2428 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2432 if (lp_client_schannel() != False) {
2433 neg_flags |= NETLOGON_NEG_SCHANNEL;
2436 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2439 TALLOC_FREE(netlogon_pipe);
2440 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2443 result = rpccli_netlogon_setup_creds(
2445 domain->dcname, /* server name. */
2446 domain->name, /* domain name */
2447 global_myname(), /* client name */
2448 account_name, /* machine account */
2449 mach_pwd, /* machine password */
2450 sec_chan_type, /* from get_trust_pw */
2453 if (!NT_STATUS_IS_OK(result)) {
2454 TALLOC_FREE(netlogon_pipe);
2458 if ((lp_client_schannel() == True) &&
2459 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2460 DEBUG(3, ("Server did not offer schannel\n"));
2461 TALLOC_FREE(netlogon_pipe);
2462 return NT_STATUS_ACCESS_DENIED;
2466 if ((lp_client_schannel() == False) ||
2467 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2469 * NetSamLogonEx only works for schannel
2471 domain->can_do_samlogon_ex = False;
2473 /* We're done - just keep the existing connection to NETLOGON
2475 conn->netlogon_pipe = netlogon_pipe;
2476 *cli = conn->netlogon_pipe;
2477 return NT_STATUS_OK;
2480 /* Using the credentials from the first pipe, open a signed and sealed
2481 second netlogon pipe. The session key is stored in the schannel
2482 part of the new pipe auth struct.
2485 result = cli_rpc_pipe_open_schannel_with_key(
2486 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2487 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2488 &conn->netlogon_pipe);
2490 /* We can now close the initial netlogon pipe. */
2491 TALLOC_FREE(netlogon_pipe);
2493 if (!NT_STATUS_IS_OK(result)) {
2494 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2495 "was %s\n", nt_errstr(result)));
2497 invalidate_cm_connection(conn);
2502 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2503 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2504 * supported). We used to only try SamLogonEx for AD, but
2505 * Samba DCs can also do it. And because we don't distinguish
2506 * between Samba and NT4, always try it once.
2508 domain->can_do_samlogon_ex = true;
2510 *cli = conn->netlogon_pipe;
2511 return NT_STATUS_OK;