2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
65 #define DBGC_CLASS DBGC_WINBIND
69 struct sockaddr_storage ss;
72 extern struct winbindd_methods reconnect_methods;
73 extern bool override_logfile;
75 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
76 static void set_dc_type_and_flags( struct winbindd_domain *domain );
77 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
78 struct dc_name_ip **dcs, int *num_dcs);
80 /****************************************************************
81 Child failed to find DC's. Reschedule check.
82 ****************************************************************/
84 static void msg_failed_to_go_online(struct messaging_context *msg,
87 struct server_id server_id,
90 struct winbindd_domain *domain;
91 const char *domainname = (const char *)data->data;
93 if (data->data == NULL || data->length == 0) {
97 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
99 for (domain = domain_list(); domain; domain = domain->next) {
100 if (domain->internal) {
104 if (strequal(domain->name, domainname)) {
105 if (domain->online) {
106 /* We're already online, ignore. */
107 DEBUG(5,("msg_fail_to_go_online: domain %s "
108 "already online.\n", domainname));
112 /* Reschedule the online check. */
113 set_domain_offline(domain);
119 /****************************************************************
120 Actually cause a reconnect from a message.
121 ****************************************************************/
123 static void msg_try_to_go_online(struct messaging_context *msg,
126 struct server_id server_id,
129 struct winbindd_domain *domain;
130 const char *domainname = (const char *)data->data;
132 if (data->data == NULL || data->length == 0) {
136 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
138 for (domain = domain_list(); domain; domain = domain->next) {
139 if (domain->internal) {
143 if (strequal(domain->name, domainname)) {
145 if (domain->online) {
146 /* We're already online, ignore. */
147 DEBUG(5,("msg_try_to_go_online: domain %s "
148 "already online.\n", domainname));
152 /* This call takes care of setting the online
153 flag to true if we connected, or re-adding
154 the offline handler if false. Bypasses online
155 check so always does network calls. */
157 init_dc_connection_network(domain);
163 /****************************************************************
164 Fork a child to try and contact a DC. Do this as contacting a
165 DC requires blocking lookups and we don't want to block our
167 ****************************************************************/
169 static bool fork_child_dc_connect(struct winbindd_domain *domain)
171 struct dc_name_ip *dcs = NULL;
173 TALLOC_CTX *mem_ctx = NULL;
174 pid_t parent_pid = sys_getpid();
179 if (domain->dc_probe_pid != (pid_t)-1) {
181 * We might already have a DC probe
182 * child working, check.
184 if (process_exists_by_pid(domain->dc_probe_pid)) {
185 DEBUG(10,("fork_child_dc_connect: pid %u already "
186 "checking for DC's.\n",
187 (unsigned int)domain->dc_probe_pid));
190 domain->dc_probe_pid = (pid_t)-1;
193 domain->dc_probe_pid = sys_fork();
195 if (domain->dc_probe_pid == (pid_t)-1) {
196 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
200 if (domain->dc_probe_pid != (pid_t)0) {
202 messaging_register(winbind_messaging_context(), NULL,
203 MSG_WINBIND_TRY_TO_GO_ONLINE,
204 msg_try_to_go_online);
205 messaging_register(winbind_messaging_context(), NULL,
206 MSG_WINBIND_FAILED_TO_GO_ONLINE,
207 msg_failed_to_go_online);
213 /* Leave messages blocked - we will never process one. */
215 if (!reinit_after_fork(winbind_messaging_context(), true)) {
216 DEBUG(0,("reinit_after_fork() failed\n"));
217 messaging_send_buf(winbind_messaging_context(),
218 pid_to_procid(parent_pid),
219 MSG_WINBIND_FAILED_TO_GO_ONLINE,
220 (uint8 *)domain->name,
221 strlen(domain->name)+1);
225 close_conns_after_fork();
227 if (!override_logfile) {
229 if (asprintf(&logfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) > 0) {
230 lp_set_logfile(logfile);
236 mem_ctx = talloc_init("fork_child_dc_connect");
238 DEBUG(0,("talloc_init failed.\n"));
239 messaging_send_buf(winbind_messaging_context(),
240 pid_to_procid(parent_pid),
241 MSG_WINBIND_FAILED_TO_GO_ONLINE,
242 (uint8 *)domain->name,
243 strlen(domain->name)+1);
247 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
248 /* Still offline ? Can't find DC's. */
249 messaging_send_buf(winbind_messaging_context(),
250 pid_to_procid(parent_pid),
251 MSG_WINBIND_FAILED_TO_GO_ONLINE,
252 (uint8 *)domain->name,
253 strlen(domain->name)+1);
257 /* We got a DC. Send a message to our parent to get it to
258 try and do the same. */
260 messaging_send_buf(winbind_messaging_context(),
261 pid_to_procid(parent_pid),
262 MSG_WINBIND_TRY_TO_GO_ONLINE,
263 (uint8 *)domain->name,
264 strlen(domain->name)+1);
268 /****************************************************************
269 Handler triggered if we're offline to try and detect a DC.
270 ****************************************************************/
272 static void check_domain_online_handler(struct event_context *ctx,
273 struct timed_event *te,
274 const struct timeval *now,
277 struct winbindd_domain *domain =
278 (struct winbindd_domain *)private_data;
280 DEBUG(10,("check_domain_online_handler: called for domain "
281 "%s (online = %s)\n", domain->name,
282 domain->online ? "True" : "False" ));
284 TALLOC_FREE(domain->check_online_event);
286 /* Are we still in "startup" mode ? */
288 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
289 /* No longer in "startup" mode. */
290 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
292 domain->startup = False;
295 /* We've been told to stay offline, so stay
298 if (get_global_winbindd_state_offline()) {
299 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
304 /* Fork a child to test if it can contact a DC.
305 If it can then send ourselves a message to
306 cause a reconnect. */
308 fork_child_dc_connect(domain);
311 /****************************************************************
312 If we're still offline setup the timeout check.
313 ****************************************************************/
315 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
317 int wbr = lp_winbind_reconnect_delay();
319 if (domain->startup) {
320 domain->check_online_timeout = 10;
321 } else if (domain->check_online_timeout < wbr) {
322 domain->check_online_timeout = wbr;
326 /****************************************************************
327 Set domain offline and also add handler to put us back online
329 ****************************************************************/
331 void set_domain_offline(struct winbindd_domain *domain)
333 DEBUG(10,("set_domain_offline: called for domain %s\n",
336 TALLOC_FREE(domain->check_online_event);
338 if (domain->internal) {
339 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
344 domain->online = False;
346 /* Offline domains are always initialized. They're
347 re-initialized when they go back online. */
349 domain->initialized = True;
351 /* We only add the timeout handler that checks and
352 allows us to go back online when we've not
353 been told to remain offline. */
355 if (get_global_winbindd_state_offline()) {
356 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
361 /* If we're in statup mode, check again in 10 seconds, not in
362 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
364 calc_new_online_timeout_check(domain);
366 domain->check_online_event = event_add_timed(winbind_event_context(),
368 timeval_current_ofs(domain->check_online_timeout,0),
369 "check_domain_online_handler",
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)
407 DEBUG(10,("set_domain_online: called for domain %s\n",
410 if (domain->internal) {
411 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
416 if (get_global_winbindd_state_offline()) {
417 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
422 winbindd_set_locator_kdc_envs(domain);
424 /* If we are waiting to get a krb5 ticket, trigger immediately. */
426 set_event_dispatch_time(winbind_event_context(),
427 "krb5_ticket_gain_handler", now);
429 /* Ok, we're out of any startup mode now... */
430 domain->startup = False;
432 if (domain->online == False) {
433 /* We were offline - now we're online. We default to
434 using the MS-RPC backend if we started offline,
435 and if we're going online for the first time we
436 should really re-initialize the backends and the
437 checks to see if we're talking to an AD or NT domain.
440 domain->initialized = False;
442 /* 'reconnect_methods' is the MS-RPC backend. */
443 if (domain->backend == &reconnect_methods) {
444 domain->backend = NULL;
448 /* Ensure we have no online timeout checks. */
449 domain->check_online_timeout = 0;
450 TALLOC_FREE(domain->check_online_event);
452 /* Ensure we ignore any pending child messages. */
453 messaging_deregister(winbind_messaging_context(),
454 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
455 messaging_deregister(winbind_messaging_context(),
456 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
458 domain->online = True;
460 /* Send an online message to the idmap child when our
461 primary domain comes online */
463 if ( domain->primary ) {
464 struct winbindd_child *idmap = idmap_child();
466 if ( idmap->pid != 0 ) {
467 messaging_send_buf(winbind_messaging_context(),
468 pid_to_procid(idmap->pid),
470 (uint8 *)domain->name,
471 strlen(domain->name)+1);
478 /****************************************************************
479 Requested to set a domain online.
480 ****************************************************************/
482 void set_domain_online_request(struct winbindd_domain *domain)
486 DEBUG(10,("set_domain_online_request: called for domain %s\n",
489 if (get_global_winbindd_state_offline()) {
490 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
495 /* We've been told it's safe to go online and
496 try and connect to a DC. But I don't believe it
497 because network manager seems to lie.
498 Wait at least 5 seconds. Heuristics suck... */
500 if (!domain->check_online_event) {
501 /* If we've come from being globally offline we
502 don't have a check online event handler set.
503 We need to add one now we're trying to go
506 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
509 domain->check_online_event = event_add_timed(winbind_event_context(),
511 timeval_current_ofs(5, 0),
512 "check_domain_online_handler",
513 check_domain_online_handler,
516 /* The above *has* to succeed for winbindd to work. */
517 if (!domain->check_online_event) {
518 smb_panic("set_domain_online_request: failed to add online handler");
524 /* Go into "startup" mode again. */
525 domain->startup_time = tev.tv_sec;
526 domain->startup = True;
530 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
533 /****************************************************************
534 Add -ve connection cache entries for domain and realm.
535 ****************************************************************/
537 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
541 add_failed_connection_entry(domain->name, server, result);
542 /* If this was the saf name for the last thing we talked to,
544 saf_delete(domain->name);
545 if (*domain->alt_name) {
546 add_failed_connection_entry(domain->alt_name, server, result);
547 saf_delete(domain->alt_name);
549 winbindd_unset_locator_kdc_env(domain);
552 /* Choose between anonymous or authenticated connections. We need to use
553 an authenticated connection if DCs have the RestrictAnonymous registry
554 entry set > 0, or the "Additional restrictions for anonymous
555 connections" set in the win2k Local Security Policy.
557 Caller to free() result in domain, username, password
560 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
562 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
563 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
564 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
566 if (*username && **username) {
568 if (!*domain || !**domain)
569 *domain = smb_xstrdup(lp_workgroup());
571 if (!*password || !**password)
572 *password = smb_xstrdup("");
574 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
575 *domain, *username));
578 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
579 *username = smb_xstrdup("");
580 *domain = smb_xstrdup("");
581 *password = smb_xstrdup("");
585 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
587 struct sockaddr_storage *dc_ss)
589 struct winbindd_domain *our_domain = NULL;
590 struct rpc_pipe_client *netlogon_pipe = NULL;
594 unsigned int orig_timeout;
595 const char *tmp = NULL;
598 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
605 if (domain->primary) {
609 our_domain = find_our_domain();
611 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
615 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
616 if (!NT_STATUS_IS_OK(result)) {
617 talloc_destroy(mem_ctx);
621 /* This call can take a long time - allow the server to time out.
622 35 seconds should do it. */
624 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
626 if (our_domain->active_directory) {
627 struct netr_DsRGetDCNameInfo *domain_info = NULL;
629 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
638 if (W_ERROR_IS_OK(werr)) {
640 mem_ctx, domain_info->dc_unc);
642 DEBUG(0, ("talloc_strdup failed\n"));
643 talloc_destroy(mem_ctx);
646 if (strlen(domain->alt_name) == 0) {
647 fstrcpy(domain->alt_name,
648 domain_info->domain_name);
650 if (strlen(domain->forest_name) == 0) {
651 fstrcpy(domain->forest_name,
652 domain_info->forest_name);
656 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
663 /* And restore our original timeout. */
664 rpccli_set_timeout(netlogon_pipe, orig_timeout);
666 if (!NT_STATUS_IS_OK(result)) {
667 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
669 talloc_destroy(mem_ctx);
673 if (!W_ERROR_IS_OK(werr)) {
674 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
676 talloc_destroy(mem_ctx);
680 /* rpccli_netr_GetAnyDCName gives us a name with \\ */
681 p = strip_hostname(tmp);
685 talloc_destroy(mem_ctx);
687 DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
689 if (!resolve_name(dcname, dc_ss, 0x20)) {
697 * Helper function to assemble trust password and account name
699 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
700 char **machine_password,
701 char **machine_account,
702 char **machine_krb5_principal)
704 const char *account_name;
705 const char *name = NULL;
707 /* If we are a DC and this is not our own domain */
712 struct winbindd_domain *our_domain = find_our_domain();
715 return NT_STATUS_INVALID_SERVER_STATE;
717 name = our_domain->name;
720 if (!get_trust_pw_clear(name, machine_password,
721 &account_name, NULL))
723 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
726 if ((machine_account != NULL) &&
727 (asprintf(machine_account, "%s$", account_name) == -1))
729 return NT_STATUS_NO_MEMORY;
732 /* For now assume our machine account only exists in our domain */
734 if (machine_krb5_principal != NULL)
736 struct winbindd_domain *our_domain = find_our_domain();
739 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
742 if (asprintf(machine_krb5_principal, "%s$@%s",
743 account_name, our_domain->alt_name) == -1)
745 return NT_STATUS_NO_MEMORY;
748 strupper_m(*machine_krb5_principal);
754 /************************************************************************
755 Given a fd with a just-connected TCP connection to a DC, open a connection
757 ************************************************************************/
759 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
761 const char *controller,
762 struct cli_state **cli,
765 char *machine_password = NULL;
766 char *machine_krb5_principal = NULL;
767 char *machine_account = NULL;
768 char *ipc_username = NULL;
769 char *ipc_domain = NULL;
770 char *ipc_password = NULL;
772 struct named_mutex *mutex;
774 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
776 struct sockaddr peeraddr;
777 socklen_t peeraddr_len;
779 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
781 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
782 controller, domain->name ));
786 mutex = grab_named_mutex(talloc_tos(), controller,
787 WINBIND_SERVER_MUTEX_WAIT_TIME);
789 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
791 result = NT_STATUS_POSSIBLE_DEADLOCK;
795 if ((*cli = cli_initialise()) == NULL) {
796 DEBUG(1, ("Could not cli_initialize\n"));
797 result = NT_STATUS_NO_MEMORY;
801 (*cli)->timeout = 10000; /* 10 seconds */
803 fstrcpy((*cli)->desthost, controller);
804 (*cli)->use_kerberos = True;
806 peeraddr_len = sizeof(peeraddr);
808 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
809 (peeraddr_len != sizeof(struct sockaddr_in)) ||
810 (peeraddr_in->sin_family != PF_INET))
812 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
813 result = NT_STATUS_UNSUCCESSFUL;
817 if (ntohs(peeraddr_in->sin_port) == 139) {
818 struct nmb_name calling;
819 struct nmb_name called;
821 make_nmb_name(&calling, global_myname(), 0x0);
822 make_nmb_name(&called, "*SMBSERVER", 0x20);
824 if (!cli_session_request(*cli, &calling, &called)) {
825 DEBUG(8, ("cli_session_request failed for %s\n",
827 result = NT_STATUS_UNSUCCESSFUL;
832 cli_setup_signing_state(*cli, Undefined);
834 if (!cli_negprot(*cli)) {
835 DEBUG(1, ("cli_negprot failed\n"));
836 result = NT_STATUS_UNSUCCESSFUL;
840 if (!is_dc_trusted_domain_situation(domain->name) &&
841 (*cli)->protocol >= PROTOCOL_NT1 &&
842 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
844 ADS_STATUS ads_status;
846 result = get_trust_creds(domain, &machine_password,
848 &machine_krb5_principal);
849 if (!NT_STATUS_IS_OK(result)) {
853 if (lp_security() == SEC_ADS) {
855 /* Try a krb5 session */
857 (*cli)->use_kerberos = True;
858 DEBUG(5, ("connecting to %s from %s with kerberos principal "
859 "[%s] and realm [%s]\n", controller, global_myname(),
860 machine_krb5_principal, domain->alt_name));
862 winbindd_set_locator_kdc_envs(domain);
864 ads_status = cli_session_setup_spnego(*cli,
865 machine_krb5_principal,
870 if (!ADS_ERR_OK(ads_status)) {
871 DEBUG(4,("failed kerberos session setup with %s\n",
872 ads_errstr(ads_status)));
875 result = ads_ntstatus(ads_status);
876 if (NT_STATUS_IS_OK(result)) {
877 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
878 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
879 goto session_setup_done;
883 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
884 (*cli)->use_kerberos = False;
886 DEBUG(5, ("connecting to %s from %s with username "
887 "[%s]\\[%s]\n", controller, global_myname(),
888 lp_workgroup(), machine_account));
890 ads_status = cli_session_setup_spnego(*cli,
895 if (!ADS_ERR_OK(ads_status)) {
896 DEBUG(4, ("authenticated session setup failed with %s\n",
897 ads_errstr(ads_status)));
900 result = ads_ntstatus(ads_status);
901 if (NT_STATUS_IS_OK(result)) {
902 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
903 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
904 goto session_setup_done;
908 /* Fall back to non-kerberos session setup with auth_user */
910 (*cli)->use_kerberos = False;
912 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
914 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
915 (strlen(ipc_username) > 0)) {
917 /* Only try authenticated if we have a username */
919 DEBUG(5, ("connecting to %s from %s with username "
920 "[%s]\\[%s]\n", controller, global_myname(),
921 ipc_domain, ipc_username));
923 if (NT_STATUS_IS_OK(cli_session_setup(
925 ipc_password, strlen(ipc_password)+1,
926 ipc_password, strlen(ipc_password)+1,
928 /* Successful logon with given username. */
929 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
930 goto session_setup_done;
932 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
933 ipc_domain, ipc_username ));
939 /* Fall back to anonymous connection, this might fail later */
940 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
941 "connection for DC %s\n",
944 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
946 DEBUG(5, ("Connected anonymously\n"));
947 cli_init_creds(*cli, "", "", "");
948 goto session_setup_done;
951 result = cli_nt_error(*cli);
953 if (NT_STATUS_IS_OK(result))
954 result = NT_STATUS_UNSUCCESSFUL;
956 /* We can't session setup */
962 /* cache the server name for later connections */
964 saf_store( domain->name, (*cli)->desthost );
965 if (domain->alt_name && (*cli)->use_kerberos) {
966 saf_store( domain->alt_name, (*cli)->desthost );
969 winbindd_set_locator_kdc_envs(domain);
971 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
973 result = cli_nt_error(*cli);
975 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
977 if (NT_STATUS_IS_OK(result))
978 result = NT_STATUS_UNSUCCESSFUL;
986 /* set the domain if empty; needed for schannel connections */
987 if ( !*(*cli)->domain ) {
988 fstrcpy( (*cli)->domain, domain->name );
991 result = NT_STATUS_OK;
995 SAFE_FREE(machine_account);
996 SAFE_FREE(machine_password);
997 SAFE_FREE(machine_krb5_principal);
998 SAFE_FREE(ipc_username);
999 SAFE_FREE(ipc_domain);
1000 SAFE_FREE(ipc_password);
1002 if (!NT_STATUS_IS_OK(result)) {
1003 winbind_add_failed_connection_entry(domain, controller, result);
1004 if ((*cli) != NULL) {
1013 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1014 const char *dcname, struct sockaddr_storage *pss,
1015 struct dc_name_ip **dcs, int *num)
1017 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1018 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1022 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1027 fstrcpy((*dcs)[*num].name, dcname);
1028 (*dcs)[*num].ss = *pss;
1033 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1034 struct sockaddr_storage *pss, uint16 port,
1035 struct sockaddr_storage **addrs, int *num)
1037 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1039 if (*addrs == NULL) {
1044 (*addrs)[*num] = *pss;
1045 set_sockaddr_port(&(*addrs)[*num], port);
1051 /*******************************************************************
1052 convert an ip to a name
1053 *******************************************************************/
1055 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1056 const struct winbindd_domain *domain,
1057 struct sockaddr_storage *pss,
1060 struct ip_service ip_list;
1061 uint32_t nt_version = NETLOGON_VERSION_1;
1067 /* For active directory servers, try to get the ldap server name.
1068 None of these failures should be considered critical for now */
1070 if (lp_security() == SEC_ADS) {
1072 ADS_STATUS ads_status;
1073 char addr[INET6_ADDRSTRLEN];
1075 print_sockaddr(addr, sizeof(addr), pss);
1077 ads = ads_init(domain->alt_name, domain->name, addr);
1078 ads->auth.flags |= ADS_AUTH_NO_BIND;
1080 ads_status = ads_connect(ads);
1081 if (ADS_ERR_OK(ads_status)) {
1082 /* We got a cldap packet. */
1083 fstrcpy(name, ads->config.ldap_server_name);
1084 namecache_store(name, 0x20, 1, &ip_list);
1086 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1088 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1089 if (ads_closest_dc(ads)) {
1090 char *sitename = sitename_fetch(ads->config.realm);
1092 /* We're going to use this KDC for this realm/domain.
1093 If we are using sites, then force the krb5 libs
1096 create_local_private_krb5_conf_for_domain(domain->alt_name,
1101 SAFE_FREE(sitename);
1103 /* use an off site KDC */
1104 create_local_private_krb5_conf_for_domain(domain->alt_name,
1109 winbindd_set_locator_kdc_envs(domain);
1111 /* Ensure we contact this DC also. */
1112 saf_store( domain->name, name);
1113 saf_store( domain->alt_name, name);
1116 ads_destroy( &ads );
1120 ads_destroy( &ads );
1124 /* try GETDC requests next */
1126 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1127 pss, domain->name, &domain->sid,
1129 const char *dc_name = NULL;
1132 for (i=0; i<5; i++) {
1133 if (receive_getdc_response(mem_ctx, pss, domain->name,
1136 fstrcpy(name, dc_name);
1137 namecache_store(name, 0x20, 1, &ip_list);
1144 /* try node status request */
1146 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1147 namecache_store(name, 0x20, 1, &ip_list);
1153 /*******************************************************************
1154 Retreive a list of IP address for domain controllers. Fill in
1155 the dcs[] with results.
1156 *******************************************************************/
1158 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1159 struct dc_name_ip **dcs, int *num_dcs)
1162 struct sockaddr_storage ss;
1163 struct ip_service *ip_list = NULL;
1164 int iplist_size = 0;
1167 enum security_types sec = (enum security_types)lp_security();
1169 is_our_domain = strequal(domain->name, lp_workgroup());
1172 && get_dc_name_via_netlogon(domain, dcname, &ss)
1173 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs, num_dcs) )
1175 char addr[INET6_ADDRSTRLEN];
1176 print_sockaddr(addr, sizeof(addr), &ss);
1177 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1182 if (sec == SEC_ADS) {
1183 char *sitename = NULL;
1185 /* We need to make sure we know the local site before
1186 doing any DNS queries, as this will restrict the
1187 get_sorted_dc_list() call below to only fetching
1188 DNS records for the correct site. */
1190 /* Find any DC to get the site record.
1191 We deliberately don't care about the
1194 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1196 sitename = sitename_fetch(domain->alt_name);
1199 /* Do the site-specific AD dns lookup first. */
1200 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1202 for ( i=0; i<iplist_size; i++ ) {
1203 char addr[INET6_ADDRSTRLEN];
1204 print_sockaddr(addr, sizeof(addr),
1206 add_one_dc_unique(mem_ctx,
1215 SAFE_FREE(sitename);
1219 /* Now we add DCs from the main AD dns lookup. */
1220 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1222 for ( i=0; i<iplist_size; i++ ) {
1223 char addr[INET6_ADDRSTRLEN];
1224 print_sockaddr(addr, sizeof(addr),
1226 add_one_dc_unique(mem_ctx,
1235 /* try standard netbios queries if no ADS */
1237 if (iplist_size==0) {
1238 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1241 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1243 /* now add to the dc array. We'll wait until the last minute
1244 to look up the name of the DC. But we fill in the char* for
1245 the ip now in to make the failed connection cache work */
1247 for ( i=0; i<iplist_size; i++ ) {
1248 char addr[INET6_ADDRSTRLEN];
1249 print_sockaddr(addr, sizeof(addr),
1251 add_one_dc_unique(mem_ctx, domain->name, addr,
1252 &ip_list[i].ss, dcs, num_dcs);
1255 SAFE_FREE( ip_list );
1260 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1261 struct winbindd_domain *domain,
1262 fstring dcname, struct sockaddr_storage *pss, int *fd)
1264 struct dc_name_ip *dcs = NULL;
1267 const char **dcnames = NULL;
1268 int num_dcnames = 0;
1270 struct sockaddr_storage *addrs = NULL;
1278 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1281 for (i=0; i<num_dcs; i++) {
1283 if (!add_string_to_array(mem_ctx, dcs[i].name,
1284 &dcnames, &num_dcnames)) {
1287 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1288 &addrs, &num_addrs)) {
1292 if (!add_string_to_array(mem_ctx, dcs[i].name,
1293 &dcnames, &num_dcnames)) {
1296 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1297 &addrs, &num_addrs)) {
1302 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1305 if ((addrs == NULL) || (dcnames == NULL))
1308 /* 5 second timeout. */
1309 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1310 for (i=0; i<num_dcs; i++) {
1311 char ab[INET6_ADDRSTRLEN];
1312 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1313 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1314 "domain %s address %s. Error was %s\n",
1315 domain->name, ab, strerror(errno) ));
1316 winbind_add_failed_connection_entry(domain,
1317 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1322 *pss = addrs[fd_index];
1324 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1325 /* Ok, we've got a name for the DC */
1326 fstrcpy(dcname, dcnames[fd_index]);
1330 /* Try to figure out the name */
1331 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1335 /* We can not continue without the DC's name */
1336 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1337 NT_STATUS_UNSUCCESSFUL);
1339 /* Throw away all arrays as we're doing this again. */
1343 TALLOC_FREE(dcnames);
1355 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1356 struct winbindd_cm_conn *new_conn)
1358 TALLOC_CTX *mem_ctx;
1360 char *saf_servername = saf_fetch( domain->name );
1363 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1364 SAFE_FREE(saf_servername);
1365 set_domain_offline(domain);
1366 return NT_STATUS_NO_MEMORY;
1369 /* we have to check the server affinity cache here since
1370 later we selecte a DC based on response time and not preference */
1372 /* Check the negative connection cache
1373 before talking to it. It going down may have
1374 triggered the reconnection. */
1376 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1378 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1379 saf_servername, domain->name ));
1381 /* convert an ip address to a name */
1382 if (is_ipaddress( saf_servername ) ) {
1384 struct sockaddr_storage ss;
1386 if (!interpret_string_addr(&ss, saf_servername,
1388 return NT_STATUS_UNSUCCESSFUL;
1390 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1391 fstrcpy( domain->dcname, saf_name );
1393 winbind_add_failed_connection_entry(
1394 domain, saf_servername,
1395 NT_STATUS_UNSUCCESSFUL);
1398 fstrcpy( domain->dcname, saf_servername );
1401 SAFE_FREE( saf_servername );
1404 for (retries = 0; retries < 3; retries++) {
1408 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1410 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1411 domain->dcname, domain->name ));
1414 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1415 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1417 struct sockaddr_storage *addrs = NULL;
1421 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1422 set_domain_offline(domain);
1423 talloc_destroy(mem_ctx);
1424 return NT_STATUS_NO_MEMORY;
1426 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1427 set_domain_offline(domain);
1428 talloc_destroy(mem_ctx);
1429 return NT_STATUS_NO_MEMORY;
1432 /* 5 second timeout. */
1433 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1439 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1441 /* This is the one place where we will
1442 set the global winbindd offline state
1443 to true, if a "WINBINDD_OFFLINE" entry
1444 is found in the winbindd cache. */
1445 set_global_winbindd_state_offline();
1449 new_conn->cli = NULL;
1451 result = cm_prepare_connection(domain, fd, domain->dcname,
1452 &new_conn->cli, &retry);
1458 if (NT_STATUS_IS_OK(result)) {
1460 winbindd_set_locator_kdc_envs(domain);
1462 if (domain->online == False) {
1463 /* We're changing state from offline to online. */
1464 set_global_winbindd_state_online();
1466 set_domain_online(domain);
1468 /* Ensure we setup the retry handler. */
1469 set_domain_offline(domain);
1472 talloc_destroy(mem_ctx);
1476 /* Close down all open pipes on a connection. */
1478 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1480 /* We're closing down a possibly dead
1481 connection. Don't have impossibly long (10s) timeouts. */
1484 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1487 if (conn->samr_pipe != NULL) {
1488 TALLOC_FREE(conn->samr_pipe);
1489 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1491 cli_set_timeout(conn->cli, 500);
1495 if (conn->lsa_pipe != NULL) {
1496 TALLOC_FREE(conn->lsa_pipe);
1497 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1499 cli_set_timeout(conn->cli, 500);
1503 if (conn->netlogon_pipe != NULL) {
1504 TALLOC_FREE(conn->netlogon_pipe);
1505 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1507 cli_set_timeout(conn->cli, 500);
1512 cli_shutdown(conn->cli);
1518 void close_conns_after_fork(void)
1520 struct winbindd_domain *domain;
1522 for (domain = domain_list(); domain; domain = domain->next) {
1523 if (domain->conn.cli == NULL)
1526 if (domain->conn.cli->fd == -1)
1529 close(domain->conn.cli->fd);
1530 domain->conn.cli->fd = -1;
1534 static bool connection_ok(struct winbindd_domain *domain)
1536 if (domain->conn.cli == NULL) {
1537 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1538 "cli!\n", domain->dcname, domain->name));
1542 if (!domain->conn.cli->initialised) {
1543 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1544 "initialised!\n", domain->dcname, domain->name));
1548 if (domain->conn.cli->fd == -1) {
1549 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1550 "never started (fd == -1)\n",
1551 domain->dcname, domain->name));
1555 if (domain->online == False) {
1556 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1563 /* Initialize a new connection up to the RPC BIND.
1564 Bypass online status check so always does network calls. */
1566 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1570 /* Internal connections never use the network. */
1571 if (domain->internal) {
1572 domain->initialized = True;
1573 return NT_STATUS_OK;
1576 if (connection_ok(domain)) {
1577 if (!domain->initialized) {
1578 set_dc_type_and_flags(domain);
1580 return NT_STATUS_OK;
1583 invalidate_cm_connection(&domain->conn);
1585 result = cm_open_connection(domain, &domain->conn);
1587 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1588 set_dc_type_and_flags(domain);
1594 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1596 if (domain->initialized && !domain->online) {
1597 /* We check for online status elsewhere. */
1598 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1601 return init_dc_connection_network(domain);
1604 /******************************************************************************
1605 Set the trust flags (direction and forest location) for a domain
1606 ******************************************************************************/
1608 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1610 struct winbindd_domain *our_domain;
1611 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1612 struct netr_DomainTrustList trusts;
1614 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1615 NETR_TRUST_FLAG_OUTBOUND |
1616 NETR_TRUST_FLAG_INBOUND);
1617 struct rpc_pipe_client *cli;
1618 TALLOC_CTX *mem_ctx = NULL;
1620 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1622 /* Our primary domain doesn't need to worry about trust flags.
1623 Force it to go through the network setup */
1624 if ( domain->primary ) {
1628 our_domain = find_our_domain();
1630 if ( !connection_ok(our_domain) ) {
1631 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1635 /* This won't work unless our domain is AD */
1637 if ( !our_domain->active_directory ) {
1641 /* Use DsEnumerateDomainTrusts to get us the trust direction
1644 result = cm_connect_netlogon(our_domain, &cli);
1646 if (!NT_STATUS_IS_OK(result)) {
1647 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1648 "a connection to %s for PIPE_NETLOGON (%s)\n",
1649 domain->name, nt_errstr(result)));
1653 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1654 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1658 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1663 if (!NT_STATUS_IS_OK(result)) {
1664 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1665 "failed to query trusted domain list: %s\n",
1666 nt_errstr(result)));
1667 talloc_destroy(mem_ctx);
1671 /* Now find the domain name and get the flags */
1673 for ( i=0; i<trusts.count; i++ ) {
1674 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1675 domain->domain_flags = trusts.array[i].trust_flags;
1676 domain->domain_type = trusts.array[i].trust_type;
1677 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1679 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1680 domain->active_directory = True;
1682 /* This flag is only set if the domain is *our*
1683 primary domain and the primary domain is in
1686 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1688 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1689 "native mode.\n", domain->name,
1690 domain->native_mode ? "" : "NOT "));
1692 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1693 "running active directory.\n", domain->name,
1694 domain->active_directory ? "" : "NOT "));
1697 domain->initialized = True;
1699 if ( !winbindd_can_contact_domain( domain) )
1700 domain->internal = True;
1706 talloc_destroy( mem_ctx );
1708 return domain->initialized;
1711 /******************************************************************************
1712 We can 'sense' certain things about the DC by it's replies to certain
1715 This tells us if this particular remote server is Active Directory, and if it
1717 ******************************************************************************/
1719 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1723 TALLOC_CTX *mem_ctx = NULL;
1724 struct rpc_pipe_client *cli;
1726 union dssetup_DsRoleInfo info;
1727 union lsa_PolicyInformation *lsa_info = NULL;
1729 if (!connection_ok(domain)) {
1733 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1736 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1740 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1742 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1743 &ndr_table_dssetup.syntax_id,
1746 if (!NT_STATUS_IS_OK(result)) {
1747 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1748 "PI_DSSETUP on domain %s: (%s)\n",
1749 domain->name, nt_errstr(result)));
1751 /* if this is just a non-AD domain we need to continue
1752 * identifying so that we can in the end return with
1753 * domain->initialized = True - gd */
1758 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1759 DS_ROLE_BASIC_INFORMATION,
1764 if (!NT_STATUS_IS_OK(result)) {
1765 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1766 "on domain %s failed: (%s)\n",
1767 domain->name, nt_errstr(result)));
1769 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1770 * every opcode on the DSSETUP pipe, continue with
1771 * no_dssetup mode here as well to get domain->initialized
1774 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1778 TALLOC_FREE(mem_ctx);
1782 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1783 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1784 domain->native_mode = True;
1786 domain->native_mode = False;
1790 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1791 &ndr_table_lsarpc.syntax_id, &cli);
1793 if (!NT_STATUS_IS_OK(result)) {
1794 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1795 "PI_LSARPC on domain %s: (%s)\n",
1796 domain->name, nt_errstr(result)));
1798 TALLOC_FREE(mem_ctx);
1802 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1803 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1805 if (NT_STATUS_IS_OK(result)) {
1806 /* This particular query is exactly what Win2k clients use
1807 to determine that the DC is active directory */
1808 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1810 LSA_POLICY_INFO_DNS,
1814 if (NT_STATUS_IS_OK(result)) {
1815 domain->active_directory = True;
1817 if (lsa_info->dns.name.string) {
1818 fstrcpy(domain->name, lsa_info->dns.name.string);
1821 if (lsa_info->dns.dns_domain.string) {
1822 fstrcpy(domain->alt_name,
1823 lsa_info->dns.dns_domain.string);
1826 /* See if we can set some domain trust flags about
1829 if (lsa_info->dns.dns_forest.string) {
1830 fstrcpy(domain->forest_name,
1831 lsa_info->dns.dns_forest.string);
1833 if (strequal(domain->forest_name, domain->alt_name)) {
1834 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1838 if (lsa_info->dns.sid) {
1839 sid_copy(&domain->sid, lsa_info->dns.sid);
1842 domain->active_directory = False;
1844 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1845 SEC_RIGHTS_MAXIMUM_ALLOWED,
1848 if (!NT_STATUS_IS_OK(result)) {
1852 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1854 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1857 if (NT_STATUS_IS_OK(result)) {
1859 if (lsa_info->account_domain.name.string) {
1860 fstrcpy(domain->name,
1861 lsa_info->account_domain.name.string);
1864 if (lsa_info->account_domain.sid) {
1865 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1871 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1872 domain->name, domain->native_mode ? "" : "NOT "));
1874 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1875 domain->name, domain->active_directory ? "" : "NOT "));
1879 TALLOC_FREE(mem_ctx);
1881 domain->initialized = True;
1884 /**********************************************************************
1885 Set the domain_flags (trust attributes, domain operating modes, etc...
1886 ***********************************************************************/
1888 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1890 /* we always have to contact our primary domain */
1892 if ( domain->primary ) {
1893 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1894 "primary domain\n"));
1895 set_dc_type_and_flags_connect( domain );
1899 /* Use our DC to get the information if possible */
1901 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1902 /* Otherwise, fallback to contacting the
1904 set_dc_type_and_flags_connect( domain );
1912 /**********************************************************************
1913 ***********************************************************************/
1915 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1916 struct dcinfo **ppdc)
1919 struct rpc_pipe_client *netlogon_pipe;
1921 if (lp_client_schannel() == False) {
1925 result = cm_connect_netlogon(domain, &netlogon_pipe);
1926 if (!NT_STATUS_IS_OK(result)) {
1930 /* Return a pointer to the struct dcinfo from the
1933 if (!domain->conn.netlogon_pipe->dc) {
1937 *ppdc = domain->conn.netlogon_pipe->dc;
1941 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1942 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1944 struct winbindd_cm_conn *conn;
1945 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1947 struct dcinfo *p_dcinfo;
1948 char *machine_password = NULL;
1949 char *machine_account = NULL;
1950 char *domain_name = NULL;
1952 result = init_dc_connection(domain);
1953 if (!NT_STATUS_IS_OK(result)) {
1957 conn = &domain->conn;
1959 if (conn->samr_pipe != NULL) {
1965 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1966 * sign and sealed pipe using the machine account password by
1967 * preference. If we can't - try schannel, if that fails, try
1971 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1972 if ((conn->cli->user_name[0] == '\0') ||
1973 (conn->cli->domain[0] == '\0') ||
1974 (conn_pwd[0] == '\0'))
1976 result = get_trust_creds(domain, &machine_password,
1977 &machine_account, NULL);
1978 if (!NT_STATUS_IS_OK(result)) {
1979 DEBUG(10, ("cm_connect_sam: No no user available for "
1980 "domain %s, trying schannel\n", conn->cli->domain));
1983 domain_name = domain->name;
1985 machine_password = SMB_STRDUP(conn_pwd);
1986 machine_account = SMB_STRDUP(conn->cli->user_name);
1987 domain_name = conn->cli->domain;
1990 if (!machine_password || !machine_account) {
1991 result = NT_STATUS_NO_MEMORY;
1995 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1996 authenticated SAMR pipe with sign & seal. */
1997 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
1998 &ndr_table_samr.syntax_id,
1999 PIPE_AUTH_LEVEL_PRIVACY,
2005 if (!NT_STATUS_IS_OK(result)) {
2006 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2007 "pipe for domain %s using NTLMSSP "
2008 "authenticated pipe: user %s\\%s. Error was "
2009 "%s\n", domain->name, domain_name,
2010 machine_account, nt_errstr(result)));
2014 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2015 "domain %s using NTLMSSP authenticated "
2016 "pipe: user %s\\%s\n", domain->name,
2017 domain_name, machine_account));
2019 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2020 conn->samr_pipe->desthost,
2021 SEC_RIGHTS_MAXIMUM_ALLOWED,
2022 &conn->sam_connect_handle);
2023 if (NT_STATUS_IS_OK(result)) {
2026 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2027 "failed for domain %s, error was %s. Trying schannel\n",
2028 domain->name, nt_errstr(result) ));
2029 TALLOC_FREE(conn->samr_pipe);
2033 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2035 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2036 /* If this call fails - conn->cli can now be NULL ! */
2037 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2038 "for domain %s, trying anon\n", domain->name));
2041 result = cli_rpc_pipe_open_schannel_with_key
2042 (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
2043 domain->name, p_dcinfo, &conn->samr_pipe);
2045 if (!NT_STATUS_IS_OK(result)) {
2046 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2047 "domain %s using schannel. Error was %s\n",
2048 domain->name, nt_errstr(result) ));
2051 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2052 "schannel.\n", domain->name ));
2054 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2055 conn->samr_pipe->desthost,
2056 SEC_RIGHTS_MAXIMUM_ALLOWED,
2057 &conn->sam_connect_handle);
2058 if (NT_STATUS_IS_OK(result)) {
2061 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2062 "for domain %s, error was %s. Trying anonymous\n",
2063 domain->name, nt_errstr(result) ));
2064 TALLOC_FREE(conn->samr_pipe);
2068 /* Finally fall back to anonymous. */
2069 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2072 if (!NT_STATUS_IS_OK(result)) {
2076 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2077 conn->samr_pipe->desthost,
2078 SEC_RIGHTS_MAXIMUM_ALLOWED,
2079 &conn->sam_connect_handle);
2080 if (!NT_STATUS_IS_OK(result)) {
2081 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2082 "for domain %s Error was %s\n",
2083 domain->name, nt_errstr(result) ));
2088 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2090 &conn->sam_connect_handle,
2091 SEC_RIGHTS_MAXIMUM_ALLOWED,
2093 &conn->sam_domain_handle);
2097 if (!NT_STATUS_IS_OK(result)) {
2098 invalidate_cm_connection(conn);
2102 *cli = conn->samr_pipe;
2103 *sam_handle = conn->sam_domain_handle;
2104 SAFE_FREE(machine_password);
2105 SAFE_FREE(machine_account);
2109 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2110 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2112 struct winbindd_cm_conn *conn;
2113 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2115 struct dcinfo *p_dcinfo;
2117 result = init_dc_connection(domain);
2118 if (!NT_STATUS_IS_OK(result))
2121 conn = &domain->conn;
2123 if (conn->lsa_pipe != NULL) {
2127 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2128 if ((conn->cli->user_name[0] == '\0') ||
2129 (conn->cli->domain[0] == '\0') ||
2130 (conn_pwd[0] == '\0')) {
2131 DEBUG(10, ("cm_connect_lsa: No no user available for "
2132 "domain %s, trying schannel\n", conn->cli->domain));
2136 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2137 * authenticated LSA pipe with sign & seal. */
2138 result = cli_rpc_pipe_open_spnego_ntlmssp
2139 (conn->cli, &ndr_table_lsarpc.syntax_id,
2140 PIPE_AUTH_LEVEL_PRIVACY,
2141 conn->cli->domain, conn->cli->user_name, conn_pwd,
2144 if (!NT_STATUS_IS_OK(result)) {
2145 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2146 "domain %s using NTLMSSP authenticated pipe: user "
2147 "%s\\%s. Error was %s. Trying schannel.\n",
2148 domain->name, conn->cli->domain,
2149 conn->cli->user_name, nt_errstr(result)));
2153 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2154 "NTLMSSP authenticated pipe: user %s\\%s\n",
2155 domain->name, conn->cli->domain, conn->cli->user_name ));
2157 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2158 SEC_RIGHTS_MAXIMUM_ALLOWED,
2160 if (NT_STATUS_IS_OK(result)) {
2164 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2167 TALLOC_FREE(conn->lsa_pipe);
2171 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2173 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2174 /* If this call fails - conn->cli can now be NULL ! */
2175 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2176 "for domain %s, trying anon\n", domain->name));
2179 result = cli_rpc_pipe_open_schannel_with_key
2180 (conn->cli, &ndr_table_lsarpc.syntax_id,
2181 PIPE_AUTH_LEVEL_PRIVACY,
2182 domain->name, p_dcinfo, &conn->lsa_pipe);
2184 if (!NT_STATUS_IS_OK(result)) {
2185 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2186 "domain %s using schannel. Error was %s\n",
2187 domain->name, nt_errstr(result) ));
2190 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2191 "schannel.\n", domain->name ));
2193 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2194 SEC_RIGHTS_MAXIMUM_ALLOWED,
2196 if (NT_STATUS_IS_OK(result)) {
2200 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2203 TALLOC_FREE(conn->lsa_pipe);
2207 result = cli_rpc_pipe_open_noauth(conn->cli,
2208 &ndr_table_lsarpc.syntax_id,
2210 if (!NT_STATUS_IS_OK(result)) {
2211 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2215 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2216 SEC_RIGHTS_MAXIMUM_ALLOWED,
2219 if (!NT_STATUS_IS_OK(result)) {
2220 invalidate_cm_connection(conn);
2224 *cli = conn->lsa_pipe;
2225 *lsa_policy = conn->lsa_policy;
2229 /****************************************************************************
2230 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2231 session key stored in conn->netlogon_pipe->dc->sess_key.
2232 ****************************************************************************/
2234 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2235 struct rpc_pipe_client **cli)
2237 struct winbindd_cm_conn *conn;
2240 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2242 uint32 sec_chan_type;
2243 const char *account_name;
2244 struct rpc_pipe_client *netlogon_pipe = NULL;
2248 result = init_dc_connection(domain);
2249 if (!NT_STATUS_IS_OK(result)) {
2253 conn = &domain->conn;
2255 if (conn->netlogon_pipe != NULL) {
2256 *cli = conn->netlogon_pipe;
2257 return NT_STATUS_OK;
2260 result = cli_rpc_pipe_open_noauth(conn->cli,
2261 &ndr_table_netlogon.syntax_id,
2263 if (!NT_STATUS_IS_OK(result)) {
2267 if ((!IS_DC) && (!domain->primary)) {
2268 /* Clear the schannel request bit and drop down */
2269 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2273 if (lp_client_schannel() != False) {
2274 neg_flags |= NETLOGON_NEG_SCHANNEL;
2277 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2280 TALLOC_FREE(netlogon_pipe);
2281 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2284 result = rpccli_netlogon_setup_creds(
2286 domain->dcname, /* server name. */
2287 domain->name, /* domain name */
2288 global_myname(), /* client name */
2289 account_name, /* machine account */
2290 mach_pwd, /* machine password */
2291 sec_chan_type, /* from get_trust_pw */
2294 if (!NT_STATUS_IS_OK(result)) {
2295 TALLOC_FREE(netlogon_pipe);
2299 if ((lp_client_schannel() == True) &&
2300 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2301 DEBUG(3, ("Server did not offer schannel\n"));
2302 TALLOC_FREE(netlogon_pipe);
2303 return NT_STATUS_ACCESS_DENIED;
2307 if ((lp_client_schannel() == False) ||
2308 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2310 * NetSamLogonEx only works for schannel
2312 domain->can_do_samlogon_ex = False;
2314 /* We're done - just keep the existing connection to NETLOGON
2316 conn->netlogon_pipe = netlogon_pipe;
2317 *cli = conn->netlogon_pipe;
2318 return NT_STATUS_OK;
2321 /* Using the credentials from the first pipe, open a signed and sealed
2322 second netlogon pipe. The session key is stored in the schannel
2323 part of the new pipe auth struct.
2326 result = cli_rpc_pipe_open_schannel_with_key(
2327 conn->cli, &ndr_table_netlogon.syntax_id,
2328 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2329 &conn->netlogon_pipe);
2331 /* We can now close the initial netlogon pipe. */
2332 TALLOC_FREE(netlogon_pipe);
2334 if (!NT_STATUS_IS_OK(result)) {
2335 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2336 "was %s\n", nt_errstr(result)));
2338 /* make sure we return something besides OK */
2339 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2343 * Try NetSamLogonEx for AD domains
2345 domain->can_do_samlogon_ex = domain->active_directory;
2347 *cli = conn->netlogon_pipe;
2348 return NT_STATUS_OK;