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, domain->name, 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, domain->name, 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 */
941 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
943 DEBUG(5, ("Connected anonymously\n"));
944 cli_init_creds(*cli, "", "", "");
945 goto session_setup_done;
948 result = cli_nt_error(*cli);
950 if (NT_STATUS_IS_OK(result))
951 result = NT_STATUS_UNSUCCESSFUL;
953 /* We can't session setup */
959 /* cache the server name for later connections */
961 saf_store( domain->name, (*cli)->desthost );
962 if (domain->alt_name && (*cli)->use_kerberos) {
963 saf_store( domain->alt_name, (*cli)->desthost );
966 winbindd_set_locator_kdc_envs(domain);
968 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
970 result = cli_nt_error(*cli);
972 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
974 if (NT_STATUS_IS_OK(result))
975 result = NT_STATUS_UNSUCCESSFUL;
983 /* set the domain if empty; needed for schannel connections */
984 if ( !*(*cli)->domain ) {
985 fstrcpy( (*cli)->domain, domain->name );
988 result = NT_STATUS_OK;
992 SAFE_FREE(machine_account);
993 SAFE_FREE(machine_password);
994 SAFE_FREE(machine_krb5_principal);
995 SAFE_FREE(ipc_username);
996 SAFE_FREE(ipc_domain);
997 SAFE_FREE(ipc_password);
999 if (!NT_STATUS_IS_OK(result)) {
1000 winbind_add_failed_connection_entry(domain, controller, result);
1001 if ((*cli) != NULL) {
1010 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1011 const char *dcname, struct sockaddr_storage *pss,
1012 struct dc_name_ip **dcs, int *num)
1014 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1015 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1019 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1024 fstrcpy((*dcs)[*num].name, dcname);
1025 (*dcs)[*num].ss = *pss;
1030 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1031 struct sockaddr_storage *pss, uint16 port,
1032 struct sockaddr_storage **addrs, int *num)
1034 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1036 if (*addrs == NULL) {
1041 (*addrs)[*num] = *pss;
1042 set_sockaddr_port(&(*addrs)[*num], port);
1048 /*******************************************************************
1049 convert an ip to a name
1050 *******************************************************************/
1052 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1053 const struct winbindd_domain *domain,
1054 struct sockaddr_storage *pss,
1057 struct ip_service ip_list;
1058 uint32_t nt_version = NETLOGON_VERSION_1;
1064 /* For active directory servers, try to get the ldap server name.
1065 None of these failures should be considered critical for now */
1067 if (lp_security() == SEC_ADS) {
1069 ADS_STATUS ads_status;
1070 char addr[INET6_ADDRSTRLEN];
1072 print_sockaddr(addr, sizeof(addr), pss);
1074 ads = ads_init(domain->alt_name, domain->name, addr);
1075 ads->auth.flags |= ADS_AUTH_NO_BIND;
1077 ads_status = ads_connect(ads);
1078 if (ADS_ERR_OK(ads_status)) {
1079 /* We got a cldap packet. */
1080 fstrcpy(name, ads->config.ldap_server_name);
1081 namecache_store(name, 0x20, 1, &ip_list);
1083 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1085 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1086 if (ads_closest_dc(ads)) {
1087 char *sitename = sitename_fetch(ads->config.realm);
1089 /* We're going to use this KDC for this realm/domain.
1090 If we are using sites, then force the krb5 libs
1093 create_local_private_krb5_conf_for_domain(domain->alt_name,
1098 SAFE_FREE(sitename);
1100 /* use an off site KDC */
1101 create_local_private_krb5_conf_for_domain(domain->alt_name,
1106 winbindd_set_locator_kdc_envs(domain);
1108 /* Ensure we contact this DC also. */
1109 saf_store( domain->name, name);
1110 saf_store( domain->alt_name, name);
1113 ads_destroy( &ads );
1117 ads_destroy( &ads );
1121 /* try GETDC requests next */
1123 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1124 pss, domain->name, &domain->sid,
1126 const char *dc_name = NULL;
1129 for (i=0; i<5; i++) {
1130 if (receive_getdc_response(mem_ctx, pss, domain->name,
1133 fstrcpy(name, dc_name);
1134 namecache_store(name, 0x20, 1, &ip_list);
1141 /* try node status request */
1143 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1144 namecache_store(name, 0x20, 1, &ip_list);
1150 /*******************************************************************
1151 Retreive a list of IP address for domain controllers. Fill in
1152 the dcs[] with results.
1153 *******************************************************************/
1155 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1156 struct dc_name_ip **dcs, int *num_dcs)
1159 struct sockaddr_storage ss;
1160 struct ip_service *ip_list = NULL;
1161 int iplist_size = 0;
1164 enum security_types sec = (enum security_types)lp_security();
1166 is_our_domain = strequal(domain->name, lp_workgroup());
1169 && get_dc_name_via_netlogon(domain, dcname, &ss)
1170 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs, num_dcs) )
1172 char addr[INET6_ADDRSTRLEN];
1173 print_sockaddr(addr, sizeof(addr), &ss);
1174 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1179 if (sec == SEC_ADS) {
1180 char *sitename = NULL;
1182 /* We need to make sure we know the local site before
1183 doing any DNS queries, as this will restrict the
1184 get_sorted_dc_list() call below to only fetching
1185 DNS records for the correct site. */
1187 /* Find any DC to get the site record.
1188 We deliberately don't care about the
1191 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1193 sitename = sitename_fetch(domain->alt_name);
1196 /* Do the site-specific AD dns lookup first. */
1197 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1199 for ( i=0; i<iplist_size; i++ ) {
1200 char addr[INET6_ADDRSTRLEN];
1201 print_sockaddr(addr, sizeof(addr),
1203 add_one_dc_unique(mem_ctx,
1212 SAFE_FREE(sitename);
1216 /* Now we add DCs from the main AD dns lookup. */
1217 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1219 for ( i=0; i<iplist_size; i++ ) {
1220 char addr[INET6_ADDRSTRLEN];
1221 print_sockaddr(addr, sizeof(addr),
1223 add_one_dc_unique(mem_ctx,
1232 /* try standard netbios queries if no ADS */
1234 if (iplist_size==0) {
1235 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1238 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1240 /* now add to the dc array. We'll wait until the last minute
1241 to look up the name of the DC. But we fill in the char* for
1242 the ip now in to make the failed connection cache work */
1244 for ( i=0; i<iplist_size; i++ ) {
1245 char addr[INET6_ADDRSTRLEN];
1246 print_sockaddr(addr, sizeof(addr),
1248 add_one_dc_unique(mem_ctx, domain->name, addr,
1249 &ip_list[i].ss, dcs, num_dcs);
1252 SAFE_FREE( ip_list );
1257 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1258 struct winbindd_domain *domain,
1259 fstring dcname, struct sockaddr_storage *pss, int *fd)
1261 struct dc_name_ip *dcs = NULL;
1264 const char **dcnames = NULL;
1265 int num_dcnames = 0;
1267 struct sockaddr_storage *addrs = NULL;
1275 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1278 for (i=0; i<num_dcs; i++) {
1280 if (!add_string_to_array(mem_ctx, dcs[i].name,
1281 &dcnames, &num_dcnames)) {
1284 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1285 &addrs, &num_addrs)) {
1289 if (!add_string_to_array(mem_ctx, dcs[i].name,
1290 &dcnames, &num_dcnames)) {
1293 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1294 &addrs, &num_addrs)) {
1299 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1302 if ((addrs == NULL) || (dcnames == NULL))
1305 /* 5 second timeout. */
1306 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1307 for (i=0; i<num_dcs; i++) {
1308 char ab[INET6_ADDRSTRLEN];
1309 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1310 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1311 "domain %s address %s. Error was %s\n",
1312 domain->name, ab, strerror(errno) ));
1313 winbind_add_failed_connection_entry(domain,
1314 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1319 *pss = addrs[fd_index];
1321 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1322 /* Ok, we've got a name for the DC */
1323 fstrcpy(dcname, dcnames[fd_index]);
1327 /* Try to figure out the name */
1328 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1332 /* We can not continue without the DC's name */
1333 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1334 NT_STATUS_UNSUCCESSFUL);
1336 /* Throw away all arrays as we're doing this again. */
1340 TALLOC_FREE(dcnames);
1352 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1353 struct winbindd_cm_conn *new_conn)
1355 TALLOC_CTX *mem_ctx;
1357 char *saf_servername = saf_fetch( domain->name );
1360 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1361 SAFE_FREE(saf_servername);
1362 set_domain_offline(domain);
1363 return NT_STATUS_NO_MEMORY;
1366 /* we have to check the server affinity cache here since
1367 later we selecte a DC based on response time and not preference */
1369 /* Check the negative connection cache
1370 before talking to it. It going down may have
1371 triggered the reconnection. */
1373 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1375 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1376 saf_servername, domain->name ));
1378 /* convert an ip address to a name */
1379 if (is_ipaddress( saf_servername ) ) {
1381 struct sockaddr_storage ss;
1383 if (!interpret_string_addr(&ss, saf_servername,
1385 return NT_STATUS_UNSUCCESSFUL;
1387 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1388 fstrcpy( domain->dcname, saf_name );
1390 winbind_add_failed_connection_entry(
1391 domain, saf_servername,
1392 NT_STATUS_UNSUCCESSFUL);
1395 fstrcpy( domain->dcname, saf_servername );
1398 SAFE_FREE( saf_servername );
1401 for (retries = 0; retries < 3; retries++) {
1405 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1407 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1408 domain->dcname, domain->name ));
1411 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1412 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1414 struct sockaddr_storage *addrs = NULL;
1418 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1419 set_domain_offline(domain);
1420 talloc_destroy(mem_ctx);
1421 return NT_STATUS_NO_MEMORY;
1423 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1424 set_domain_offline(domain);
1425 talloc_destroy(mem_ctx);
1426 return NT_STATUS_NO_MEMORY;
1429 /* 5 second timeout. */
1430 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1436 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1438 /* This is the one place where we will
1439 set the global winbindd offline state
1440 to true, if a "WINBINDD_OFFLINE" entry
1441 is found in the winbindd cache. */
1442 set_global_winbindd_state_offline();
1446 new_conn->cli = NULL;
1448 result = cm_prepare_connection(domain, fd, domain->dcname,
1449 &new_conn->cli, &retry);
1455 if (NT_STATUS_IS_OK(result)) {
1457 winbindd_set_locator_kdc_envs(domain);
1459 if (domain->online == False) {
1460 /* We're changing state from offline to online. */
1461 set_global_winbindd_state_online();
1463 set_domain_online(domain);
1465 /* Ensure we setup the retry handler. */
1466 set_domain_offline(domain);
1469 talloc_destroy(mem_ctx);
1473 /* Close down all open pipes on a connection. */
1475 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1477 /* We're closing down a possibly dead
1478 connection. Don't have impossibly long (10s) timeouts. */
1481 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1484 if (conn->samr_pipe != NULL) {
1485 TALLOC_FREE(conn->samr_pipe);
1486 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1488 cli_set_timeout(conn->cli, 500);
1492 if (conn->lsa_pipe != NULL) {
1493 TALLOC_FREE(conn->lsa_pipe);
1494 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1496 cli_set_timeout(conn->cli, 500);
1500 if (conn->netlogon_pipe != NULL) {
1501 TALLOC_FREE(conn->netlogon_pipe);
1502 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1504 cli_set_timeout(conn->cli, 500);
1509 cli_shutdown(conn->cli);
1515 void close_conns_after_fork(void)
1517 struct winbindd_domain *domain;
1519 for (domain = domain_list(); domain; domain = domain->next) {
1520 if (domain->conn.cli == NULL)
1523 if (domain->conn.cli->fd == -1)
1526 close(domain->conn.cli->fd);
1527 domain->conn.cli->fd = -1;
1531 static bool connection_ok(struct winbindd_domain *domain)
1533 if (domain->conn.cli == NULL) {
1534 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1535 "cli!\n", domain->dcname, domain->name));
1539 if (!domain->conn.cli->initialised) {
1540 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1541 "initialised!\n", domain->dcname, domain->name));
1545 if (domain->conn.cli->fd == -1) {
1546 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1547 "never started (fd == -1)\n",
1548 domain->dcname, domain->name));
1552 if (domain->online == False) {
1553 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1560 /* Initialize a new connection up to the RPC BIND.
1561 Bypass online status check so always does network calls. */
1563 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1567 /* Internal connections never use the network. */
1568 if (domain->internal) {
1569 domain->initialized = True;
1570 return NT_STATUS_OK;
1573 if (connection_ok(domain)) {
1574 if (!domain->initialized) {
1575 set_dc_type_and_flags(domain);
1577 return NT_STATUS_OK;
1580 invalidate_cm_connection(&domain->conn);
1582 result = cm_open_connection(domain, &domain->conn);
1584 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1585 set_dc_type_and_flags(domain);
1591 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1593 if (domain->initialized && !domain->online) {
1594 /* We check for online status elsewhere. */
1595 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1598 return init_dc_connection_network(domain);
1601 /******************************************************************************
1602 Set the trust flags (direction and forest location) for a domain
1603 ******************************************************************************/
1605 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1607 struct winbindd_domain *our_domain;
1608 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1609 struct netr_DomainTrustList trusts;
1611 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1612 NETR_TRUST_FLAG_OUTBOUND |
1613 NETR_TRUST_FLAG_INBOUND);
1614 struct rpc_pipe_client *cli;
1615 TALLOC_CTX *mem_ctx = NULL;
1617 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1619 /* Our primary domain doesn't need to worry about trust flags.
1620 Force it to go through the network setup */
1621 if ( domain->primary ) {
1625 our_domain = find_our_domain();
1627 if ( !connection_ok(our_domain) ) {
1628 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1632 /* This won't work unless our domain is AD */
1634 if ( !our_domain->active_directory ) {
1638 /* Use DsEnumerateDomainTrusts to get us the trust direction
1641 result = cm_connect_netlogon(our_domain, &cli);
1643 if (!NT_STATUS_IS_OK(result)) {
1644 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1645 "a connection to %s for PIPE_NETLOGON (%s)\n",
1646 domain->name, nt_errstr(result)));
1650 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1651 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1655 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1660 if (!NT_STATUS_IS_OK(result)) {
1661 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1662 "failed to query trusted domain list: %s\n",
1663 nt_errstr(result)));
1664 talloc_destroy(mem_ctx);
1668 /* Now find the domain name and get the flags */
1670 for ( i=0; i<trusts.count; i++ ) {
1671 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1672 domain->domain_flags = trusts.array[i].trust_flags;
1673 domain->domain_type = trusts.array[i].trust_type;
1674 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1676 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1677 domain->active_directory = True;
1679 /* This flag is only set if the domain is *our*
1680 primary domain and the primary domain is in
1683 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1685 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1686 "native mode.\n", domain->name,
1687 domain->native_mode ? "" : "NOT "));
1689 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1690 "running active directory.\n", domain->name,
1691 domain->active_directory ? "" : "NOT "));
1694 domain->initialized = True;
1696 if ( !winbindd_can_contact_domain( domain) )
1697 domain->internal = True;
1703 talloc_destroy( mem_ctx );
1705 return domain->initialized;
1708 /******************************************************************************
1709 We can 'sense' certain things about the DC by it's replies to certain
1712 This tells us if this particular remote server is Active Directory, and if it
1714 ******************************************************************************/
1716 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1720 TALLOC_CTX *mem_ctx = NULL;
1721 struct rpc_pipe_client *cli;
1723 union dssetup_DsRoleInfo info;
1724 union lsa_PolicyInformation *lsa_info = NULL;
1726 if (!connection_ok(domain)) {
1730 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1733 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1737 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1739 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1740 &ndr_table_dssetup.syntax_id,
1743 if (!NT_STATUS_IS_OK(result)) {
1744 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1745 "PI_DSSETUP on domain %s: (%s)\n",
1746 domain->name, nt_errstr(result)));
1748 /* if this is just a non-AD domain we need to continue
1749 * identifying so that we can in the end return with
1750 * domain->initialized = True - gd */
1755 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1756 DS_ROLE_BASIC_INFORMATION,
1761 if (!NT_STATUS_IS_OK(result)) {
1762 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1763 "on domain %s failed: (%s)\n",
1764 domain->name, nt_errstr(result)));
1766 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1767 * every opcode on the DSSETUP pipe, continue with
1768 * no_dssetup mode here as well to get domain->initialized
1771 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1775 TALLOC_FREE(mem_ctx);
1779 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1780 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1781 domain->native_mode = True;
1783 domain->native_mode = False;
1787 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1788 &ndr_table_lsarpc.syntax_id, &cli);
1790 if (!NT_STATUS_IS_OK(result)) {
1791 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1792 "PI_LSARPC on domain %s: (%s)\n",
1793 domain->name, nt_errstr(result)));
1795 TALLOC_FREE(mem_ctx);
1799 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1800 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1802 if (NT_STATUS_IS_OK(result)) {
1803 /* This particular query is exactly what Win2k clients use
1804 to determine that the DC is active directory */
1805 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1807 LSA_POLICY_INFO_DNS,
1811 if (NT_STATUS_IS_OK(result)) {
1812 domain->active_directory = True;
1814 if (lsa_info->dns.name.string) {
1815 fstrcpy(domain->name, lsa_info->dns.name.string);
1818 if (lsa_info->dns.dns_domain.string) {
1819 fstrcpy(domain->alt_name,
1820 lsa_info->dns.dns_domain.string);
1823 /* See if we can set some domain trust flags about
1826 if (lsa_info->dns.dns_forest.string) {
1827 fstrcpy(domain->forest_name,
1828 lsa_info->dns.dns_forest.string);
1830 if (strequal(domain->forest_name, domain->alt_name)) {
1831 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1835 if (lsa_info->dns.sid) {
1836 sid_copy(&domain->sid, lsa_info->dns.sid);
1839 domain->active_directory = False;
1841 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1842 SEC_RIGHTS_MAXIMUM_ALLOWED,
1845 if (!NT_STATUS_IS_OK(result)) {
1849 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1851 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1854 if (NT_STATUS_IS_OK(result)) {
1856 if (lsa_info->account_domain.name.string) {
1857 fstrcpy(domain->name,
1858 lsa_info->account_domain.name.string);
1861 if (lsa_info->account_domain.sid) {
1862 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1868 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1869 domain->name, domain->native_mode ? "" : "NOT "));
1871 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1872 domain->name, domain->active_directory ? "" : "NOT "));
1876 TALLOC_FREE(mem_ctx);
1878 domain->initialized = True;
1881 /**********************************************************************
1882 Set the domain_flags (trust attributes, domain operating modes, etc...
1883 ***********************************************************************/
1885 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1887 /* we always have to contact our primary domain */
1889 if ( domain->primary ) {
1890 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1891 "primary domain\n"));
1892 set_dc_type_and_flags_connect( domain );
1896 /* Use our DC to get the information if possible */
1898 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1899 /* Otherwise, fallback to contacting the
1901 set_dc_type_and_flags_connect( domain );
1909 /**********************************************************************
1910 ***********************************************************************/
1912 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1913 struct dcinfo **ppdc)
1916 struct rpc_pipe_client *netlogon_pipe;
1918 if (lp_client_schannel() == False) {
1922 result = cm_connect_netlogon(domain, &netlogon_pipe);
1923 if (!NT_STATUS_IS_OK(result)) {
1927 /* Return a pointer to the struct dcinfo from the
1930 *ppdc = domain->conn.netlogon_pipe->dc;
1934 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1935 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1937 struct winbindd_cm_conn *conn;
1938 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1940 struct dcinfo *p_dcinfo;
1941 char *machine_password = NULL;
1942 char *machine_account = NULL;
1943 char *domain_name = NULL;
1945 result = init_dc_connection(domain);
1946 if (!NT_STATUS_IS_OK(result)) {
1950 conn = &domain->conn;
1952 if (conn->samr_pipe != NULL) {
1957 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1958 * sign and sealed pipe using the machine account password by
1959 * preference. If we can't - try schannel, if that fails, try
1963 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1964 if ((conn->cli->user_name[0] == '\0') ||
1965 (conn->cli->domain[0] == '\0') ||
1966 (conn_pwd[0] == '\0'))
1968 result = get_trust_creds(domain, &machine_password,
1969 &machine_account, NULL);
1970 if (!NT_STATUS_IS_OK(result)) {
1971 DEBUG(10, ("cm_connect_sam: No no user available for "
1972 "domain %s, trying schannel\n", conn->cli->domain));
1975 domain_name = domain->name;
1977 machine_password = SMB_STRDUP(conn_pwd);
1978 machine_account = SMB_STRDUP(conn->cli->user_name);
1979 domain_name = conn->cli->domain;
1982 if (!machine_password || !machine_account) {
1983 result = NT_STATUS_NO_MEMORY;
1987 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1988 authenticated SAMR pipe with sign & seal. */
1989 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
1990 &ndr_table_samr.syntax_id,
1991 PIPE_AUTH_LEVEL_PRIVACY,
1997 if (!NT_STATUS_IS_OK(result)) {
1998 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1999 "pipe for domain %s using NTLMSSP "
2000 "authenticated pipe: user %s\\%s. Error was "
2001 "%s\n", domain->name, domain_name,
2002 machine_account, nt_errstr(result)));
2006 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2007 "domain %s using NTLMSSP authenticated "
2008 "pipe: user %s\\%s\n", domain->name,
2009 domain_name, machine_account));
2011 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2012 conn->samr_pipe->desthost,
2013 SEC_RIGHTS_MAXIMUM_ALLOWED,
2014 &conn->sam_connect_handle);
2015 if (NT_STATUS_IS_OK(result)) {
2018 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2019 "failed for domain %s, error was %s. Trying schannel\n",
2020 domain->name, nt_errstr(result) ));
2021 TALLOC_FREE(conn->samr_pipe);
2025 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2027 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2028 /* If this call fails - conn->cli can now be NULL ! */
2029 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2030 "for domain %s, trying anon\n", domain->name));
2033 result = cli_rpc_pipe_open_schannel_with_key
2034 (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
2035 domain->name, p_dcinfo, &conn->samr_pipe);
2037 if (!NT_STATUS_IS_OK(result)) {
2038 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2039 "domain %s using schannel. Error was %s\n",
2040 domain->name, nt_errstr(result) ));
2043 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2044 "schannel.\n", domain->name ));
2046 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2047 conn->samr_pipe->desthost,
2048 SEC_RIGHTS_MAXIMUM_ALLOWED,
2049 &conn->sam_connect_handle);
2050 if (NT_STATUS_IS_OK(result)) {
2053 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2054 "for domain %s, error was %s. Trying anonymous\n",
2055 domain->name, nt_errstr(result) ));
2056 TALLOC_FREE(conn->samr_pipe);
2060 /* Finally fall back to anonymous. */
2061 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2064 if (!NT_STATUS_IS_OK(result)) {
2068 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2069 conn->samr_pipe->desthost,
2070 SEC_RIGHTS_MAXIMUM_ALLOWED,
2071 &conn->sam_connect_handle);
2072 if (!NT_STATUS_IS_OK(result)) {
2073 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2074 "for domain %s Error was %s\n",
2075 domain->name, nt_errstr(result) ));
2080 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2082 &conn->sam_connect_handle,
2083 SEC_RIGHTS_MAXIMUM_ALLOWED,
2085 &conn->sam_domain_handle);
2089 if (!NT_STATUS_IS_OK(result)) {
2090 invalidate_cm_connection(conn);
2094 *cli = conn->samr_pipe;
2095 *sam_handle = conn->sam_domain_handle;
2096 SAFE_FREE(machine_password);
2097 SAFE_FREE(machine_account);
2101 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2102 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2104 struct winbindd_cm_conn *conn;
2105 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2107 struct dcinfo *p_dcinfo;
2109 result = init_dc_connection(domain);
2110 if (!NT_STATUS_IS_OK(result))
2113 conn = &domain->conn;
2115 if (conn->lsa_pipe != NULL) {
2119 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2120 if ((conn->cli->user_name[0] == '\0') ||
2121 (conn->cli->domain[0] == '\0') ||
2122 (conn_pwd[0] == '\0')) {
2123 DEBUG(10, ("cm_connect_lsa: No no user available for "
2124 "domain %s, trying schannel\n", conn->cli->domain));
2128 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2129 * authenticated LSA pipe with sign & seal. */
2130 result = cli_rpc_pipe_open_spnego_ntlmssp
2131 (conn->cli, &ndr_table_lsarpc.syntax_id,
2132 PIPE_AUTH_LEVEL_PRIVACY,
2133 conn->cli->domain, conn->cli->user_name, conn_pwd,
2136 if (!NT_STATUS_IS_OK(result)) {
2137 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2138 "domain %s using NTLMSSP authenticated pipe: user "
2139 "%s\\%s. Error was %s. Trying schannel.\n",
2140 domain->name, conn->cli->domain,
2141 conn->cli->user_name, nt_errstr(result)));
2145 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2146 "NTLMSSP authenticated pipe: user %s\\%s\n",
2147 domain->name, conn->cli->domain, conn->cli->user_name ));
2149 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2150 SEC_RIGHTS_MAXIMUM_ALLOWED,
2152 if (NT_STATUS_IS_OK(result)) {
2156 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2159 TALLOC_FREE(conn->lsa_pipe);
2163 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2165 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2166 /* If this call fails - conn->cli can now be NULL ! */
2167 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2168 "for domain %s, trying anon\n", domain->name));
2171 result = cli_rpc_pipe_open_schannel_with_key
2172 (conn->cli, &ndr_table_lsarpc.syntax_id,
2173 PIPE_AUTH_LEVEL_PRIVACY,
2174 domain->name, p_dcinfo, &conn->lsa_pipe);
2176 if (!NT_STATUS_IS_OK(result)) {
2177 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2178 "domain %s using schannel. Error was %s\n",
2179 domain->name, nt_errstr(result) ));
2182 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2183 "schannel.\n", domain->name ));
2185 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2186 SEC_RIGHTS_MAXIMUM_ALLOWED,
2188 if (NT_STATUS_IS_OK(result)) {
2192 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2195 TALLOC_FREE(conn->lsa_pipe);
2199 result = cli_rpc_pipe_open_noauth(conn->cli,
2200 &ndr_table_lsarpc.syntax_id,
2202 if (!NT_STATUS_IS_OK(result)) {
2203 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2207 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2208 SEC_RIGHTS_MAXIMUM_ALLOWED,
2211 if (!NT_STATUS_IS_OK(result)) {
2212 invalidate_cm_connection(conn);
2216 *cli = conn->lsa_pipe;
2217 *lsa_policy = conn->lsa_policy;
2221 /****************************************************************************
2222 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2223 session key stored in conn->netlogon_pipe->dc->sess_key.
2224 ****************************************************************************/
2226 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2227 struct rpc_pipe_client **cli)
2229 struct winbindd_cm_conn *conn;
2232 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2234 uint32 sec_chan_type;
2235 const char *account_name;
2236 struct rpc_pipe_client *netlogon_pipe = NULL;
2240 result = init_dc_connection(domain);
2241 if (!NT_STATUS_IS_OK(result)) {
2245 conn = &domain->conn;
2247 if (conn->netlogon_pipe != NULL) {
2248 *cli = conn->netlogon_pipe;
2249 return NT_STATUS_OK;
2252 result = cli_rpc_pipe_open_noauth(conn->cli,
2253 &ndr_table_netlogon.syntax_id,
2255 if (!NT_STATUS_IS_OK(result)) {
2259 if ((!IS_DC) && (!domain->primary)) {
2260 /* Clear the schannel request bit and drop down */
2261 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2265 if (lp_client_schannel() != False) {
2266 neg_flags |= NETLOGON_NEG_SCHANNEL;
2269 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2272 TALLOC_FREE(netlogon_pipe);
2273 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2276 result = rpccli_netlogon_setup_creds(
2278 domain->dcname, /* server name. */
2279 domain->name, /* domain name */
2280 global_myname(), /* client name */
2281 account_name, /* machine account */
2282 mach_pwd, /* machine password */
2283 sec_chan_type, /* from get_trust_pw */
2286 if (!NT_STATUS_IS_OK(result)) {
2287 TALLOC_FREE(netlogon_pipe);
2291 if ((lp_client_schannel() == True) &&
2292 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2293 DEBUG(3, ("Server did not offer schannel\n"));
2294 TALLOC_FREE(netlogon_pipe);
2295 return NT_STATUS_ACCESS_DENIED;
2299 if ((lp_client_schannel() == False) ||
2300 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2302 * NetSamLogonEx only works for schannel
2304 domain->can_do_samlogon_ex = False;
2306 /* We're done - just keep the existing connection to NETLOGON
2308 conn->netlogon_pipe = netlogon_pipe;
2309 *cli = conn->netlogon_pipe;
2310 return NT_STATUS_OK;
2313 /* Using the credentials from the first pipe, open a signed and sealed
2314 second netlogon pipe. The session key is stored in the schannel
2315 part of the new pipe auth struct.
2318 result = cli_rpc_pipe_open_schannel_with_key(
2319 conn->cli, &ndr_table_netlogon.syntax_id,
2320 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2321 &conn->netlogon_pipe);
2323 /* We can now close the initial netlogon pipe. */
2324 TALLOC_FREE(netlogon_pipe);
2326 if (!NT_STATUS_IS_OK(result)) {
2327 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2328 "was %s\n", nt_errstr(result)));
2330 /* make sure we return something besides OK */
2331 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2335 * Try NetSamLogonEx for AD domains
2337 domain->can_do_samlogon_ex = domain->active_directory;
2339 *cli = conn->netlogon_pipe;
2340 return NT_STATUS_OK;