2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
63 #include "../libcli/auth/libcli_auth.h"
66 #define DBGC_CLASS DBGC_WINBIND
70 struct sockaddr_storage ss;
73 extern struct winbindd_methods reconnect_methods;
74 extern bool override_logfile;
76 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
77 static void set_dc_type_and_flags( struct winbindd_domain *domain );
78 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
79 struct dc_name_ip **dcs, int *num_dcs);
81 /****************************************************************
82 Child failed to find DC's. Reschedule check.
83 ****************************************************************/
85 static void msg_failed_to_go_online(struct messaging_context *msg,
88 struct server_id server_id,
91 struct winbindd_domain *domain;
92 const char *domainname = (const char *)data->data;
94 if (data->data == NULL || data->length == 0) {
98 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
100 for (domain = domain_list(); domain; domain = domain->next) {
101 if (domain->internal) {
105 if (strequal(domain->name, domainname)) {
106 if (domain->online) {
107 /* We're already online, ignore. */
108 DEBUG(5,("msg_fail_to_go_online: domain %s "
109 "already online.\n", domainname));
113 /* Reschedule the online check. */
114 set_domain_offline(domain);
120 /****************************************************************
121 Actually cause a reconnect from a message.
122 ****************************************************************/
124 static void msg_try_to_go_online(struct messaging_context *msg,
127 struct server_id server_id,
130 struct winbindd_domain *domain;
131 const char *domainname = (const char *)data->data;
133 if (data->data == NULL || data->length == 0) {
137 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
139 for (domain = domain_list(); domain; domain = domain->next) {
140 if (domain->internal) {
144 if (strequal(domain->name, domainname)) {
146 if (domain->online) {
147 /* We're already online, ignore. */
148 DEBUG(5,("msg_try_to_go_online: domain %s "
149 "already online.\n", domainname));
153 /* This call takes care of setting the online
154 flag to true if we connected, or re-adding
155 the offline handler if false. Bypasses online
156 check so always does network calls. */
158 init_dc_connection_network(domain);
164 /****************************************************************
165 Fork a child to try and contact a DC. Do this as contacting a
166 DC requires blocking lookups and we don't want to block our
168 ****************************************************************/
170 static bool fork_child_dc_connect(struct winbindd_domain *domain)
172 struct dc_name_ip *dcs = NULL;
174 TALLOC_CTX *mem_ctx = NULL;
175 pid_t parent_pid = sys_getpid();
181 if (domain->dc_probe_pid != (pid_t)-1) {
183 * We might already have a DC probe
184 * child working, check.
186 if (process_exists_by_pid(domain->dc_probe_pid)) {
187 DEBUG(10,("fork_child_dc_connect: pid %u already "
188 "checking for DC's.\n",
189 (unsigned int)domain->dc_probe_pid));
192 domain->dc_probe_pid = (pid_t)-1;
195 domain->dc_probe_pid = sys_fork();
197 if (domain->dc_probe_pid == (pid_t)-1) {
198 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
202 if (domain->dc_probe_pid != (pid_t)0) {
204 messaging_register(winbind_messaging_context(), NULL,
205 MSG_WINBIND_TRY_TO_GO_ONLINE,
206 msg_try_to_go_online);
207 messaging_register(winbind_messaging_context(), NULL,
208 MSG_WINBIND_FAILED_TO_GO_ONLINE,
209 msg_failed_to_go_online);
215 /* Leave messages blocked - we will never process one. */
217 if (!override_logfile) {
218 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
219 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
224 if (!winbindd_reinit_after_fork(lfile)) {
225 messaging_send_buf(winbind_messaging_context(),
226 pid_to_procid(parent_pid),
227 MSG_WINBIND_FAILED_TO_GO_ONLINE,
228 (uint8 *)domain->name,
229 strlen(domain->name)+1);
234 mem_ctx = talloc_init("fork_child_dc_connect");
236 DEBUG(0,("talloc_init failed.\n"));
237 messaging_send_buf(winbind_messaging_context(),
238 pid_to_procid(parent_pid),
239 MSG_WINBIND_FAILED_TO_GO_ONLINE,
240 (uint8 *)domain->name,
241 strlen(domain->name)+1);
245 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
246 /* Still offline ? Can't find DC's. */
247 messaging_send_buf(winbind_messaging_context(),
248 pid_to_procid(parent_pid),
249 MSG_WINBIND_FAILED_TO_GO_ONLINE,
250 (uint8 *)domain->name,
251 strlen(domain->name)+1);
255 /* We got a DC. Send a message to our parent to get it to
256 try and do the same. */
258 messaging_send_buf(winbind_messaging_context(),
259 pid_to_procid(parent_pid),
260 MSG_WINBIND_TRY_TO_GO_ONLINE,
261 (uint8 *)domain->name,
262 strlen(domain->name)+1);
266 /****************************************************************
267 Handler triggered if we're offline to try and detect a DC.
268 ****************************************************************/
270 static void check_domain_online_handler(struct event_context *ctx,
271 struct timed_event *te,
275 struct winbindd_domain *domain =
276 (struct winbindd_domain *)private_data;
278 DEBUG(10,("check_domain_online_handler: called for domain "
279 "%s (online = %s)\n", domain->name,
280 domain->online ? "True" : "False" ));
282 TALLOC_FREE(domain->check_online_event);
284 /* Are we still in "startup" mode ? */
286 if (domain->startup && (now.tv_sec > domain->startup_time + 30)) {
287 /* No longer in "startup" mode. */
288 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
290 domain->startup = False;
293 /* We've been told to stay offline, so stay
296 if (get_global_winbindd_state_offline()) {
297 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
302 /* Fork a child to test if it can contact a DC.
303 If it can then send ourselves a message to
304 cause a reconnect. */
306 fork_child_dc_connect(domain);
309 /****************************************************************
310 If we're still offline setup the timeout check.
311 ****************************************************************/
313 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
315 int wbr = lp_winbind_reconnect_delay();
317 if (domain->startup) {
318 domain->check_online_timeout = 10;
319 } else if (domain->check_online_timeout < wbr) {
320 domain->check_online_timeout = wbr;
324 /****************************************************************
325 Set domain offline and also add handler to put us back online
327 ****************************************************************/
329 void set_domain_offline(struct winbindd_domain *domain)
331 DEBUG(10,("set_domain_offline: called for domain %s\n",
334 TALLOC_FREE(domain->check_online_event);
336 if (domain->internal) {
337 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
342 domain->online = False;
344 /* Offline domains are always initialized. They're
345 re-initialized when they go back online. */
347 domain->initialized = True;
349 /* We only add the timeout handler that checks and
350 allows us to go back online when we've not
351 been told to remain offline. */
353 if (get_global_winbindd_state_offline()) {
354 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
359 /* If we're in statup mode, check again in 10 seconds, not in
360 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
362 calc_new_online_timeout_check(domain);
364 domain->check_online_event = event_add_timed(winbind_event_context(),
366 timeval_current_ofs(domain->check_online_timeout,0),
367 check_domain_online_handler,
370 /* The above *has* to succeed for winbindd to work. */
371 if (!domain->check_online_event) {
372 smb_panic("set_domain_offline: failed to add online handler");
375 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
378 /* Send an offline message to the idmap child when our
379 primary domain goes offline */
381 if ( domain->primary ) {
382 struct winbindd_child *idmap = idmap_child();
384 if ( idmap->pid != 0 ) {
385 messaging_send_buf(winbind_messaging_context(),
386 pid_to_procid(idmap->pid),
388 (uint8 *)domain->name,
389 strlen(domain->name)+1);
396 /****************************************************************
397 Set domain online - if allowed.
398 ****************************************************************/
400 static void set_domain_online(struct winbindd_domain *domain)
402 DEBUG(10,("set_domain_online: called for domain %s\n",
405 if (domain->internal) {
406 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
411 if (get_global_winbindd_state_offline()) {
412 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
417 winbindd_set_locator_kdc_envs(domain);
419 /* If we are waiting to get a krb5 ticket, trigger immediately. */
420 ccache_regain_all_now();
422 /* Ok, we're out of any startup mode now... */
423 domain->startup = False;
425 if (domain->online == False) {
426 /* We were offline - now we're online. We default to
427 using the MS-RPC backend if we started offline,
428 and if we're going online for the first time we
429 should really re-initialize the backends and the
430 checks to see if we're talking to an AD or NT domain.
433 domain->initialized = False;
435 /* 'reconnect_methods' is the MS-RPC backend. */
436 if (domain->backend == &reconnect_methods) {
437 domain->backend = NULL;
441 /* Ensure we have no online timeout checks. */
442 domain->check_online_timeout = 0;
443 TALLOC_FREE(domain->check_online_event);
445 /* Ensure we ignore any pending child messages. */
446 messaging_deregister(winbind_messaging_context(),
447 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
448 messaging_deregister(winbind_messaging_context(),
449 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
451 domain->online = True;
453 /* Send an online message to the idmap child when our
454 primary domain comes online */
456 if ( domain->primary ) {
457 struct winbindd_child *idmap = idmap_child();
459 if ( idmap->pid != 0 ) {
460 messaging_send_buf(winbind_messaging_context(),
461 pid_to_procid(idmap->pid),
463 (uint8 *)domain->name,
464 strlen(domain->name)+1);
471 /****************************************************************
472 Requested to set a domain online.
473 ****************************************************************/
475 void set_domain_online_request(struct winbindd_domain *domain)
479 DEBUG(10,("set_domain_online_request: called for domain %s\n",
482 if (get_global_winbindd_state_offline()) {
483 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
488 /* We've been told it's safe to go online and
489 try and connect to a DC. But I don't believe it
490 because network manager seems to lie.
491 Wait at least 5 seconds. Heuristics suck... */
496 /* Go into "startup" mode again. */
497 domain->startup_time = tev.tv_sec;
498 domain->startup = True;
502 if (!domain->check_online_event) {
503 /* If we've come from being globally offline we
504 don't have a check online event handler set.
505 We need to add one now we're trying to go
508 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
512 TALLOC_FREE(domain->check_online_event);
514 domain->check_online_event = event_add_timed(winbind_event_context(),
517 check_domain_online_handler,
520 /* The above *has* to succeed for winbindd to work. */
521 if (!domain->check_online_event) {
522 smb_panic("set_domain_online_request: failed to add online handler");
526 /****************************************************************
527 Add -ve connection cache entries for domain and realm.
528 ****************************************************************/
530 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
534 add_failed_connection_entry(domain->name, server, result);
535 /* If this was the saf name for the last thing we talked to,
537 saf_delete(domain->name);
538 if (*domain->alt_name) {
539 add_failed_connection_entry(domain->alt_name, server, result);
540 saf_delete(domain->alt_name);
542 winbindd_unset_locator_kdc_env(domain);
545 /* Choose between anonymous or authenticated connections. We need to use
546 an authenticated connection if DCs have the RestrictAnonymous registry
547 entry set > 0, or the "Additional restrictions for anonymous
548 connections" set in the win2k Local Security Policy.
550 Caller to free() result in domain, username, password
553 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
555 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
556 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
557 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
559 if (*username && **username) {
561 if (!*domain || !**domain)
562 *domain = smb_xstrdup(lp_workgroup());
564 if (!*password || !**password)
565 *password = smb_xstrdup("");
567 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
568 *domain, *username));
571 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
572 *username = smb_xstrdup("");
573 *domain = smb_xstrdup("");
574 *password = smb_xstrdup("");
578 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
580 struct sockaddr_storage *dc_ss)
582 struct winbindd_domain *our_domain = NULL;
583 struct rpc_pipe_client *netlogon_pipe = NULL;
587 unsigned int orig_timeout;
588 const char *tmp = NULL;
591 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
598 if (domain->primary) {
602 our_domain = find_our_domain();
604 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
608 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
609 if (!NT_STATUS_IS_OK(result)) {
610 talloc_destroy(mem_ctx);
614 /* This call can take a long time - allow the server to time out.
615 35 seconds should do it. */
617 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
619 if (our_domain->active_directory) {
620 struct netr_DsRGetDCNameInfo *domain_info = NULL;
622 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
631 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
633 mem_ctx, domain_info->dc_unc);
635 DEBUG(0, ("talloc_strdup failed\n"));
636 talloc_destroy(mem_ctx);
639 if (strlen(domain->alt_name) == 0) {
640 fstrcpy(domain->alt_name,
641 domain_info->domain_name);
643 if (strlen(domain->forest_name) == 0) {
644 fstrcpy(domain->forest_name,
645 domain_info->forest_name);
649 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
656 /* And restore our original timeout. */
657 rpccli_set_timeout(netlogon_pipe, orig_timeout);
659 if (!NT_STATUS_IS_OK(result)) {
660 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
662 talloc_destroy(mem_ctx);
666 if (!W_ERROR_IS_OK(werr)) {
667 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
669 talloc_destroy(mem_ctx);
673 /* rpccli_netr_GetAnyDCName gives us a name with \\ */
674 p = strip_hostname(tmp);
678 talloc_destroy(mem_ctx);
680 DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
682 if (!resolve_name(dcname, dc_ss, 0x20)) {
690 * Helper function to assemble trust password and account name
692 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
693 char **machine_password,
694 char **machine_account,
695 char **machine_krb5_principal)
697 const char *account_name;
698 const char *name = NULL;
700 /* If we are a DC and this is not our own domain */
705 struct winbindd_domain *our_domain = find_our_domain();
708 return NT_STATUS_INVALID_SERVER_STATE;
710 name = our_domain->name;
713 if (!get_trust_pw_clear(name, machine_password,
714 &account_name, NULL))
716 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
719 if ((machine_account != NULL) &&
720 (asprintf(machine_account, "%s$", account_name) == -1))
722 return NT_STATUS_NO_MEMORY;
725 /* For now assume our machine account only exists in our domain */
727 if (machine_krb5_principal != NULL)
729 struct winbindd_domain *our_domain = find_our_domain();
732 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
735 if (asprintf(machine_krb5_principal, "%s$@%s",
736 account_name, our_domain->alt_name) == -1)
738 return NT_STATUS_NO_MEMORY;
741 strupper_m(*machine_krb5_principal);
747 /************************************************************************
748 Given a fd with a just-connected TCP connection to a DC, open a connection
750 ************************************************************************/
752 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
754 const char *controller,
755 struct cli_state **cli,
758 char *machine_password = NULL;
759 char *machine_krb5_principal = NULL;
760 char *machine_account = NULL;
761 char *ipc_username = NULL;
762 char *ipc_domain = NULL;
763 char *ipc_password = NULL;
765 struct named_mutex *mutex;
767 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
769 struct sockaddr peeraddr;
770 socklen_t peeraddr_len;
772 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
774 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
775 controller, domain->name ));
779 mutex = grab_named_mutex(talloc_tos(), controller,
780 WINBIND_SERVER_MUTEX_WAIT_TIME);
782 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
784 result = NT_STATUS_POSSIBLE_DEADLOCK;
788 if ((*cli = cli_initialise()) == NULL) {
789 DEBUG(1, ("Could not cli_initialize\n"));
790 result = NT_STATUS_NO_MEMORY;
794 (*cli)->timeout = 10000; /* 10 seconds */
796 fstrcpy((*cli)->desthost, controller);
797 (*cli)->use_kerberos = True;
799 peeraddr_len = sizeof(peeraddr);
801 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
802 (peeraddr_len != sizeof(struct sockaddr_in)) ||
803 (peeraddr_in->sin_family != PF_INET))
805 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
806 result = NT_STATUS_UNSUCCESSFUL;
810 if (ntohs(peeraddr_in->sin_port) == 139) {
811 struct nmb_name calling;
812 struct nmb_name called;
814 make_nmb_name(&calling, global_myname(), 0x0);
815 make_nmb_name(&called, "*SMBSERVER", 0x20);
817 if (!cli_session_request(*cli, &calling, &called)) {
818 DEBUG(8, ("cli_session_request failed for %s\n",
820 result = NT_STATUS_UNSUCCESSFUL;
825 result = cli_negprot(*cli);
827 if (!NT_STATUS_IS_OK(result)) {
828 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
832 if (!is_dc_trusted_domain_situation(domain->name) &&
833 (*cli)->protocol >= PROTOCOL_NT1 &&
834 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
836 ADS_STATUS ads_status;
838 result = get_trust_creds(domain, &machine_password,
840 &machine_krb5_principal);
841 if (!NT_STATUS_IS_OK(result)) {
845 if (lp_security() == SEC_ADS) {
847 /* Try a krb5 session */
849 (*cli)->use_kerberos = True;
850 DEBUG(5, ("connecting to %s from %s with kerberos principal "
851 "[%s] and realm [%s]\n", controller, global_myname(),
852 machine_krb5_principal, domain->alt_name));
854 winbindd_set_locator_kdc_envs(domain);
856 ads_status = cli_session_setup_spnego(*cli,
857 machine_krb5_principal,
862 if (!ADS_ERR_OK(ads_status)) {
863 DEBUG(4,("failed kerberos session setup with %s\n",
864 ads_errstr(ads_status)));
867 result = ads_ntstatus(ads_status);
868 if (NT_STATUS_IS_OK(result)) {
869 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
870 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
871 if (!NT_STATUS_IS_OK(result)) {
874 goto session_setup_done;
878 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
879 (*cli)->use_kerberos = False;
881 DEBUG(5, ("connecting to %s from %s with username "
882 "[%s]\\[%s]\n", controller, global_myname(),
883 lp_workgroup(), machine_account));
885 ads_status = cli_session_setup_spnego(*cli,
890 if (!ADS_ERR_OK(ads_status)) {
891 DEBUG(4, ("authenticated session setup failed with %s\n",
892 ads_errstr(ads_status)));
895 result = ads_ntstatus(ads_status);
896 if (NT_STATUS_IS_OK(result)) {
897 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
898 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
899 if (!NT_STATUS_IS_OK(result)) {
902 goto session_setup_done;
906 /* Fall back to non-kerberos session setup with auth_user */
908 (*cli)->use_kerberos = False;
910 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
912 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
913 (strlen(ipc_username) > 0)) {
915 /* Only try authenticated if we have a username */
917 DEBUG(5, ("connecting to %s from %s with username "
918 "[%s]\\[%s]\n", controller, global_myname(),
919 ipc_domain, ipc_username));
921 if (NT_STATUS_IS_OK(cli_session_setup(
923 ipc_password, strlen(ipc_password)+1,
924 ipc_password, strlen(ipc_password)+1,
926 /* Successful logon with given username. */
927 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
928 if (!NT_STATUS_IS_OK(result)) {
931 goto session_setup_done;
933 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
934 ipc_domain, ipc_username ));
940 /* Fall back to anonymous connection, this might fail later */
941 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
942 "connection for DC %s\n",
945 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
947 DEBUG(5, ("Connected anonymously\n"));
948 result = cli_init_creds(*cli, "", "", "");
949 if (!NT_STATUS_IS_OK(result)) {
952 goto session_setup_done;
955 result = cli_nt_error(*cli);
957 if (NT_STATUS_IS_OK(result))
958 result = NT_STATUS_UNSUCCESSFUL;
960 /* We can't session setup */
966 /* cache the server name for later connections */
968 saf_store( domain->name, (*cli)->desthost );
969 if (domain->alt_name && (*cli)->use_kerberos) {
970 saf_store( domain->alt_name, (*cli)->desthost );
973 winbindd_set_locator_kdc_envs(domain);
975 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
977 if (!NT_STATUS_IS_OK(result)) {
978 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
985 /* set the domain if empty; needed for schannel connections */
986 if ( !(*cli)->domain[0] ) {
987 result = cli_set_domain((*cli), domain->name);
988 if (!NT_STATUS_IS_OK(result)) {
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 = NULL;
1777 struct policy_handle pol;
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_creds(struct winbindd_domain *domain,
1968 struct netlogon_creds_CredentialState **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 netlogon_creds_CredentialState 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, struct policy_handle *sam_handle)
1996 struct winbindd_cm_conn *conn;
1997 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1998 struct netlogon_creds_CredentialState *p_creds;
1999 char *machine_password = NULL;
2000 char *machine_account = NULL;
2001 char *domain_name = NULL;
2003 result = init_dc_connection(domain);
2004 if (!NT_STATUS_IS_OK(result)) {
2008 conn = &domain->conn;
2010 if (conn->samr_pipe != NULL) {
2016 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2017 * sign and sealed pipe using the machine account password by
2018 * preference. If we can't - try schannel, if that fails, try
2022 if ((conn->cli->user_name[0] == '\0') ||
2023 (conn->cli->domain[0] == '\0') ||
2024 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2026 result = get_trust_creds(domain, &machine_password,
2027 &machine_account, NULL);
2028 if (!NT_STATUS_IS_OK(result)) {
2029 DEBUG(10, ("cm_connect_sam: No no user available for "
2030 "domain %s, trying schannel\n", conn->cli->domain));
2033 domain_name = domain->name;
2035 machine_password = SMB_STRDUP(conn->cli->password);
2036 machine_account = SMB_STRDUP(conn->cli->user_name);
2037 domain_name = conn->cli->domain;
2040 if (!machine_password || !machine_account) {
2041 result = NT_STATUS_NO_MEMORY;
2045 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2046 authenticated SAMR pipe with sign & seal. */
2047 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2048 &ndr_table_samr.syntax_id,
2049 PIPE_AUTH_LEVEL_PRIVACY,
2055 if (!NT_STATUS_IS_OK(result)) {
2056 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2057 "pipe for domain %s using NTLMSSP "
2058 "authenticated pipe: user %s\\%s. Error was "
2059 "%s\n", domain->name, domain_name,
2060 machine_account, nt_errstr(result)));
2064 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2065 "domain %s using NTLMSSP authenticated "
2066 "pipe: user %s\\%s\n", domain->name,
2067 domain_name, machine_account));
2069 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2070 conn->samr_pipe->desthost,
2071 SEC_RIGHTS_MAXIMUM_ALLOWED,
2072 &conn->sam_connect_handle);
2073 if (NT_STATUS_IS_OK(result)) {
2076 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2077 "failed for domain %s, error was %s. Trying schannel\n",
2078 domain->name, nt_errstr(result) ));
2079 TALLOC_FREE(conn->samr_pipe);
2083 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2085 if (!cm_get_schannel_creds(domain, &p_creds)) {
2086 /* If this call fails - conn->cli can now be NULL ! */
2087 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2088 "for domain %s, trying anon\n", domain->name));
2091 result = cli_rpc_pipe_open_schannel_with_key
2092 (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
2093 domain->name, &p_creds, &conn->samr_pipe);
2095 if (!NT_STATUS_IS_OK(result)) {
2096 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2097 "domain %s using schannel. Error was %s\n",
2098 domain->name, nt_errstr(result) ));
2101 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2102 "schannel.\n", domain->name ));
2104 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2105 conn->samr_pipe->desthost,
2106 SEC_RIGHTS_MAXIMUM_ALLOWED,
2107 &conn->sam_connect_handle);
2108 if (NT_STATUS_IS_OK(result)) {
2111 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2112 "for domain %s, error was %s. Trying anonymous\n",
2113 domain->name, nt_errstr(result) ));
2114 TALLOC_FREE(conn->samr_pipe);
2118 /* Finally fall back to anonymous. */
2119 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2122 if (!NT_STATUS_IS_OK(result)) {
2126 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2127 conn->samr_pipe->desthost,
2128 SEC_RIGHTS_MAXIMUM_ALLOWED,
2129 &conn->sam_connect_handle);
2130 if (!NT_STATUS_IS_OK(result)) {
2131 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2132 "for domain %s Error was %s\n",
2133 domain->name, nt_errstr(result) ));
2138 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2140 &conn->sam_connect_handle,
2141 SEC_RIGHTS_MAXIMUM_ALLOWED,
2143 &conn->sam_domain_handle);
2147 if (!NT_STATUS_IS_OK(result)) {
2148 invalidate_cm_connection(conn);
2152 *cli = conn->samr_pipe;
2153 *sam_handle = conn->sam_domain_handle;
2154 SAFE_FREE(machine_password);
2155 SAFE_FREE(machine_account);
2159 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2160 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2162 struct winbindd_cm_conn *conn;
2163 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2164 struct netlogon_creds_CredentialState *p_creds;
2166 result = init_dc_connection(domain);
2167 if (!NT_STATUS_IS_OK(result))
2170 conn = &domain->conn;
2172 if (conn->lsa_pipe != NULL) {
2176 if ((conn->cli->user_name[0] == '\0') ||
2177 (conn->cli->domain[0] == '\0') ||
2178 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2179 DEBUG(10, ("cm_connect_lsa: No no user available for "
2180 "domain %s, trying schannel\n", conn->cli->domain));
2184 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2185 * authenticated LSA pipe with sign & seal. */
2186 result = cli_rpc_pipe_open_spnego_ntlmssp
2187 (conn->cli, &ndr_table_lsarpc.syntax_id,
2188 PIPE_AUTH_LEVEL_PRIVACY,
2189 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2192 if (!NT_STATUS_IS_OK(result)) {
2193 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2194 "domain %s using NTLMSSP authenticated pipe: user "
2195 "%s\\%s. Error was %s. Trying schannel.\n",
2196 domain->name, conn->cli->domain,
2197 conn->cli->user_name, nt_errstr(result)));
2201 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2202 "NTLMSSP authenticated pipe: user %s\\%s\n",
2203 domain->name, conn->cli->domain, conn->cli->user_name ));
2205 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2206 SEC_RIGHTS_MAXIMUM_ALLOWED,
2208 if (NT_STATUS_IS_OK(result)) {
2212 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2215 TALLOC_FREE(conn->lsa_pipe);
2219 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2221 if (!cm_get_schannel_creds(domain, &p_creds)) {
2222 /* If this call fails - conn->cli can now be NULL ! */
2223 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2224 "for domain %s, trying anon\n", domain->name));
2227 result = cli_rpc_pipe_open_schannel_with_key
2228 (conn->cli, &ndr_table_lsarpc.syntax_id,
2229 PIPE_AUTH_LEVEL_PRIVACY,
2230 domain->name, p_creds, &conn->lsa_pipe);
2232 if (!NT_STATUS_IS_OK(result)) {
2233 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2234 "domain %s using schannel. Error was %s\n",
2235 domain->name, nt_errstr(result) ));
2238 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2239 "schannel.\n", domain->name ));
2241 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2242 SEC_RIGHTS_MAXIMUM_ALLOWED,
2244 if (NT_STATUS_IS_OK(result)) {
2248 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2251 TALLOC_FREE(conn->lsa_pipe);
2255 result = cli_rpc_pipe_open_noauth(conn->cli,
2256 &ndr_table_lsarpc.syntax_id,
2258 if (!NT_STATUS_IS_OK(result)) {
2259 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2263 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2264 SEC_RIGHTS_MAXIMUM_ALLOWED,
2267 if (!NT_STATUS_IS_OK(result)) {
2268 invalidate_cm_connection(conn);
2272 *cli = conn->lsa_pipe;
2273 *lsa_policy = conn->lsa_policy;
2277 /****************************************************************************
2278 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2279 session key stored in conn->netlogon_pipe->dc->sess_key.
2280 ****************************************************************************/
2282 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2283 struct rpc_pipe_client **cli)
2285 struct winbindd_cm_conn *conn;
2288 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2290 uint32 sec_chan_type;
2291 const char *account_name;
2292 struct rpc_pipe_client *netlogon_pipe = NULL;
2296 result = init_dc_connection(domain);
2297 if (!NT_STATUS_IS_OK(result)) {
2301 conn = &domain->conn;
2303 if (conn->netlogon_pipe != NULL) {
2304 *cli = conn->netlogon_pipe;
2305 return NT_STATUS_OK;
2308 result = cli_rpc_pipe_open_noauth(conn->cli,
2309 &ndr_table_netlogon.syntax_id,
2311 if (!NT_STATUS_IS_OK(result)) {
2315 if ((!IS_DC) && (!domain->primary)) {
2316 /* Clear the schannel request bit and drop down */
2317 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2321 if (lp_client_schannel() != False) {
2322 neg_flags |= NETLOGON_NEG_SCHANNEL;
2325 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2328 TALLOC_FREE(netlogon_pipe);
2329 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2332 result = rpccli_netlogon_setup_creds(
2334 domain->dcname, /* server name. */
2335 domain->name, /* domain name */
2336 global_myname(), /* client name */
2337 account_name, /* machine account */
2338 mach_pwd, /* machine password */
2339 sec_chan_type, /* from get_trust_pw */
2342 if (!NT_STATUS_IS_OK(result)) {
2343 TALLOC_FREE(netlogon_pipe);
2347 if ((lp_client_schannel() == True) &&
2348 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2349 DEBUG(3, ("Server did not offer schannel\n"));
2350 TALLOC_FREE(netlogon_pipe);
2351 return NT_STATUS_ACCESS_DENIED;
2355 if ((lp_client_schannel() == False) ||
2356 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2358 * NetSamLogonEx only works for schannel
2360 domain->can_do_samlogon_ex = False;
2362 /* We're done - just keep the existing connection to NETLOGON
2364 conn->netlogon_pipe = netlogon_pipe;
2365 *cli = conn->netlogon_pipe;
2366 return NT_STATUS_OK;
2369 /* Using the credentials from the first pipe, open a signed and sealed
2370 second netlogon pipe. The session key is stored in the schannel
2371 part of the new pipe auth struct.
2374 result = cli_rpc_pipe_open_schannel_with_key(
2375 conn->cli, &ndr_table_netlogon.syntax_id,
2376 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2377 &conn->netlogon_pipe);
2379 /* We can now close the initial netlogon pipe. */
2380 TALLOC_FREE(netlogon_pipe);
2382 if (!NT_STATUS_IS_OK(result)) {
2383 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2384 "was %s\n", nt_errstr(result)));
2386 /* make sure we return something besides OK */
2387 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2391 * Try NetSamLogonEx for AD domains
2393 domain->can_do_samlogon_ex = domain->active_directory;
2395 *cli = conn->netlogon_pipe;
2396 return NT_STATUS_OK;