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)
408 DEBUG(10,("set_domain_online: called for domain %s\n",
411 if (domain->internal) {
412 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
417 if (get_global_winbindd_state_offline()) {
418 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
423 winbindd_set_locator_kdc_envs(domain);
425 /* If we are waiting to get a krb5 ticket, trigger immediately. */
427 set_event_dispatch_time(winbind_event_context(),
428 "krb5_ticket_gain_handler", now);
430 /* Ok, we're out of any startup mode now... */
431 domain->startup = False;
433 if (domain->online == False) {
434 /* We were offline - now we're online. We default to
435 using the MS-RPC backend if we started offline,
436 and if we're going online for the first time we
437 should really re-initialize the backends and the
438 checks to see if we're talking to an AD or NT domain.
441 domain->initialized = False;
443 /* 'reconnect_methods' is the MS-RPC backend. */
444 if (domain->backend == &reconnect_methods) {
445 domain->backend = NULL;
449 /* Ensure we have no online timeout checks. */
450 domain->check_online_timeout = 0;
451 TALLOC_FREE(domain->check_online_event);
453 /* Ensure we ignore any pending child messages. */
454 messaging_deregister(winbind_messaging_context(),
455 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
456 messaging_deregister(winbind_messaging_context(),
457 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
459 domain->online = True;
461 /* Send an online message to the idmap child when our
462 primary domain comes online */
464 if ( domain->primary ) {
465 struct winbindd_child *idmap = idmap_child();
467 if ( idmap->pid != 0 ) {
468 messaging_send_buf(winbind_messaging_context(),
469 pid_to_procid(idmap->pid),
471 (uint8 *)domain->name,
472 strlen(domain->name)+1);
479 /****************************************************************
480 Requested to set a domain online.
481 ****************************************************************/
483 void set_domain_online_request(struct winbindd_domain *domain)
487 DEBUG(10,("set_domain_online_request: called for domain %s\n",
490 if (get_global_winbindd_state_offline()) {
491 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
496 /* We've been told it's safe to go online and
497 try and connect to a DC. But I don't believe it
498 because network manager seems to lie.
499 Wait at least 5 seconds. Heuristics suck... */
501 if (!domain->check_online_event) {
502 /* If we've come from being globally offline we
503 don't have a check online event handler set.
504 We need to add one now we're trying to go
507 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
510 domain->check_online_event = event_add_timed(winbind_event_context(),
512 timeval_current_ofs(5, 0),
513 "check_domain_online_handler",
514 check_domain_online_handler,
517 /* The above *has* to succeed for winbindd to work. */
518 if (!domain->check_online_event) {
519 smb_panic("set_domain_online_request: failed to add online handler");
525 /* Go into "startup" mode again. */
526 domain->startup_time = tev.tv_sec;
527 domain->startup = True;
531 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
534 /****************************************************************
535 Add -ve connection cache entries for domain and realm.
536 ****************************************************************/
538 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
542 add_failed_connection_entry(domain->name, server, result);
543 /* If this was the saf name for the last thing we talked to,
545 saf_delete(domain->name);
546 if (*domain->alt_name) {
547 add_failed_connection_entry(domain->alt_name, server, result);
548 saf_delete(domain->alt_name);
550 winbindd_unset_locator_kdc_env(domain);
553 /* Choose between anonymous or authenticated connections. We need to use
554 an authenticated connection if DCs have the RestrictAnonymous registry
555 entry set > 0, or the "Additional restrictions for anonymous
556 connections" set in the win2k Local Security Policy.
558 Caller to free() result in domain, username, password
561 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
563 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
564 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
565 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
567 if (*username && **username) {
569 if (!*domain || !**domain)
570 *domain = smb_xstrdup(lp_workgroup());
572 if (!*password || !**password)
573 *password = smb_xstrdup("");
575 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
576 *domain, *username));
579 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
580 *username = smb_xstrdup("");
581 *domain = smb_xstrdup("");
582 *password = smb_xstrdup("");
586 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
588 struct sockaddr_storage *dc_ss)
590 struct winbindd_domain *our_domain = NULL;
591 struct rpc_pipe_client *netlogon_pipe = NULL;
595 unsigned int orig_timeout;
596 const char *tmp = NULL;
599 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
606 if (domain->primary) {
610 our_domain = find_our_domain();
612 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
616 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
617 if (!NT_STATUS_IS_OK(result)) {
618 talloc_destroy(mem_ctx);
622 /* This call can take a long time - allow the server to time out.
623 35 seconds should do it. */
625 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
627 if (our_domain->active_directory) {
628 struct netr_DsRGetDCNameInfo *domain_info = NULL;
630 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
639 if (W_ERROR_IS_OK(werr)) {
641 mem_ctx, domain_info->dc_unc);
643 DEBUG(0, ("talloc_strdup failed\n"));
644 talloc_destroy(mem_ctx);
647 if (strlen(domain->alt_name) == 0) {
648 fstrcpy(domain->alt_name,
649 domain_info->domain_name);
651 if (strlen(domain->forest_name) == 0) {
652 fstrcpy(domain->forest_name,
653 domain_info->forest_name);
657 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
664 /* And restore our original timeout. */
665 rpccli_set_timeout(netlogon_pipe, orig_timeout);
667 if (!NT_STATUS_IS_OK(result)) {
668 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
670 talloc_destroy(mem_ctx);
674 if (!W_ERROR_IS_OK(werr)) {
675 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
677 talloc_destroy(mem_ctx);
681 /* rpccli_netr_GetAnyDCName gives us a name with \\ */
682 p = strip_hostname(tmp);
686 talloc_destroy(mem_ctx);
688 DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
690 if (!resolve_name(dcname, dc_ss, 0x20)) {
698 * Helper function to assemble trust password and account name
700 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
701 char **machine_password,
702 char **machine_account,
703 char **machine_krb5_principal)
705 const char *account_name;
706 const char *name = NULL;
708 /* If we are a DC and this is not our own domain */
713 struct winbindd_domain *our_domain = find_our_domain();
716 return NT_STATUS_INVALID_SERVER_STATE;
718 name = our_domain->name;
721 if (!get_trust_pw_clear(name, machine_password,
722 &account_name, NULL))
724 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
727 if ((machine_account != NULL) &&
728 (asprintf(machine_account, "%s$", account_name) == -1))
730 return NT_STATUS_NO_MEMORY;
733 /* For now assume our machine account only exists in our domain */
735 if (machine_krb5_principal != NULL)
737 struct winbindd_domain *our_domain = find_our_domain();
740 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
743 if (asprintf(machine_krb5_principal, "%s$@%s",
744 account_name, our_domain->alt_name) == -1)
746 return NT_STATUS_NO_MEMORY;
749 strupper_m(*machine_krb5_principal);
755 /************************************************************************
756 Given a fd with a just-connected TCP connection to a DC, open a connection
758 ************************************************************************/
760 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
762 const char *controller,
763 struct cli_state **cli,
766 char *machine_password = NULL;
767 char *machine_krb5_principal = NULL;
768 char *machine_account = NULL;
769 char *ipc_username = NULL;
770 char *ipc_domain = NULL;
771 char *ipc_password = NULL;
773 struct named_mutex *mutex;
775 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
777 struct sockaddr peeraddr;
778 socklen_t peeraddr_len;
780 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
782 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
783 controller, domain->name ));
787 mutex = grab_named_mutex(talloc_tos(), controller,
788 WINBIND_SERVER_MUTEX_WAIT_TIME);
790 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
792 result = NT_STATUS_POSSIBLE_DEADLOCK;
796 if ((*cli = cli_initialise()) == NULL) {
797 DEBUG(1, ("Could not cli_initialize\n"));
798 result = NT_STATUS_NO_MEMORY;
802 (*cli)->timeout = 10000; /* 10 seconds */
804 fstrcpy((*cli)->desthost, controller);
805 (*cli)->use_kerberos = True;
807 peeraddr_len = sizeof(peeraddr);
809 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
810 (peeraddr_len != sizeof(struct sockaddr_in)) ||
811 (peeraddr_in->sin_family != PF_INET))
813 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
814 result = NT_STATUS_UNSUCCESSFUL;
818 if (ntohs(peeraddr_in->sin_port) == 139) {
819 struct nmb_name calling;
820 struct nmb_name called;
822 make_nmb_name(&calling, global_myname(), 0x0);
823 make_nmb_name(&called, "*SMBSERVER", 0x20);
825 if (!cli_session_request(*cli, &calling, &called)) {
826 DEBUG(8, ("cli_session_request failed for %s\n",
828 result = NT_STATUS_UNSUCCESSFUL;
833 cli_setup_signing_state(*cli, Undefined);
835 result = cli_negprot(*cli);
837 if (!NT_STATUS_IS_OK(result)) {
838 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
842 if (!is_dc_trusted_domain_situation(domain->name) &&
843 (*cli)->protocol >= PROTOCOL_NT1 &&
844 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
846 ADS_STATUS ads_status;
848 result = get_trust_creds(domain, &machine_password,
850 &machine_krb5_principal);
851 if (!NT_STATUS_IS_OK(result)) {
855 if (lp_security() == SEC_ADS) {
857 /* Try a krb5 session */
859 (*cli)->use_kerberos = True;
860 DEBUG(5, ("connecting to %s from %s with kerberos principal "
861 "[%s] and realm [%s]\n", controller, global_myname(),
862 machine_krb5_principal, domain->alt_name));
864 winbindd_set_locator_kdc_envs(domain);
866 ads_status = cli_session_setup_spnego(*cli,
867 machine_krb5_principal,
872 if (!ADS_ERR_OK(ads_status)) {
873 DEBUG(4,("failed kerberos session setup with %s\n",
874 ads_errstr(ads_status)));
877 result = ads_ntstatus(ads_status);
878 if (NT_STATUS_IS_OK(result)) {
879 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
880 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
881 goto session_setup_done;
885 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
886 (*cli)->use_kerberos = False;
888 DEBUG(5, ("connecting to %s from %s with username "
889 "[%s]\\[%s]\n", controller, global_myname(),
890 lp_workgroup(), machine_account));
892 ads_status = cli_session_setup_spnego(*cli,
897 if (!ADS_ERR_OK(ads_status)) {
898 DEBUG(4, ("authenticated session setup failed with %s\n",
899 ads_errstr(ads_status)));
902 result = ads_ntstatus(ads_status);
903 if (NT_STATUS_IS_OK(result)) {
904 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
905 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
906 goto session_setup_done;
910 /* Fall back to non-kerberos session setup with auth_user */
912 (*cli)->use_kerberos = False;
914 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
916 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
917 (strlen(ipc_username) > 0)) {
919 /* Only try authenticated if we have a username */
921 DEBUG(5, ("connecting to %s from %s with username "
922 "[%s]\\[%s]\n", controller, global_myname(),
923 ipc_domain, ipc_username));
925 if (NT_STATUS_IS_OK(cli_session_setup(
927 ipc_password, strlen(ipc_password)+1,
928 ipc_password, strlen(ipc_password)+1,
930 /* Successful logon with given username. */
931 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
932 goto session_setup_done;
934 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
935 ipc_domain, ipc_username ));
941 /* Fall back to anonymous connection, this might fail later */
942 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
943 "connection for DC %s\n",
946 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
948 DEBUG(5, ("Connected anonymously\n"));
949 cli_init_creds(*cli, "", "", "");
950 goto session_setup_done;
953 result = cli_nt_error(*cli);
955 if (NT_STATUS_IS_OK(result))
956 result = NT_STATUS_UNSUCCESSFUL;
958 /* We can't session setup */
964 /* cache the server name for later connections */
966 saf_store( domain->name, (*cli)->desthost );
967 if (domain->alt_name && (*cli)->use_kerberos) {
968 saf_store( domain->alt_name, (*cli)->desthost );
971 winbindd_set_locator_kdc_envs(domain);
973 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
975 result = cli_nt_error(*cli);
977 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
979 if (NT_STATUS_IS_OK(result))
980 result = NT_STATUS_UNSUCCESSFUL;
988 /* set the domain if empty; needed for schannel connections */
989 if ( !*(*cli)->domain ) {
990 fstrcpy( (*cli)->domain, domain->name );
993 result = NT_STATUS_OK;
997 SAFE_FREE(machine_account);
998 SAFE_FREE(machine_password);
999 SAFE_FREE(machine_krb5_principal);
1000 SAFE_FREE(ipc_username);
1001 SAFE_FREE(ipc_domain);
1002 SAFE_FREE(ipc_password);
1004 if (!NT_STATUS_IS_OK(result)) {
1005 winbind_add_failed_connection_entry(domain, controller, result);
1006 if ((*cli) != NULL) {
1015 /*******************************************************************
1016 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1019 Keeps the list unique by not adding duplicate entries.
1021 @param[in] mem_ctx talloc memory context to allocate from
1022 @param[in] domain_name domain of the DC
1023 @param[in] dcname name of the DC to add to the list
1024 @param[in] pss Internet address and port pair to add to the list
1025 @param[in,out] dcs array of dc_name_ip structures to add to
1026 @param[in,out] num_dcs number of dcs returned in the dcs array
1027 @return true if the list was added to, false otherwise
1028 *******************************************************************/
1030 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1031 const char *dcname, struct sockaddr_storage *pss,
1032 struct dc_name_ip **dcs, int *num)
1036 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1037 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1041 /* Make sure there's no duplicates in the list */
1042 for (i=0; i<*num; i++)
1043 if (sockaddr_equal((struct sockaddr *)&(*dcs)[i].ss, (struct sockaddr *)pss))
1046 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1051 fstrcpy((*dcs)[*num].name, dcname);
1052 (*dcs)[*num].ss = *pss;
1057 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1058 struct sockaddr_storage *pss, uint16 port,
1059 struct sockaddr_storage **addrs, int *num)
1061 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1063 if (*addrs == NULL) {
1068 (*addrs)[*num] = *pss;
1069 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1075 /*******************************************************************
1076 convert an ip to a name
1077 *******************************************************************/
1079 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1080 const struct winbindd_domain *domain,
1081 struct sockaddr_storage *pss,
1084 struct ip_service ip_list;
1085 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1091 /* For active directory servers, try to get the ldap server name.
1092 None of these failures should be considered critical for now */
1094 if (lp_security() == SEC_ADS) {
1096 ADS_STATUS ads_status;
1097 char addr[INET6_ADDRSTRLEN];
1099 print_sockaddr(addr, sizeof(addr), pss);
1101 ads = ads_init(domain->alt_name, domain->name, addr);
1102 ads->auth.flags |= ADS_AUTH_NO_BIND;
1104 ads_status = ads_connect(ads);
1105 if (ADS_ERR_OK(ads_status)) {
1106 /* We got a cldap packet. */
1107 fstrcpy(name, ads->config.ldap_server_name);
1108 namecache_store(name, 0x20, 1, &ip_list);
1110 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1112 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1113 if (ads_closest_dc(ads)) {
1114 char *sitename = sitename_fetch(ads->config.realm);
1116 /* We're going to use this KDC for this realm/domain.
1117 If we are using sites, then force the krb5 libs
1120 create_local_private_krb5_conf_for_domain(domain->alt_name,
1125 SAFE_FREE(sitename);
1127 /* use an off site KDC */
1128 create_local_private_krb5_conf_for_domain(domain->alt_name,
1133 winbindd_set_locator_kdc_envs(domain);
1135 /* Ensure we contact this DC also. */
1136 saf_store( domain->name, name);
1137 saf_store( domain->alt_name, name);
1140 ads_destroy( &ads );
1144 ads_destroy( &ads );
1148 /* try GETDC requests next */
1150 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1151 pss, domain->name, &domain->sid,
1153 const char *dc_name = NULL;
1156 for (i=0; i<5; i++) {
1157 if (receive_getdc_response(mem_ctx, pss, domain->name,
1160 fstrcpy(name, dc_name);
1161 namecache_store(name, 0x20, 1, &ip_list);
1168 /* try node status request */
1170 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1171 namecache_store(name, 0x20, 1, &ip_list);
1177 /*******************************************************************
1178 Retrieve a list of IP addresses for domain controllers.
1180 The array is sorted in the preferred connection order.
1182 @param[in] mem_ctx talloc memory context to allocate from
1183 @param[in] domain domain to retrieve DCs for
1184 @param[out] dcs array of dcs that will be returned
1185 @param[out] num_dcs number of dcs returned in the dcs array
1187 *******************************************************************/
1189 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1190 struct dc_name_ip **dcs, int *num_dcs)
1193 struct sockaddr_storage ss;
1194 struct ip_service *ip_list = NULL;
1195 int iplist_size = 0;
1198 enum security_types sec = (enum security_types)lp_security();
1200 is_our_domain = strequal(domain->name, lp_workgroup());
1202 /* If not our domain, get the preferred DC, by asking our primary DC */
1204 && get_dc_name_via_netlogon(domain, dcname, &ss)
1205 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1208 char addr[INET6_ADDRSTRLEN];
1209 print_sockaddr(addr, sizeof(addr), &ss);
1210 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1215 if (sec == SEC_ADS) {
1216 char *sitename = NULL;
1218 /* We need to make sure we know the local site before
1219 doing any DNS queries, as this will restrict the
1220 get_sorted_dc_list() call below to only fetching
1221 DNS records for the correct site. */
1223 /* Find any DC to get the site record.
1224 We deliberately don't care about the
1227 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1229 sitename = sitename_fetch(domain->alt_name);
1232 /* Do the site-specific AD dns lookup first. */
1233 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1234 &iplist_size, True);
1236 /* Add ips to the DC array. We don't look up the name
1237 of the DC in this function, but we fill in the char*
1238 of the ip now to make the failed connection cache
1240 for ( i=0; i<iplist_size; i++ ) {
1241 char addr[INET6_ADDRSTRLEN];
1242 print_sockaddr(addr, sizeof(addr),
1244 add_one_dc_unique(mem_ctx,
1253 SAFE_FREE(sitename);
1257 /* Now we add DCs from the main AD DNS lookup. */
1258 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1259 &iplist_size, True);
1261 for ( i=0; i<iplist_size; i++ ) {
1262 char addr[INET6_ADDRSTRLEN];
1263 print_sockaddr(addr, sizeof(addr),
1265 add_one_dc_unique(mem_ctx,
1277 /* Try standard netbios queries if no ADS */
1278 if (*num_dcs == 0) {
1279 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1282 for ( i=0; i<iplist_size; i++ ) {
1283 char addr[INET6_ADDRSTRLEN];
1284 print_sockaddr(addr, sizeof(addr),
1286 add_one_dc_unique(mem_ctx,
1301 /*******************************************************************
1302 Find and make a connection to a DC in the given domain.
1304 @param[in] mem_ctx talloc memory context to allocate from
1305 @param[in] domain domain to find a dc in
1306 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1307 @param[out] pss DC Internet address and port
1308 @param[out] fd fd of the open socket connected to the newly found dc
1309 @return true when a DC connection is made, false otherwise
1310 *******************************************************************/
1312 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1313 struct winbindd_domain *domain,
1314 fstring dcname, struct sockaddr_storage *pss, int *fd)
1316 struct dc_name_ip *dcs = NULL;
1319 const char **dcnames = NULL;
1320 int num_dcnames = 0;
1322 struct sockaddr_storage *addrs = NULL;
1330 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1333 for (i=0; i<num_dcs; i++) {
1335 if (!add_string_to_array(mem_ctx, dcs[i].name,
1336 &dcnames, &num_dcnames)) {
1339 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1340 &addrs, &num_addrs)) {
1344 if (!add_string_to_array(mem_ctx, dcs[i].name,
1345 &dcnames, &num_dcnames)) {
1348 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1349 &addrs, &num_addrs)) {
1354 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1357 if ((addrs == NULL) || (dcnames == NULL))
1360 /* 5 second timeout. */
1361 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1362 for (i=0; i<num_dcs; i++) {
1363 char ab[INET6_ADDRSTRLEN];
1364 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1365 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1366 "domain %s address %s. Error was %s\n",
1367 domain->name, ab, strerror(errno) ));
1368 winbind_add_failed_connection_entry(domain,
1369 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1374 *pss = addrs[fd_index];
1376 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1377 /* Ok, we've got a name for the DC */
1378 fstrcpy(dcname, dcnames[fd_index]);
1382 /* Try to figure out the name */
1383 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1387 /* We can not continue without the DC's name */
1388 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1389 NT_STATUS_UNSUCCESSFUL);
1391 /* Throw away all arrays as we're doing this again. */
1395 TALLOC_FREE(dcnames);
1407 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1408 struct winbindd_cm_conn *new_conn)
1410 TALLOC_CTX *mem_ctx;
1412 char *saf_servername = saf_fetch( domain->name );
1415 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1416 SAFE_FREE(saf_servername);
1417 set_domain_offline(domain);
1418 return NT_STATUS_NO_MEMORY;
1421 /* we have to check the server affinity cache here since
1422 later we selecte a DC based on response time and not preference */
1424 /* Check the negative connection cache
1425 before talking to it. It going down may have
1426 triggered the reconnection. */
1428 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1430 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1431 saf_servername, domain->name ));
1433 /* convert an ip address to a name */
1434 if (is_ipaddress( saf_servername ) ) {
1436 struct sockaddr_storage ss;
1438 if (!interpret_string_addr(&ss, saf_servername,
1440 return NT_STATUS_UNSUCCESSFUL;
1442 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1443 fstrcpy( domain->dcname, saf_name );
1445 winbind_add_failed_connection_entry(
1446 domain, saf_servername,
1447 NT_STATUS_UNSUCCESSFUL);
1450 fstrcpy( domain->dcname, saf_servername );
1453 SAFE_FREE( saf_servername );
1456 for (retries = 0; retries < 3; retries++) {
1460 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1462 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1463 domain->dcname, domain->name ));
1466 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1467 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1469 struct sockaddr_storage *addrs = NULL;
1473 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1474 set_domain_offline(domain);
1475 talloc_destroy(mem_ctx);
1476 return NT_STATUS_NO_MEMORY;
1478 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1479 set_domain_offline(domain);
1480 talloc_destroy(mem_ctx);
1481 return NT_STATUS_NO_MEMORY;
1484 /* 5 second timeout. */
1485 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1491 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1493 /* This is the one place where we will
1494 set the global winbindd offline state
1495 to true, if a "WINBINDD_OFFLINE" entry
1496 is found in the winbindd cache. */
1497 set_global_winbindd_state_offline();
1501 new_conn->cli = NULL;
1503 result = cm_prepare_connection(domain, fd, domain->dcname,
1504 &new_conn->cli, &retry);
1510 if (NT_STATUS_IS_OK(result)) {
1512 winbindd_set_locator_kdc_envs(domain);
1514 if (domain->online == False) {
1515 /* We're changing state from offline to online. */
1516 set_global_winbindd_state_online();
1518 set_domain_online(domain);
1520 /* Ensure we setup the retry handler. */
1521 set_domain_offline(domain);
1524 talloc_destroy(mem_ctx);
1528 /* Close down all open pipes on a connection. */
1530 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1532 /* We're closing down a possibly dead
1533 connection. Don't have impossibly long (10s) timeouts. */
1536 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1539 if (conn->samr_pipe != NULL) {
1540 TALLOC_FREE(conn->samr_pipe);
1541 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1543 cli_set_timeout(conn->cli, 500);
1547 if (conn->lsa_pipe != NULL) {
1548 TALLOC_FREE(conn->lsa_pipe);
1549 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1551 cli_set_timeout(conn->cli, 500);
1555 if (conn->netlogon_pipe != NULL) {
1556 TALLOC_FREE(conn->netlogon_pipe);
1557 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1559 cli_set_timeout(conn->cli, 500);
1564 cli_shutdown(conn->cli);
1570 void close_conns_after_fork(void)
1572 struct winbindd_domain *domain;
1574 for (domain = domain_list(); domain; domain = domain->next) {
1575 if (domain->conn.cli == NULL)
1578 if (domain->conn.cli->fd == -1)
1581 close(domain->conn.cli->fd);
1582 domain->conn.cli->fd = -1;
1586 static bool connection_ok(struct winbindd_domain *domain)
1588 if (domain->conn.cli == NULL) {
1589 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1590 "cli!\n", domain->dcname, domain->name));
1594 if (!domain->conn.cli->initialised) {
1595 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1596 "initialised!\n", domain->dcname, domain->name));
1600 if (domain->conn.cli->fd == -1) {
1601 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1602 "never started (fd == -1)\n",
1603 domain->dcname, domain->name));
1607 if (domain->online == False) {
1608 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1615 /* Initialize a new connection up to the RPC BIND.
1616 Bypass online status check so always does network calls. */
1618 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1622 /* Internal connections never use the network. */
1623 if (domain->internal) {
1624 domain->initialized = True;
1625 return NT_STATUS_OK;
1628 if (connection_ok(domain)) {
1629 if (!domain->initialized) {
1630 set_dc_type_and_flags(domain);
1632 return NT_STATUS_OK;
1635 invalidate_cm_connection(&domain->conn);
1637 result = cm_open_connection(domain, &domain->conn);
1639 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1640 set_dc_type_and_flags(domain);
1646 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1648 if (domain->initialized && !domain->online) {
1649 /* We check for online status elsewhere. */
1650 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1653 return init_dc_connection_network(domain);
1656 /******************************************************************************
1657 Set the trust flags (direction and forest location) for a domain
1658 ******************************************************************************/
1660 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1662 struct winbindd_domain *our_domain;
1663 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1664 struct netr_DomainTrustList trusts;
1666 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1667 NETR_TRUST_FLAG_OUTBOUND |
1668 NETR_TRUST_FLAG_INBOUND);
1669 struct rpc_pipe_client *cli;
1670 TALLOC_CTX *mem_ctx = NULL;
1672 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1674 /* Our primary domain doesn't need to worry about trust flags.
1675 Force it to go through the network setup */
1676 if ( domain->primary ) {
1680 our_domain = find_our_domain();
1682 if ( !connection_ok(our_domain) ) {
1683 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1687 /* This won't work unless our domain is AD */
1689 if ( !our_domain->active_directory ) {
1693 /* Use DsEnumerateDomainTrusts to get us the trust direction
1696 result = cm_connect_netlogon(our_domain, &cli);
1698 if (!NT_STATUS_IS_OK(result)) {
1699 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1700 "a connection to %s for PIPE_NETLOGON (%s)\n",
1701 domain->name, nt_errstr(result)));
1705 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1706 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1710 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1715 if (!NT_STATUS_IS_OK(result)) {
1716 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1717 "failed to query trusted domain list: %s\n",
1718 nt_errstr(result)));
1719 talloc_destroy(mem_ctx);
1723 /* Now find the domain name and get the flags */
1725 for ( i=0; i<trusts.count; i++ ) {
1726 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1727 domain->domain_flags = trusts.array[i].trust_flags;
1728 domain->domain_type = trusts.array[i].trust_type;
1729 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1731 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1732 domain->active_directory = True;
1734 /* This flag is only set if the domain is *our*
1735 primary domain and the primary domain is in
1738 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1740 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1741 "native mode.\n", domain->name,
1742 domain->native_mode ? "" : "NOT "));
1744 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1745 "running active directory.\n", domain->name,
1746 domain->active_directory ? "" : "NOT "));
1749 domain->initialized = True;
1751 if ( !winbindd_can_contact_domain( domain) )
1752 domain->internal = True;
1758 talloc_destroy( mem_ctx );
1760 return domain->initialized;
1763 /******************************************************************************
1764 We can 'sense' certain things about the DC by it's replies to certain
1767 This tells us if this particular remote server is Active Directory, and if it
1769 ******************************************************************************/
1771 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1775 TALLOC_CTX *mem_ctx = NULL;
1776 struct rpc_pipe_client *cli;
1778 union dssetup_DsRoleInfo info;
1779 union lsa_PolicyInformation *lsa_info = NULL;
1781 if (!connection_ok(domain)) {
1785 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1788 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1792 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1794 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1795 &ndr_table_dssetup.syntax_id,
1798 if (!NT_STATUS_IS_OK(result)) {
1799 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1800 "PI_DSSETUP on domain %s: (%s)\n",
1801 domain->name, nt_errstr(result)));
1803 /* if this is just a non-AD domain we need to continue
1804 * identifying so that we can in the end return with
1805 * domain->initialized = True - gd */
1810 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1811 DS_ROLE_BASIC_INFORMATION,
1816 if (!NT_STATUS_IS_OK(result)) {
1817 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1818 "on domain %s failed: (%s)\n",
1819 domain->name, nt_errstr(result)));
1821 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1822 * every opcode on the DSSETUP pipe, continue with
1823 * no_dssetup mode here as well to get domain->initialized
1826 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1830 TALLOC_FREE(mem_ctx);
1834 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1835 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1836 domain->native_mode = True;
1838 domain->native_mode = False;
1842 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1843 &ndr_table_lsarpc.syntax_id, &cli);
1845 if (!NT_STATUS_IS_OK(result)) {
1846 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1847 "PI_LSARPC on domain %s: (%s)\n",
1848 domain->name, nt_errstr(result)));
1850 TALLOC_FREE(mem_ctx);
1854 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1855 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1857 if (NT_STATUS_IS_OK(result)) {
1858 /* This particular query is exactly what Win2k clients use
1859 to determine that the DC is active directory */
1860 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1862 LSA_POLICY_INFO_DNS,
1866 if (NT_STATUS_IS_OK(result)) {
1867 domain->active_directory = True;
1869 if (lsa_info->dns.name.string) {
1870 fstrcpy(domain->name, lsa_info->dns.name.string);
1873 if (lsa_info->dns.dns_domain.string) {
1874 fstrcpy(domain->alt_name,
1875 lsa_info->dns.dns_domain.string);
1878 /* See if we can set some domain trust flags about
1881 if (lsa_info->dns.dns_forest.string) {
1882 fstrcpy(domain->forest_name,
1883 lsa_info->dns.dns_forest.string);
1885 if (strequal(domain->forest_name, domain->alt_name)) {
1886 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1890 if (lsa_info->dns.sid) {
1891 sid_copy(&domain->sid, lsa_info->dns.sid);
1894 domain->active_directory = False;
1896 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1897 SEC_RIGHTS_MAXIMUM_ALLOWED,
1900 if (!NT_STATUS_IS_OK(result)) {
1904 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1906 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1909 if (NT_STATUS_IS_OK(result)) {
1911 if (lsa_info->account_domain.name.string) {
1912 fstrcpy(domain->name,
1913 lsa_info->account_domain.name.string);
1916 if (lsa_info->account_domain.sid) {
1917 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1923 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1924 domain->name, domain->native_mode ? "" : "NOT "));
1926 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1927 domain->name, domain->active_directory ? "" : "NOT "));
1931 TALLOC_FREE(mem_ctx);
1933 domain->initialized = True;
1936 /**********************************************************************
1937 Set the domain_flags (trust attributes, domain operating modes, etc...
1938 ***********************************************************************/
1940 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1942 /* we always have to contact our primary domain */
1944 if ( domain->primary ) {
1945 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1946 "primary domain\n"));
1947 set_dc_type_and_flags_connect( domain );
1951 /* Use our DC to get the information if possible */
1953 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1954 /* Otherwise, fallback to contacting the
1956 set_dc_type_and_flags_connect( domain );
1964 /**********************************************************************
1965 ***********************************************************************/
1967 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1968 struct dcinfo **ppdc)
1971 struct rpc_pipe_client *netlogon_pipe;
1973 if (lp_client_schannel() == False) {
1977 result = cm_connect_netlogon(domain, &netlogon_pipe);
1978 if (!NT_STATUS_IS_OK(result)) {
1982 /* Return a pointer to the struct dcinfo from the
1985 if (!domain->conn.netlogon_pipe->dc) {
1989 *ppdc = domain->conn.netlogon_pipe->dc;
1993 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1994 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1996 struct winbindd_cm_conn *conn;
1997 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1999 struct dcinfo *p_dcinfo;
2000 char *machine_password = NULL;
2001 char *machine_account = NULL;
2002 char *domain_name = NULL;
2004 result = init_dc_connection(domain);
2005 if (!NT_STATUS_IS_OK(result)) {
2009 conn = &domain->conn;
2011 if (conn->samr_pipe != NULL) {
2017 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2018 * sign and sealed pipe using the machine account password by
2019 * preference. If we can't - try schannel, if that fails, try
2023 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2024 if ((conn->cli->user_name[0] == '\0') ||
2025 (conn->cli->domain[0] == '\0') ||
2026 (conn_pwd[0] == '\0'))
2028 result = get_trust_creds(domain, &machine_password,
2029 &machine_account, NULL);
2030 if (!NT_STATUS_IS_OK(result)) {
2031 DEBUG(10, ("cm_connect_sam: No no user available for "
2032 "domain %s, trying schannel\n", conn->cli->domain));
2035 domain_name = domain->name;
2037 machine_password = SMB_STRDUP(conn_pwd);
2038 machine_account = SMB_STRDUP(conn->cli->user_name);
2039 domain_name = conn->cli->domain;
2042 if (!machine_password || !machine_account) {
2043 result = NT_STATUS_NO_MEMORY;
2047 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2048 authenticated SAMR pipe with sign & seal. */
2049 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2050 &ndr_table_samr.syntax_id,
2051 PIPE_AUTH_LEVEL_PRIVACY,
2057 if (!NT_STATUS_IS_OK(result)) {
2058 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2059 "pipe for domain %s using NTLMSSP "
2060 "authenticated pipe: user %s\\%s. Error was "
2061 "%s\n", domain->name, domain_name,
2062 machine_account, nt_errstr(result)));
2066 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2067 "domain %s using NTLMSSP authenticated "
2068 "pipe: user %s\\%s\n", domain->name,
2069 domain_name, machine_account));
2071 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2072 conn->samr_pipe->desthost,
2073 SEC_RIGHTS_MAXIMUM_ALLOWED,
2074 &conn->sam_connect_handle);
2075 if (NT_STATUS_IS_OK(result)) {
2078 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2079 "failed for domain %s, error was %s. Trying schannel\n",
2080 domain->name, nt_errstr(result) ));
2081 TALLOC_FREE(conn->samr_pipe);
2085 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2087 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2088 /* If this call fails - conn->cli can now be NULL ! */
2089 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2090 "for domain %s, trying anon\n", domain->name));
2093 result = cli_rpc_pipe_open_schannel_with_key
2094 (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
2095 domain->name, p_dcinfo, &conn->samr_pipe);
2097 if (!NT_STATUS_IS_OK(result)) {
2098 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2099 "domain %s using schannel. Error was %s\n",
2100 domain->name, nt_errstr(result) ));
2103 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2104 "schannel.\n", domain->name ));
2106 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2107 conn->samr_pipe->desthost,
2108 SEC_RIGHTS_MAXIMUM_ALLOWED,
2109 &conn->sam_connect_handle);
2110 if (NT_STATUS_IS_OK(result)) {
2113 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2114 "for domain %s, error was %s. Trying anonymous\n",
2115 domain->name, nt_errstr(result) ));
2116 TALLOC_FREE(conn->samr_pipe);
2120 /* Finally fall back to anonymous. */
2121 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2124 if (!NT_STATUS_IS_OK(result)) {
2128 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2129 conn->samr_pipe->desthost,
2130 SEC_RIGHTS_MAXIMUM_ALLOWED,
2131 &conn->sam_connect_handle);
2132 if (!NT_STATUS_IS_OK(result)) {
2133 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2134 "for domain %s Error was %s\n",
2135 domain->name, nt_errstr(result) ));
2140 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2142 &conn->sam_connect_handle,
2143 SEC_RIGHTS_MAXIMUM_ALLOWED,
2145 &conn->sam_domain_handle);
2149 if (!NT_STATUS_IS_OK(result)) {
2150 invalidate_cm_connection(conn);
2154 *cli = conn->samr_pipe;
2155 *sam_handle = conn->sam_domain_handle;
2156 SAFE_FREE(machine_password);
2157 SAFE_FREE(machine_account);
2161 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2162 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2164 struct winbindd_cm_conn *conn;
2165 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2167 struct dcinfo *p_dcinfo;
2169 result = init_dc_connection(domain);
2170 if (!NT_STATUS_IS_OK(result))
2173 conn = &domain->conn;
2175 if (conn->lsa_pipe != NULL) {
2179 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2180 if ((conn->cli->user_name[0] == '\0') ||
2181 (conn->cli->domain[0] == '\0') ||
2182 (conn_pwd[0] == '\0')) {
2183 DEBUG(10, ("cm_connect_lsa: No no user available for "
2184 "domain %s, trying schannel\n", conn->cli->domain));
2188 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2189 * authenticated LSA pipe with sign & seal. */
2190 result = cli_rpc_pipe_open_spnego_ntlmssp
2191 (conn->cli, &ndr_table_lsarpc.syntax_id,
2192 PIPE_AUTH_LEVEL_PRIVACY,
2193 conn->cli->domain, conn->cli->user_name, conn_pwd,
2196 if (!NT_STATUS_IS_OK(result)) {
2197 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2198 "domain %s using NTLMSSP authenticated pipe: user "
2199 "%s\\%s. Error was %s. Trying schannel.\n",
2200 domain->name, conn->cli->domain,
2201 conn->cli->user_name, nt_errstr(result)));
2205 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2206 "NTLMSSP authenticated pipe: user %s\\%s\n",
2207 domain->name, conn->cli->domain, conn->cli->user_name ));
2209 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2210 SEC_RIGHTS_MAXIMUM_ALLOWED,
2212 if (NT_STATUS_IS_OK(result)) {
2216 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2219 TALLOC_FREE(conn->lsa_pipe);
2223 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2225 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2226 /* If this call fails - conn->cli can now be NULL ! */
2227 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2228 "for domain %s, trying anon\n", domain->name));
2231 result = cli_rpc_pipe_open_schannel_with_key
2232 (conn->cli, &ndr_table_lsarpc.syntax_id,
2233 PIPE_AUTH_LEVEL_PRIVACY,
2234 domain->name, p_dcinfo, &conn->lsa_pipe);
2236 if (!NT_STATUS_IS_OK(result)) {
2237 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2238 "domain %s using schannel. Error was %s\n",
2239 domain->name, nt_errstr(result) ));
2242 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2243 "schannel.\n", domain->name ));
2245 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2246 SEC_RIGHTS_MAXIMUM_ALLOWED,
2248 if (NT_STATUS_IS_OK(result)) {
2252 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2255 TALLOC_FREE(conn->lsa_pipe);
2259 result = cli_rpc_pipe_open_noauth(conn->cli,
2260 &ndr_table_lsarpc.syntax_id,
2262 if (!NT_STATUS_IS_OK(result)) {
2263 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2267 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2268 SEC_RIGHTS_MAXIMUM_ALLOWED,
2271 if (!NT_STATUS_IS_OK(result)) {
2272 invalidate_cm_connection(conn);
2276 *cli = conn->lsa_pipe;
2277 *lsa_policy = conn->lsa_policy;
2281 /****************************************************************************
2282 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2283 session key stored in conn->netlogon_pipe->dc->sess_key.
2284 ****************************************************************************/
2286 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2287 struct rpc_pipe_client **cli)
2289 struct winbindd_cm_conn *conn;
2292 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2294 uint32 sec_chan_type;
2295 const char *account_name;
2296 struct rpc_pipe_client *netlogon_pipe = NULL;
2300 result = init_dc_connection(domain);
2301 if (!NT_STATUS_IS_OK(result)) {
2305 conn = &domain->conn;
2307 if (conn->netlogon_pipe != NULL) {
2308 *cli = conn->netlogon_pipe;
2309 return NT_STATUS_OK;
2312 result = cli_rpc_pipe_open_noauth(conn->cli,
2313 &ndr_table_netlogon.syntax_id,
2315 if (!NT_STATUS_IS_OK(result)) {
2319 if ((!IS_DC) && (!domain->primary)) {
2320 /* Clear the schannel request bit and drop down */
2321 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2325 if (lp_client_schannel() != False) {
2326 neg_flags |= NETLOGON_NEG_SCHANNEL;
2329 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2332 TALLOC_FREE(netlogon_pipe);
2333 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2336 result = rpccli_netlogon_setup_creds(
2338 domain->dcname, /* server name. */
2339 domain->name, /* domain name */
2340 global_myname(), /* client name */
2341 account_name, /* machine account */
2342 mach_pwd, /* machine password */
2343 sec_chan_type, /* from get_trust_pw */
2346 if (!NT_STATUS_IS_OK(result)) {
2347 TALLOC_FREE(netlogon_pipe);
2351 if ((lp_client_schannel() == True) &&
2352 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2353 DEBUG(3, ("Server did not offer schannel\n"));
2354 TALLOC_FREE(netlogon_pipe);
2355 return NT_STATUS_ACCESS_DENIED;
2359 if ((lp_client_schannel() == False) ||
2360 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2362 * NetSamLogonEx only works for schannel
2364 domain->can_do_samlogon_ex = False;
2366 /* We're done - just keep the existing connection to NETLOGON
2368 conn->netlogon_pipe = netlogon_pipe;
2369 *cli = conn->netlogon_pipe;
2370 return NT_STATUS_OK;
2373 /* Using the credentials from the first pipe, open a signed and sealed
2374 second netlogon pipe. The session key is stored in the schannel
2375 part of the new pipe auth struct.
2378 result = cli_rpc_pipe_open_schannel_with_key(
2379 conn->cli, &ndr_table_netlogon.syntax_id,
2380 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2381 &conn->netlogon_pipe);
2383 /* We can now close the initial netlogon pipe. */
2384 TALLOC_FREE(netlogon_pipe);
2386 if (!NT_STATUS_IS_OK(result)) {
2387 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2388 "was %s\n", nt_errstr(result)));
2390 /* make sure we return something besides OK */
2391 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2395 * Try NetSamLogonEx for AD domains
2397 domain->can_do_samlogon_ex = domain->active_directory;
2399 *cli = conn->netlogon_pipe;
2400 return NT_STATUS_OK;