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(),
216 winbind_event_context(), true)) {
217 DEBUG(0,("reinit_after_fork() failed\n"));
218 messaging_send_buf(winbind_messaging_context(),
219 pid_to_procid(parent_pid),
220 MSG_WINBIND_FAILED_TO_GO_ONLINE,
221 (uint8 *)domain->name,
222 strlen(domain->name)+1);
226 close_conns_after_fork();
228 if (!override_logfile) {
230 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) > 0) {
231 lp_set_logfile(lfile);
237 mem_ctx = talloc_init("fork_child_dc_connect");
239 DEBUG(0,("talloc_init failed.\n"));
240 messaging_send_buf(winbind_messaging_context(),
241 pid_to_procid(parent_pid),
242 MSG_WINBIND_FAILED_TO_GO_ONLINE,
243 (uint8 *)domain->name,
244 strlen(domain->name)+1);
248 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
249 /* Still offline ? Can't find DC's. */
250 messaging_send_buf(winbind_messaging_context(),
251 pid_to_procid(parent_pid),
252 MSG_WINBIND_FAILED_TO_GO_ONLINE,
253 (uint8 *)domain->name,
254 strlen(domain->name)+1);
258 /* We got a DC. Send a message to our parent to get it to
259 try and do the same. */
261 messaging_send_buf(winbind_messaging_context(),
262 pid_to_procid(parent_pid),
263 MSG_WINBIND_TRY_TO_GO_ONLINE,
264 (uint8 *)domain->name,
265 strlen(domain->name)+1);
269 /****************************************************************
270 Handler triggered if we're offline to try and detect a DC.
271 ****************************************************************/
273 static void check_domain_online_handler(struct event_context *ctx,
274 struct timed_event *te,
275 const struct timeval *now,
278 struct winbindd_domain *domain =
279 (struct winbindd_domain *)private_data;
281 DEBUG(10,("check_domain_online_handler: called for domain "
282 "%s (online = %s)\n", domain->name,
283 domain->online ? "True" : "False" ));
285 TALLOC_FREE(domain->check_online_event);
287 /* Are we still in "startup" mode ? */
289 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
290 /* No longer in "startup" mode. */
291 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
293 domain->startup = False;
296 /* We've been told to stay offline, so stay
299 if (get_global_winbindd_state_offline()) {
300 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
305 /* Fork a child to test if it can contact a DC.
306 If it can then send ourselves a message to
307 cause a reconnect. */
309 fork_child_dc_connect(domain);
312 /****************************************************************
313 If we're still offline setup the timeout check.
314 ****************************************************************/
316 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
318 int wbr = lp_winbind_reconnect_delay();
320 if (domain->startup) {
321 domain->check_online_timeout = 10;
322 } else if (domain->check_online_timeout < wbr) {
323 domain->check_online_timeout = wbr;
327 /****************************************************************
328 Set domain offline and also add handler to put us back online
330 ****************************************************************/
332 void set_domain_offline(struct winbindd_domain *domain)
334 DEBUG(10,("set_domain_offline: called for domain %s\n",
337 TALLOC_FREE(domain->check_online_event);
339 if (domain->internal) {
340 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
345 domain->online = False;
347 /* Offline domains are always initialized. They're
348 re-initialized when they go back online. */
350 domain->initialized = True;
352 /* We only add the timeout handler that checks and
353 allows us to go back online when we've not
354 been told to remain offline. */
356 if (get_global_winbindd_state_offline()) {
357 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
362 /* If we're in statup mode, check again in 10 seconds, not in
363 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
365 calc_new_online_timeout_check(domain);
367 domain->check_online_event = event_add_timed(winbind_event_context(),
369 timeval_current_ofs(domain->check_online_timeout,0),
370 "check_domain_online_handler",
371 check_domain_online_handler,
374 /* The above *has* to succeed for winbindd to work. */
375 if (!domain->check_online_event) {
376 smb_panic("set_domain_offline: failed to add online handler");
379 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
382 /* Send an offline message to the idmap child when our
383 primary domain goes offline */
385 if ( domain->primary ) {
386 struct winbindd_child *idmap = idmap_child();
388 if ( idmap->pid != 0 ) {
389 messaging_send_buf(winbind_messaging_context(),
390 pid_to_procid(idmap->pid),
392 (uint8 *)domain->name,
393 strlen(domain->name)+1);
400 /****************************************************************
401 Set domain online - if allowed.
402 ****************************************************************/
404 static void set_domain_online(struct winbindd_domain *domain)
406 DEBUG(10,("set_domain_online: called for domain %s\n",
409 if (domain->internal) {
410 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
415 if (get_global_winbindd_state_offline()) {
416 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
421 winbindd_set_locator_kdc_envs(domain);
423 /* If we are waiting to get a krb5 ticket, trigger immediately. */
424 ccache_regain_all_now();
426 /* Ok, we're out of any startup mode now... */
427 domain->startup = False;
429 if (domain->online == False) {
430 /* We were offline - now we're online. We default to
431 using the MS-RPC backend if we started offline,
432 and if we're going online for the first time we
433 should really re-initialize the backends and the
434 checks to see if we're talking to an AD or NT domain.
437 domain->initialized = False;
439 /* 'reconnect_methods' is the MS-RPC backend. */
440 if (domain->backend == &reconnect_methods) {
441 domain->backend = NULL;
445 /* Ensure we have no online timeout checks. */
446 domain->check_online_timeout = 0;
447 TALLOC_FREE(domain->check_online_event);
449 /* Ensure we ignore any pending child messages. */
450 messaging_deregister(winbind_messaging_context(),
451 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
452 messaging_deregister(winbind_messaging_context(),
453 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
455 domain->online = True;
457 /* Send an online message to the idmap child when our
458 primary domain comes online */
460 if ( domain->primary ) {
461 struct winbindd_child *idmap = idmap_child();
463 if ( idmap->pid != 0 ) {
464 messaging_send_buf(winbind_messaging_context(),
465 pid_to_procid(idmap->pid),
467 (uint8 *)domain->name,
468 strlen(domain->name)+1);
475 /****************************************************************
476 Requested to set a domain online.
477 ****************************************************************/
479 void set_domain_online_request(struct winbindd_domain *domain)
483 DEBUG(10,("set_domain_online_request: called for domain %s\n",
486 if (get_global_winbindd_state_offline()) {
487 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
492 /* We've been told it's safe to go online and
493 try and connect to a DC. But I don't believe it
494 because network manager seems to lie.
495 Wait at least 5 seconds. Heuristics suck... */
500 /* Go into "startup" mode again. */
501 domain->startup_time = tev.tv_sec;
502 domain->startup = True;
506 if (!domain->check_online_event) {
507 /* If we've come from being globally offline we
508 don't have a check online event handler set.
509 We need to add one now we're trying to go
512 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
516 TALLOC_FREE(domain->check_online_event);
518 domain->check_online_event = event_add_timed(winbind_event_context(),
521 "check_domain_online_handler",
522 check_domain_online_handler,
525 /* The above *has* to succeed for winbindd to work. */
526 if (!domain->check_online_event) {
527 smb_panic("set_domain_online_request: failed to add online handler");
531 /****************************************************************
532 Add -ve connection cache entries for domain and realm.
533 ****************************************************************/
535 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
539 add_failed_connection_entry(domain->name, server, result);
540 /* If this was the saf name for the last thing we talked to,
542 saf_delete(domain->name);
543 if (*domain->alt_name) {
544 add_failed_connection_entry(domain->alt_name, server, result);
545 saf_delete(domain->alt_name);
547 winbindd_unset_locator_kdc_env(domain);
550 /* Choose between anonymous or authenticated connections. We need to use
551 an authenticated connection if DCs have the RestrictAnonymous registry
552 entry set > 0, or the "Additional restrictions for anonymous
553 connections" set in the win2k Local Security Policy.
555 Caller to free() result in domain, username, password
558 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
560 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
561 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
562 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
564 if (*username && **username) {
566 if (!*domain || !**domain)
567 *domain = smb_xstrdup(lp_workgroup());
569 if (!*password || !**password)
570 *password = smb_xstrdup("");
572 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
573 *domain, *username));
576 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
577 *username = smb_xstrdup("");
578 *domain = smb_xstrdup("");
579 *password = smb_xstrdup("");
583 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
585 struct sockaddr_storage *dc_ss)
587 struct winbindd_domain *our_domain = NULL;
588 struct rpc_pipe_client *netlogon_pipe = NULL;
592 unsigned int orig_timeout;
593 const char *tmp = NULL;
596 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
603 if (domain->primary) {
607 our_domain = find_our_domain();
609 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
613 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
614 if (!NT_STATUS_IS_OK(result)) {
615 talloc_destroy(mem_ctx);
619 /* This call can take a long time - allow the server to time out.
620 35 seconds should do it. */
622 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
624 if (our_domain->active_directory) {
625 struct netr_DsRGetDCNameInfo *domain_info = NULL;
627 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
636 if (W_ERROR_IS_OK(werr)) {
638 mem_ctx, domain_info->dc_unc);
640 DEBUG(0, ("talloc_strdup failed\n"));
641 talloc_destroy(mem_ctx);
644 if (strlen(domain->alt_name) == 0) {
645 fstrcpy(domain->alt_name,
646 domain_info->domain_name);
648 if (strlen(domain->forest_name) == 0) {
649 fstrcpy(domain->forest_name,
650 domain_info->forest_name);
654 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
661 /* And restore our original timeout. */
662 rpccli_set_timeout(netlogon_pipe, orig_timeout);
664 if (!NT_STATUS_IS_OK(result)) {
665 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
667 talloc_destroy(mem_ctx);
671 if (!W_ERROR_IS_OK(werr)) {
672 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
674 talloc_destroy(mem_ctx);
678 /* rpccli_netr_GetAnyDCName gives us a name with \\ */
679 p = strip_hostname(tmp);
683 talloc_destroy(mem_ctx);
685 DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
687 if (!resolve_name(dcname, dc_ss, 0x20)) {
695 * Helper function to assemble trust password and account name
697 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
698 char **machine_password,
699 char **machine_account,
700 char **machine_krb5_principal)
702 const char *account_name;
703 const char *name = NULL;
705 /* If we are a DC and this is not our own domain */
710 struct winbindd_domain *our_domain = find_our_domain();
713 return NT_STATUS_INVALID_SERVER_STATE;
715 name = our_domain->name;
718 if (!get_trust_pw_clear(name, machine_password,
719 &account_name, NULL))
721 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
724 if ((machine_account != NULL) &&
725 (asprintf(machine_account, "%s$", account_name) == -1))
727 return NT_STATUS_NO_MEMORY;
730 /* For now assume our machine account only exists in our domain */
732 if (machine_krb5_principal != NULL)
734 struct winbindd_domain *our_domain = find_our_domain();
737 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
740 if (asprintf(machine_krb5_principal, "%s$@%s",
741 account_name, our_domain->alt_name) == -1)
743 return NT_STATUS_NO_MEMORY;
746 strupper_m(*machine_krb5_principal);
752 /************************************************************************
753 Given a fd with a just-connected TCP connection to a DC, open a connection
755 ************************************************************************/
757 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
759 const char *controller,
760 struct cli_state **cli,
763 char *machine_password = NULL;
764 char *machine_krb5_principal = NULL;
765 char *machine_account = NULL;
766 char *ipc_username = NULL;
767 char *ipc_domain = NULL;
768 char *ipc_password = NULL;
770 struct named_mutex *mutex;
772 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
774 struct sockaddr peeraddr;
775 socklen_t peeraddr_len;
777 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
779 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
780 controller, domain->name ));
784 mutex = grab_named_mutex(talloc_tos(), controller,
785 WINBIND_SERVER_MUTEX_WAIT_TIME);
787 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
789 result = NT_STATUS_POSSIBLE_DEADLOCK;
793 if ((*cli = cli_initialise()) == NULL) {
794 DEBUG(1, ("Could not cli_initialize\n"));
795 result = NT_STATUS_NO_MEMORY;
799 (*cli)->timeout = 10000; /* 10 seconds */
801 fstrcpy((*cli)->desthost, controller);
802 (*cli)->use_kerberos = True;
804 peeraddr_len = sizeof(peeraddr);
806 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
807 (peeraddr_len != sizeof(struct sockaddr_in)) ||
808 (peeraddr_in->sin_family != PF_INET))
810 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
811 result = NT_STATUS_UNSUCCESSFUL;
815 if (ntohs(peeraddr_in->sin_port) == 139) {
816 struct nmb_name calling;
817 struct nmb_name called;
819 make_nmb_name(&calling, global_myname(), 0x0);
820 make_nmb_name(&called, "*SMBSERVER", 0x20);
822 if (!cli_session_request(*cli, &calling, &called)) {
823 DEBUG(8, ("cli_session_request failed for %s\n",
825 result = NT_STATUS_UNSUCCESSFUL;
830 cli_setup_signing_state(*cli, Undefined);
832 result = cli_negprot(*cli);
834 if (!NT_STATUS_IS_OK(result)) {
835 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
839 if (!is_dc_trusted_domain_situation(domain->name) &&
840 (*cli)->protocol >= PROTOCOL_NT1 &&
841 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
843 ADS_STATUS ads_status;
845 result = get_trust_creds(domain, &machine_password,
847 &machine_krb5_principal);
848 if (!NT_STATUS_IS_OK(result)) {
852 if (lp_security() == SEC_ADS) {
854 /* Try a krb5 session */
856 (*cli)->use_kerberos = True;
857 DEBUG(5, ("connecting to %s from %s with kerberos principal "
858 "[%s] and realm [%s]\n", controller, global_myname(),
859 machine_krb5_principal, domain->alt_name));
861 winbindd_set_locator_kdc_envs(domain);
863 ads_status = cli_session_setup_spnego(*cli,
864 machine_krb5_principal,
869 if (!ADS_ERR_OK(ads_status)) {
870 DEBUG(4,("failed kerberos session setup with %s\n",
871 ads_errstr(ads_status)));
874 result = ads_ntstatus(ads_status);
875 if (NT_STATUS_IS_OK(result)) {
876 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
877 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
878 goto session_setup_done;
882 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
883 (*cli)->use_kerberos = False;
885 DEBUG(5, ("connecting to %s from %s with username "
886 "[%s]\\[%s]\n", controller, global_myname(),
887 lp_workgroup(), machine_account));
889 ads_status = cli_session_setup_spnego(*cli,
894 if (!ADS_ERR_OK(ads_status)) {
895 DEBUG(4, ("authenticated session setup failed with %s\n",
896 ads_errstr(ads_status)));
899 result = ads_ntstatus(ads_status);
900 if (NT_STATUS_IS_OK(result)) {
901 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
902 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
903 goto session_setup_done;
907 /* Fall back to non-kerberos session setup with auth_user */
909 (*cli)->use_kerberos = False;
911 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
913 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
914 (strlen(ipc_username) > 0)) {
916 /* Only try authenticated if we have a username */
918 DEBUG(5, ("connecting to %s from %s with username "
919 "[%s]\\[%s]\n", controller, global_myname(),
920 ipc_domain, ipc_username));
922 if (NT_STATUS_IS_OK(cli_session_setup(
924 ipc_password, strlen(ipc_password)+1,
925 ipc_password, strlen(ipc_password)+1,
927 /* Successful logon with given username. */
928 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
929 goto session_setup_done;
931 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
932 ipc_domain, ipc_username ));
938 /* Fall back to anonymous connection, this might fail later */
939 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
940 "connection for DC %s\n",
943 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
945 DEBUG(5, ("Connected anonymously\n"));
946 cli_init_creds(*cli, "", "", "");
947 goto session_setup_done;
950 result = cli_nt_error(*cli);
952 if (NT_STATUS_IS_OK(result))
953 result = NT_STATUS_UNSUCCESSFUL;
955 /* We can't session setup */
961 /* cache the server name for later connections */
963 saf_store( domain->name, (*cli)->desthost );
964 if (domain->alt_name && (*cli)->use_kerberos) {
965 saf_store( domain->alt_name, (*cli)->desthost );
968 winbindd_set_locator_kdc_envs(domain);
970 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
972 result = cli_nt_error(*cli);
974 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
976 if (NT_STATUS_IS_OK(result))
977 result = NT_STATUS_UNSUCCESSFUL;
985 /* set the domain if empty; needed for schannel connections */
986 if ( !*(*cli)->domain ) {
987 fstrcpy( (*cli)->domain, domain->name );
990 result = NT_STATUS_OK;
994 SAFE_FREE(machine_account);
995 SAFE_FREE(machine_password);
996 SAFE_FREE(machine_krb5_principal);
997 SAFE_FREE(ipc_username);
998 SAFE_FREE(ipc_domain);
999 SAFE_FREE(ipc_password);
1001 if (!NT_STATUS_IS_OK(result)) {
1002 winbind_add_failed_connection_entry(domain, controller, result);
1003 if ((*cli) != NULL) {
1012 /*******************************************************************
1013 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1016 Keeps the list unique by not adding duplicate entries.
1018 @param[in] mem_ctx talloc memory context to allocate from
1019 @param[in] domain_name domain of the DC
1020 @param[in] dcname name of the DC to add to the list
1021 @param[in] pss Internet address and port pair to add to the list
1022 @param[in,out] dcs array of dc_name_ip structures to add to
1023 @param[in,out] num_dcs number of dcs returned in the dcs array
1024 @return true if the list was added to, false otherwise
1025 *******************************************************************/
1027 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1028 const char *dcname, struct sockaddr_storage *pss,
1029 struct dc_name_ip **dcs, int *num)
1033 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1034 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1038 /* Make sure there's no duplicates in the list */
1039 for (i=0; i<*num; i++)
1040 if (sockaddr_equal((struct sockaddr *)&(*dcs)[i].ss, (struct sockaddr *)pss))
1043 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1048 fstrcpy((*dcs)[*num].name, dcname);
1049 (*dcs)[*num].ss = *pss;
1054 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1055 struct sockaddr_storage *pss, uint16 port,
1056 struct sockaddr_storage **addrs, int *num)
1058 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1060 if (*addrs == NULL) {
1065 (*addrs)[*num] = *pss;
1066 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1072 /*******************************************************************
1073 convert an ip to a name
1074 *******************************************************************/
1076 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1077 const struct winbindd_domain *domain,
1078 struct sockaddr_storage *pss,
1081 struct ip_service ip_list;
1082 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1088 /* For active directory servers, try to get the ldap server name.
1089 None of these failures should be considered critical for now */
1091 if (lp_security() == SEC_ADS) {
1093 ADS_STATUS ads_status;
1094 char addr[INET6_ADDRSTRLEN];
1096 print_sockaddr(addr, sizeof(addr), pss);
1098 ads = ads_init(domain->alt_name, domain->name, addr);
1099 ads->auth.flags |= ADS_AUTH_NO_BIND;
1101 ads_status = ads_connect(ads);
1102 if (ADS_ERR_OK(ads_status)) {
1103 /* We got a cldap packet. */
1104 fstrcpy(name, ads->config.ldap_server_name);
1105 namecache_store(name, 0x20, 1, &ip_list);
1107 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1109 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1110 if (ads_closest_dc(ads)) {
1111 char *sitename = sitename_fetch(ads->config.realm);
1113 /* We're going to use this KDC for this realm/domain.
1114 If we are using sites, then force the krb5 libs
1117 create_local_private_krb5_conf_for_domain(domain->alt_name,
1122 SAFE_FREE(sitename);
1124 /* use an off site KDC */
1125 create_local_private_krb5_conf_for_domain(domain->alt_name,
1130 winbindd_set_locator_kdc_envs(domain);
1132 /* Ensure we contact this DC also. */
1133 saf_store( domain->name, name);
1134 saf_store( domain->alt_name, name);
1137 ads_destroy( &ads );
1141 ads_destroy( &ads );
1145 /* try GETDC requests next */
1147 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1148 pss, domain->name, &domain->sid,
1150 const char *dc_name = NULL;
1153 for (i=0; i<5; i++) {
1154 if (receive_getdc_response(mem_ctx, pss, domain->name,
1157 fstrcpy(name, dc_name);
1158 namecache_store(name, 0x20, 1, &ip_list);
1165 /* try node status request */
1167 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1168 namecache_store(name, 0x20, 1, &ip_list);
1174 /*******************************************************************
1175 Retrieve a list of IP addresses for domain controllers.
1177 The array is sorted in the preferred connection order.
1179 @param[in] mem_ctx talloc memory context to allocate from
1180 @param[in] domain domain to retrieve DCs for
1181 @param[out] dcs array of dcs that will be returned
1182 @param[out] num_dcs number of dcs returned in the dcs array
1184 *******************************************************************/
1186 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1187 struct dc_name_ip **dcs, int *num_dcs)
1190 struct sockaddr_storage ss;
1191 struct ip_service *ip_list = NULL;
1192 int iplist_size = 0;
1195 enum security_types sec = (enum security_types)lp_security();
1197 is_our_domain = strequal(domain->name, lp_workgroup());
1199 /* If not our domain, get the preferred DC, by asking our primary DC */
1201 && get_dc_name_via_netlogon(domain, dcname, &ss)
1202 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1205 char addr[INET6_ADDRSTRLEN];
1206 print_sockaddr(addr, sizeof(addr), &ss);
1207 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1212 if (sec == SEC_ADS) {
1213 char *sitename = NULL;
1215 /* We need to make sure we know the local site before
1216 doing any DNS queries, as this will restrict the
1217 get_sorted_dc_list() call below to only fetching
1218 DNS records for the correct site. */
1220 /* Find any DC to get the site record.
1221 We deliberately don't care about the
1224 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1226 sitename = sitename_fetch(domain->alt_name);
1229 /* Do the site-specific AD dns lookup first. */
1230 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1231 &iplist_size, True);
1233 /* Add ips to the DC array. We don't look up the name
1234 of the DC in this function, but we fill in the char*
1235 of the ip now to make the failed connection cache
1237 for ( i=0; i<iplist_size; i++ ) {
1238 char addr[INET6_ADDRSTRLEN];
1239 print_sockaddr(addr, sizeof(addr),
1241 add_one_dc_unique(mem_ctx,
1250 SAFE_FREE(sitename);
1254 /* Now we add DCs from the main AD DNS lookup. */
1255 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1256 &iplist_size, True);
1258 for ( i=0; i<iplist_size; i++ ) {
1259 char addr[INET6_ADDRSTRLEN];
1260 print_sockaddr(addr, sizeof(addr),
1262 add_one_dc_unique(mem_ctx,
1274 /* Try standard netbios queries if no ADS */
1275 if (*num_dcs == 0) {
1276 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1279 for ( i=0; i<iplist_size; i++ ) {
1280 char addr[INET6_ADDRSTRLEN];
1281 print_sockaddr(addr, sizeof(addr),
1283 add_one_dc_unique(mem_ctx,
1298 /*******************************************************************
1299 Find and make a connection to a DC in the given domain.
1301 @param[in] mem_ctx talloc memory context to allocate from
1302 @param[in] domain domain to find a dc in
1303 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1304 @param[out] pss DC Internet address and port
1305 @param[out] fd fd of the open socket connected to the newly found dc
1306 @return true when a DC connection is made, false otherwise
1307 *******************************************************************/
1309 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1310 struct winbindd_domain *domain,
1311 fstring dcname, struct sockaddr_storage *pss, int *fd)
1313 struct dc_name_ip *dcs = NULL;
1316 const char **dcnames = NULL;
1317 int num_dcnames = 0;
1319 struct sockaddr_storage *addrs = NULL;
1327 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1330 for (i=0; i<num_dcs; i++) {
1332 if (!add_string_to_array(mem_ctx, dcs[i].name,
1333 &dcnames, &num_dcnames)) {
1336 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1337 &addrs, &num_addrs)) {
1341 if (!add_string_to_array(mem_ctx, dcs[i].name,
1342 &dcnames, &num_dcnames)) {
1345 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1346 &addrs, &num_addrs)) {
1351 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1354 if ((addrs == NULL) || (dcnames == NULL))
1357 /* 5 second timeout. */
1358 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1359 for (i=0; i<num_dcs; i++) {
1360 char ab[INET6_ADDRSTRLEN];
1361 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1362 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1363 "domain %s address %s. Error was %s\n",
1364 domain->name, ab, strerror(errno) ));
1365 winbind_add_failed_connection_entry(domain,
1366 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1371 *pss = addrs[fd_index];
1373 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1374 /* Ok, we've got a name for the DC */
1375 fstrcpy(dcname, dcnames[fd_index]);
1379 /* Try to figure out the name */
1380 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1384 /* We can not continue without the DC's name */
1385 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1386 NT_STATUS_UNSUCCESSFUL);
1388 /* Throw away all arrays as we're doing this again. */
1392 TALLOC_FREE(dcnames);
1404 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1405 struct winbindd_cm_conn *new_conn)
1407 TALLOC_CTX *mem_ctx;
1409 char *saf_servername = saf_fetch( domain->name );
1412 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1413 SAFE_FREE(saf_servername);
1414 set_domain_offline(domain);
1415 return NT_STATUS_NO_MEMORY;
1418 /* we have to check the server affinity cache here since
1419 later we selecte a DC based on response time and not preference */
1421 /* Check the negative connection cache
1422 before talking to it. It going down may have
1423 triggered the reconnection. */
1425 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1427 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1428 saf_servername, domain->name ));
1430 /* convert an ip address to a name */
1431 if (is_ipaddress( saf_servername ) ) {
1433 struct sockaddr_storage ss;
1435 if (!interpret_string_addr(&ss, saf_servername,
1437 return NT_STATUS_UNSUCCESSFUL;
1439 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1440 fstrcpy( domain->dcname, saf_name );
1442 winbind_add_failed_connection_entry(
1443 domain, saf_servername,
1444 NT_STATUS_UNSUCCESSFUL);
1447 fstrcpy( domain->dcname, saf_servername );
1450 SAFE_FREE( saf_servername );
1453 for (retries = 0; retries < 3; retries++) {
1457 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1459 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1460 domain->dcname, domain->name ));
1463 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1464 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1466 struct sockaddr_storage *addrs = NULL;
1470 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1471 set_domain_offline(domain);
1472 talloc_destroy(mem_ctx);
1473 return NT_STATUS_NO_MEMORY;
1475 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1476 set_domain_offline(domain);
1477 talloc_destroy(mem_ctx);
1478 return NT_STATUS_NO_MEMORY;
1481 /* 5 second timeout. */
1482 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1488 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1490 /* This is the one place where we will
1491 set the global winbindd offline state
1492 to true, if a "WINBINDD_OFFLINE" entry
1493 is found in the winbindd cache. */
1494 set_global_winbindd_state_offline();
1498 new_conn->cli = NULL;
1500 result = cm_prepare_connection(domain, fd, domain->dcname,
1501 &new_conn->cli, &retry);
1507 if (NT_STATUS_IS_OK(result)) {
1509 winbindd_set_locator_kdc_envs(domain);
1511 if (domain->online == False) {
1512 /* We're changing state from offline to online. */
1513 set_global_winbindd_state_online();
1515 set_domain_online(domain);
1517 /* Ensure we setup the retry handler. */
1518 set_domain_offline(domain);
1521 talloc_destroy(mem_ctx);
1525 /* Close down all open pipes on a connection. */
1527 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1529 /* We're closing down a possibly dead
1530 connection. Don't have impossibly long (10s) timeouts. */
1533 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1536 if (conn->samr_pipe != NULL) {
1537 TALLOC_FREE(conn->samr_pipe);
1538 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1540 cli_set_timeout(conn->cli, 500);
1544 if (conn->lsa_pipe != NULL) {
1545 TALLOC_FREE(conn->lsa_pipe);
1546 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1548 cli_set_timeout(conn->cli, 500);
1552 if (conn->netlogon_pipe != NULL) {
1553 TALLOC_FREE(conn->netlogon_pipe);
1554 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1556 cli_set_timeout(conn->cli, 500);
1561 cli_shutdown(conn->cli);
1567 void close_conns_after_fork(void)
1569 struct winbindd_domain *domain;
1571 for (domain = domain_list(); domain; domain = domain->next) {
1572 if (domain->conn.cli == NULL)
1575 if (domain->conn.cli->fd == -1)
1578 close(domain->conn.cli->fd);
1579 domain->conn.cli->fd = -1;
1583 static bool connection_ok(struct winbindd_domain *domain)
1585 if (domain->conn.cli == NULL) {
1586 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1587 "cli!\n", domain->dcname, domain->name));
1591 if (!domain->conn.cli->initialised) {
1592 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1593 "initialised!\n", domain->dcname, domain->name));
1597 if (domain->conn.cli->fd == -1) {
1598 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1599 "never started (fd == -1)\n",
1600 domain->dcname, domain->name));
1604 if (domain->online == False) {
1605 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1612 /* Initialize a new connection up to the RPC BIND.
1613 Bypass online status check so always does network calls. */
1615 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1619 /* Internal connections never use the network. */
1620 if (domain->internal) {
1621 domain->initialized = True;
1622 return NT_STATUS_OK;
1625 if (connection_ok(domain)) {
1626 if (!domain->initialized) {
1627 set_dc_type_and_flags(domain);
1629 return NT_STATUS_OK;
1632 invalidate_cm_connection(&domain->conn);
1634 result = cm_open_connection(domain, &domain->conn);
1636 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1637 set_dc_type_and_flags(domain);
1643 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1645 if (domain->initialized && !domain->online) {
1646 /* We check for online status elsewhere. */
1647 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1650 return init_dc_connection_network(domain);
1653 /******************************************************************************
1654 Set the trust flags (direction and forest location) for a domain
1655 ******************************************************************************/
1657 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1659 struct winbindd_domain *our_domain;
1660 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1661 struct netr_DomainTrustList trusts;
1663 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1664 NETR_TRUST_FLAG_OUTBOUND |
1665 NETR_TRUST_FLAG_INBOUND);
1666 struct rpc_pipe_client *cli;
1667 TALLOC_CTX *mem_ctx = NULL;
1669 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1671 /* Our primary domain doesn't need to worry about trust flags.
1672 Force it to go through the network setup */
1673 if ( domain->primary ) {
1677 our_domain = find_our_domain();
1679 if ( !connection_ok(our_domain) ) {
1680 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1684 /* This won't work unless our domain is AD */
1686 if ( !our_domain->active_directory ) {
1690 /* Use DsEnumerateDomainTrusts to get us the trust direction
1693 result = cm_connect_netlogon(our_domain, &cli);
1695 if (!NT_STATUS_IS_OK(result)) {
1696 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1697 "a connection to %s for PIPE_NETLOGON (%s)\n",
1698 domain->name, nt_errstr(result)));
1702 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1703 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1707 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1712 if (!NT_STATUS_IS_OK(result)) {
1713 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1714 "failed to query trusted domain list: %s\n",
1715 nt_errstr(result)));
1716 talloc_destroy(mem_ctx);
1720 /* Now find the domain name and get the flags */
1722 for ( i=0; i<trusts.count; i++ ) {
1723 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1724 domain->domain_flags = trusts.array[i].trust_flags;
1725 domain->domain_type = trusts.array[i].trust_type;
1726 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1728 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1729 domain->active_directory = True;
1731 /* This flag is only set if the domain is *our*
1732 primary domain and the primary domain is in
1735 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1737 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1738 "native mode.\n", domain->name,
1739 domain->native_mode ? "" : "NOT "));
1741 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1742 "running active directory.\n", domain->name,
1743 domain->active_directory ? "" : "NOT "));
1746 domain->initialized = True;
1748 if ( !winbindd_can_contact_domain( domain) )
1749 domain->internal = True;
1755 talloc_destroy( mem_ctx );
1757 return domain->initialized;
1760 /******************************************************************************
1761 We can 'sense' certain things about the DC by it's replies to certain
1764 This tells us if this particular remote server is Active Directory, and if it
1766 ******************************************************************************/
1768 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1772 TALLOC_CTX *mem_ctx = NULL;
1773 struct rpc_pipe_client *cli;
1775 union dssetup_DsRoleInfo info;
1776 union lsa_PolicyInformation *lsa_info = NULL;
1778 if (!connection_ok(domain)) {
1782 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1785 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1789 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1791 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1792 &ndr_table_dssetup.syntax_id,
1795 if (!NT_STATUS_IS_OK(result)) {
1796 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1797 "PI_DSSETUP on domain %s: (%s)\n",
1798 domain->name, nt_errstr(result)));
1800 /* if this is just a non-AD domain we need to continue
1801 * identifying so that we can in the end return with
1802 * domain->initialized = True - gd */
1807 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1808 DS_ROLE_BASIC_INFORMATION,
1813 if (!NT_STATUS_IS_OK(result)) {
1814 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1815 "on domain %s failed: (%s)\n",
1816 domain->name, nt_errstr(result)));
1818 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1819 * every opcode on the DSSETUP pipe, continue with
1820 * no_dssetup mode here as well to get domain->initialized
1823 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1827 TALLOC_FREE(mem_ctx);
1831 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1832 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1833 domain->native_mode = True;
1835 domain->native_mode = False;
1839 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1840 &ndr_table_lsarpc.syntax_id, &cli);
1842 if (!NT_STATUS_IS_OK(result)) {
1843 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1844 "PI_LSARPC on domain %s: (%s)\n",
1845 domain->name, nt_errstr(result)));
1847 TALLOC_FREE(mem_ctx);
1851 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1852 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1854 if (NT_STATUS_IS_OK(result)) {
1855 /* This particular query is exactly what Win2k clients use
1856 to determine that the DC is active directory */
1857 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1859 LSA_POLICY_INFO_DNS,
1863 if (NT_STATUS_IS_OK(result)) {
1864 domain->active_directory = True;
1866 if (lsa_info->dns.name.string) {
1867 fstrcpy(domain->name, lsa_info->dns.name.string);
1870 if (lsa_info->dns.dns_domain.string) {
1871 fstrcpy(domain->alt_name,
1872 lsa_info->dns.dns_domain.string);
1875 /* See if we can set some domain trust flags about
1878 if (lsa_info->dns.dns_forest.string) {
1879 fstrcpy(domain->forest_name,
1880 lsa_info->dns.dns_forest.string);
1882 if (strequal(domain->forest_name, domain->alt_name)) {
1883 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1887 if (lsa_info->dns.sid) {
1888 sid_copy(&domain->sid, lsa_info->dns.sid);
1891 domain->active_directory = False;
1893 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1894 SEC_RIGHTS_MAXIMUM_ALLOWED,
1897 if (!NT_STATUS_IS_OK(result)) {
1901 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1903 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1906 if (NT_STATUS_IS_OK(result)) {
1908 if (lsa_info->account_domain.name.string) {
1909 fstrcpy(domain->name,
1910 lsa_info->account_domain.name.string);
1913 if (lsa_info->account_domain.sid) {
1914 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1920 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1921 domain->name, domain->native_mode ? "" : "NOT "));
1923 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1924 domain->name, domain->active_directory ? "" : "NOT "));
1928 TALLOC_FREE(mem_ctx);
1930 domain->initialized = True;
1933 /**********************************************************************
1934 Set the domain_flags (trust attributes, domain operating modes, etc...
1935 ***********************************************************************/
1937 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1939 /* we always have to contact our primary domain */
1941 if ( domain->primary ) {
1942 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1943 "primary domain\n"));
1944 set_dc_type_and_flags_connect( domain );
1948 /* Use our DC to get the information if possible */
1950 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1951 /* Otherwise, fallback to contacting the
1953 set_dc_type_and_flags_connect( domain );
1961 /**********************************************************************
1962 ***********************************************************************/
1964 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1965 struct dcinfo **ppdc)
1968 struct rpc_pipe_client *netlogon_pipe;
1970 if (lp_client_schannel() == False) {
1974 result = cm_connect_netlogon(domain, &netlogon_pipe);
1975 if (!NT_STATUS_IS_OK(result)) {
1979 /* Return a pointer to the struct dcinfo from the
1982 if (!domain->conn.netlogon_pipe->dc) {
1986 *ppdc = domain->conn.netlogon_pipe->dc;
1990 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1991 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1993 struct winbindd_cm_conn *conn;
1994 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1996 struct dcinfo *p_dcinfo;
1997 char *machine_password = NULL;
1998 char *machine_account = NULL;
1999 char *domain_name = NULL;
2001 result = init_dc_connection(domain);
2002 if (!NT_STATUS_IS_OK(result)) {
2006 conn = &domain->conn;
2008 if (conn->samr_pipe != NULL) {
2014 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2015 * sign and sealed pipe using the machine account password by
2016 * preference. If we can't - try schannel, if that fails, try
2020 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2021 if ((conn->cli->user_name[0] == '\0') ||
2022 (conn->cli->domain[0] == '\0') ||
2023 (conn_pwd[0] == '\0'))
2025 result = get_trust_creds(domain, &machine_password,
2026 &machine_account, NULL);
2027 if (!NT_STATUS_IS_OK(result)) {
2028 DEBUG(10, ("cm_connect_sam: No no user available for "
2029 "domain %s, trying schannel\n", conn->cli->domain));
2032 domain_name = domain->name;
2034 machine_password = SMB_STRDUP(conn_pwd);
2035 machine_account = SMB_STRDUP(conn->cli->user_name);
2036 domain_name = conn->cli->domain;
2039 if (!machine_password || !machine_account) {
2040 result = NT_STATUS_NO_MEMORY;
2044 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2045 authenticated SAMR pipe with sign & seal. */
2046 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2047 &ndr_table_samr.syntax_id,
2048 PIPE_AUTH_LEVEL_PRIVACY,
2054 if (!NT_STATUS_IS_OK(result)) {
2055 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2056 "pipe for domain %s using NTLMSSP "
2057 "authenticated pipe: user %s\\%s. Error was "
2058 "%s\n", domain->name, domain_name,
2059 machine_account, nt_errstr(result)));
2063 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2064 "domain %s using NTLMSSP authenticated "
2065 "pipe: user %s\\%s\n", domain->name,
2066 domain_name, machine_account));
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)) {
2075 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2076 "failed for domain %s, error was %s. Trying schannel\n",
2077 domain->name, nt_errstr(result) ));
2078 TALLOC_FREE(conn->samr_pipe);
2082 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2084 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2085 /* If this call fails - conn->cli can now be NULL ! */
2086 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2087 "for domain %s, trying anon\n", domain->name));
2090 result = cli_rpc_pipe_open_schannel_with_key
2091 (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
2092 domain->name, p_dcinfo, &conn->samr_pipe);
2094 if (!NT_STATUS_IS_OK(result)) {
2095 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2096 "domain %s using schannel. Error was %s\n",
2097 domain->name, nt_errstr(result) ));
2100 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2101 "schannel.\n", domain->name ));
2103 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2104 conn->samr_pipe->desthost,
2105 SEC_RIGHTS_MAXIMUM_ALLOWED,
2106 &conn->sam_connect_handle);
2107 if (NT_STATUS_IS_OK(result)) {
2110 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2111 "for domain %s, error was %s. Trying anonymous\n",
2112 domain->name, nt_errstr(result) ));
2113 TALLOC_FREE(conn->samr_pipe);
2117 /* Finally fall back to anonymous. */
2118 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2121 if (!NT_STATUS_IS_OK(result)) {
2125 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2126 conn->samr_pipe->desthost,
2127 SEC_RIGHTS_MAXIMUM_ALLOWED,
2128 &conn->sam_connect_handle);
2129 if (!NT_STATUS_IS_OK(result)) {
2130 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2131 "for domain %s Error was %s\n",
2132 domain->name, nt_errstr(result) ));
2137 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2139 &conn->sam_connect_handle,
2140 SEC_RIGHTS_MAXIMUM_ALLOWED,
2142 &conn->sam_domain_handle);
2146 if (!NT_STATUS_IS_OK(result)) {
2147 invalidate_cm_connection(conn);
2151 *cli = conn->samr_pipe;
2152 *sam_handle = conn->sam_domain_handle;
2153 SAFE_FREE(machine_password);
2154 SAFE_FREE(machine_account);
2158 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2159 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2161 struct winbindd_cm_conn *conn;
2162 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2164 struct dcinfo *p_dcinfo;
2166 result = init_dc_connection(domain);
2167 if (!NT_STATUS_IS_OK(result))
2170 conn = &domain->conn;
2172 if (conn->lsa_pipe != NULL) {
2176 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2177 if ((conn->cli->user_name[0] == '\0') ||
2178 (conn->cli->domain[0] == '\0') ||
2179 (conn_pwd[0] == '\0')) {
2180 DEBUG(10, ("cm_connect_lsa: No no user available for "
2181 "domain %s, trying schannel\n", conn->cli->domain));
2185 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2186 * authenticated LSA pipe with sign & seal. */
2187 result = cli_rpc_pipe_open_spnego_ntlmssp
2188 (conn->cli, &ndr_table_lsarpc.syntax_id,
2189 PIPE_AUTH_LEVEL_PRIVACY,
2190 conn->cli->domain, conn->cli->user_name, conn_pwd,
2193 if (!NT_STATUS_IS_OK(result)) {
2194 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2195 "domain %s using NTLMSSP authenticated pipe: user "
2196 "%s\\%s. Error was %s. Trying schannel.\n",
2197 domain->name, conn->cli->domain,
2198 conn->cli->user_name, nt_errstr(result)));
2202 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2203 "NTLMSSP authenticated pipe: user %s\\%s\n",
2204 domain->name, conn->cli->domain, conn->cli->user_name ));
2206 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2207 SEC_RIGHTS_MAXIMUM_ALLOWED,
2209 if (NT_STATUS_IS_OK(result)) {
2213 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2216 TALLOC_FREE(conn->lsa_pipe);
2220 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2222 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2223 /* If this call fails - conn->cli can now be NULL ! */
2224 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2225 "for domain %s, trying anon\n", domain->name));
2228 result = cli_rpc_pipe_open_schannel_with_key
2229 (conn->cli, &ndr_table_lsarpc.syntax_id,
2230 PIPE_AUTH_LEVEL_PRIVACY,
2231 domain->name, p_dcinfo, &conn->lsa_pipe);
2233 if (!NT_STATUS_IS_OK(result)) {
2234 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2235 "domain %s using schannel. Error was %s\n",
2236 domain->name, nt_errstr(result) ));
2239 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2240 "schannel.\n", domain->name ));
2242 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2243 SEC_RIGHTS_MAXIMUM_ALLOWED,
2245 if (NT_STATUS_IS_OK(result)) {
2249 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2252 TALLOC_FREE(conn->lsa_pipe);
2256 result = cli_rpc_pipe_open_noauth(conn->cli,
2257 &ndr_table_lsarpc.syntax_id,
2259 if (!NT_STATUS_IS_OK(result)) {
2260 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2264 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2265 SEC_RIGHTS_MAXIMUM_ALLOWED,
2268 if (!NT_STATUS_IS_OK(result)) {
2269 invalidate_cm_connection(conn);
2273 *cli = conn->lsa_pipe;
2274 *lsa_policy = conn->lsa_policy;
2278 /****************************************************************************
2279 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2280 session key stored in conn->netlogon_pipe->dc->sess_key.
2281 ****************************************************************************/
2283 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2284 struct rpc_pipe_client **cli)
2286 struct winbindd_cm_conn *conn;
2289 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2291 uint32 sec_chan_type;
2292 const char *account_name;
2293 struct rpc_pipe_client *netlogon_pipe = NULL;
2297 result = init_dc_connection(domain);
2298 if (!NT_STATUS_IS_OK(result)) {
2302 conn = &domain->conn;
2304 if (conn->netlogon_pipe != NULL) {
2305 *cli = conn->netlogon_pipe;
2306 return NT_STATUS_OK;
2309 result = cli_rpc_pipe_open_noauth(conn->cli,
2310 &ndr_table_netlogon.syntax_id,
2312 if (!NT_STATUS_IS_OK(result)) {
2316 if ((!IS_DC) && (!domain->primary)) {
2317 /* Clear the schannel request bit and drop down */
2318 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2322 if (lp_client_schannel() != False) {
2323 neg_flags |= NETLOGON_NEG_SCHANNEL;
2326 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2329 TALLOC_FREE(netlogon_pipe);
2330 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2333 result = rpccli_netlogon_setup_creds(
2335 domain->dcname, /* server name. */
2336 domain->name, /* domain name */
2337 global_myname(), /* client name */
2338 account_name, /* machine account */
2339 mach_pwd, /* machine password */
2340 sec_chan_type, /* from get_trust_pw */
2343 if (!NT_STATUS_IS_OK(result)) {
2344 TALLOC_FREE(netlogon_pipe);
2348 if ((lp_client_schannel() == True) &&
2349 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2350 DEBUG(3, ("Server did not offer schannel\n"));
2351 TALLOC_FREE(netlogon_pipe);
2352 return NT_STATUS_ACCESS_DENIED;
2356 if ((lp_client_schannel() == False) ||
2357 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2359 * NetSamLogonEx only works for schannel
2361 domain->can_do_samlogon_ex = False;
2363 /* We're done - just keep the existing connection to NETLOGON
2365 conn->netlogon_pipe = netlogon_pipe;
2366 *cli = conn->netlogon_pipe;
2367 return NT_STATUS_OK;
2370 /* Using the credentials from the first pipe, open a signed and sealed
2371 second netlogon pipe. The session key is stored in the schannel
2372 part of the new pipe auth struct.
2375 result = cli_rpc_pipe_open_schannel_with_key(
2376 conn->cli, &ndr_table_netlogon.syntax_id,
2377 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2378 &conn->netlogon_pipe);
2380 /* We can now close the initial netlogon pipe. */
2381 TALLOC_FREE(netlogon_pipe);
2383 if (!NT_STATUS_IS_OK(result)) {
2384 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2385 "was %s\n", nt_errstr(result)));
2387 /* make sure we return something besides OK */
2388 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2392 * Try NetSamLogonEx for AD domains
2394 domain->can_do_samlogon_ex = domain->active_directory;
2396 *cli = conn->netlogon_pipe;
2397 return NT_STATUS_OK;