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"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "libsmb/libsmb.h"
73 #include "libsmb/clidgram.h"
76 #include "../libcli/security/security.h"
79 #include "auth/gensec/gensec.h"
80 #include "../libcli/smb/smbXcli_base.h"
81 #include "libcli/auth/netlogon_creds_cli.h"
83 #include "rpc_server/rpc_ncacn_np.h"
84 #include "auth/credentials/credentials.h"
85 #include "lib/param/param.h"
88 #define DBGC_CLASS DBGC_WINBIND
92 struct sockaddr_storage ss;
95 extern struct winbindd_methods reconnect_methods;
96 extern bool override_logfile;
98 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
99 static void set_dc_type_and_flags( struct winbindd_domain *domain );
100 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
101 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
102 struct dc_name_ip **dcs, int *num_dcs,
103 uint32_t request_flags);
105 /****************************************************************
106 Child failed to find DC's. Reschedule check.
107 ****************************************************************/
109 static void msg_failed_to_go_online(struct messaging_context *msg,
112 struct server_id server_id,
115 struct winbindd_domain *domain;
116 const char *domainname = (const char *)data->data;
118 if (data->data == NULL || data->length == 0) {
122 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
124 for (domain = domain_list(); domain; domain = domain->next) {
125 if (domain->internal) {
129 if (strequal(domain->name, domainname)) {
130 if (domain->online) {
131 /* We're already online, ignore. */
132 DEBUG(5,("msg_fail_to_go_online: domain %s "
133 "already online.\n", domainname));
137 /* Reschedule the online check. */
138 set_domain_offline(domain);
144 /****************************************************************
145 Actually cause a reconnect from a message.
146 ****************************************************************/
148 static void msg_try_to_go_online(struct messaging_context *msg,
151 struct server_id server_id,
154 struct winbindd_domain *domain;
155 const char *domainname = (const char *)data->data;
157 if (data->data == NULL || data->length == 0) {
161 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
163 for (domain = domain_list(); domain; domain = domain->next) {
164 if (domain->internal) {
168 if (strequal(domain->name, domainname)) {
170 if (domain->online) {
171 /* We're already online, ignore. */
172 DEBUG(5,("msg_try_to_go_online: domain %s "
173 "already online.\n", domainname));
177 /* This call takes care of setting the online
178 flag to true if we connected, or re-adding
179 the offline handler if false. Bypasses online
180 check so always does network calls. */
182 init_dc_connection_network(domain, true);
188 /****************************************************************
189 Fork a child to try and contact a DC. Do this as contacting a
190 DC requires blocking lookups and we don't want to block our
192 ****************************************************************/
194 static bool fork_child_dc_connect(struct winbindd_domain *domain)
196 struct dc_name_ip *dcs = NULL;
198 TALLOC_CTX *mem_ctx = NULL;
199 pid_t parent_pid = getpid();
203 if (domain->dc_probe_pid != (pid_t)-1) {
205 * We might already have a DC probe
206 * child working, check.
208 if (process_exists_by_pid(domain->dc_probe_pid)) {
209 DEBUG(10,("fork_child_dc_connect: pid %u already "
210 "checking for DC's.\n",
211 (unsigned int)domain->dc_probe_pid));
214 domain->dc_probe_pid = (pid_t)-1;
217 domain->dc_probe_pid = fork();
219 if (domain->dc_probe_pid == (pid_t)-1) {
220 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
224 if (domain->dc_probe_pid != (pid_t)0) {
226 messaging_register(server_messaging_context(), NULL,
227 MSG_WINBIND_TRY_TO_GO_ONLINE,
228 msg_try_to_go_online);
229 messaging_register(server_messaging_context(), NULL,
230 MSG_WINBIND_FAILED_TO_GO_ONLINE,
231 msg_failed_to_go_online);
237 /* Leave messages blocked - we will never process one. */
239 if (!override_logfile) {
240 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
241 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
246 status = winbindd_reinit_after_fork(NULL, lfile);
247 if (!NT_STATUS_IS_OK(status)) {
248 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
250 messaging_send_buf(server_messaging_context(),
251 pid_to_procid(parent_pid),
252 MSG_WINBIND_FAILED_TO_GO_ONLINE,
253 (const uint8_t *)domain->name,
254 strlen(domain->name)+1);
259 setproctitle("dc-connect child");
261 mem_ctx = talloc_init("fork_child_dc_connect");
263 DEBUG(0,("talloc_init failed.\n"));
264 messaging_send_buf(server_messaging_context(),
265 pid_to_procid(parent_pid),
266 MSG_WINBIND_FAILED_TO_GO_ONLINE,
267 (const uint8_t *)domain->name,
268 strlen(domain->name)+1);
272 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs, 0)) || (num_dcs == 0)) {
273 /* Still offline ? Can't find DC's. */
274 messaging_send_buf(server_messaging_context(),
275 pid_to_procid(parent_pid),
276 MSG_WINBIND_FAILED_TO_GO_ONLINE,
277 (const uint8_t *)domain->name,
278 strlen(domain->name)+1);
282 /* We got a DC. Send a message to our parent to get it to
283 try and do the same. */
285 messaging_send_buf(server_messaging_context(),
286 pid_to_procid(parent_pid),
287 MSG_WINBIND_TRY_TO_GO_ONLINE,
288 (const uint8_t *)domain->name,
289 strlen(domain->name)+1);
293 /****************************************************************
294 Handler triggered if we're offline to try and detect a DC.
295 ****************************************************************/
297 static void check_domain_online_handler(struct tevent_context *ctx,
298 struct tevent_timer *te,
302 struct winbindd_domain *domain =
303 (struct winbindd_domain *)private_data;
305 DEBUG(10,("check_domain_online_handler: called for domain "
306 "%s (online = %s)\n", domain->name,
307 domain->online ? "True" : "False" ));
309 TALLOC_FREE(domain->check_online_event);
311 /* Are we still in "startup" mode ? */
313 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
314 /* No longer in "startup" mode. */
315 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
317 domain->startup = False;
320 /* We've been told to stay offline, so stay
323 if (get_global_winbindd_state_offline()) {
324 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
329 /* Fork a child to test if it can contact a DC.
330 If it can then send ourselves a message to
331 cause a reconnect. */
333 fork_child_dc_connect(domain);
336 /****************************************************************
337 If we're still offline setup the timeout check.
338 ****************************************************************/
340 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
342 int wbr = lp_winbind_reconnect_delay();
344 if (domain->startup) {
345 domain->check_online_timeout = 10;
346 } else if (domain->check_online_timeout < wbr) {
347 domain->check_online_timeout = wbr;
351 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
354 struct server_id server_id,
357 const char *domain_name = (const char *)data->data;
358 struct winbindd_domain *domain;
360 domain = find_domain_from_name_noinit(domain_name);
361 if (domain == NULL) {
365 domain->online = false;
367 DEBUG(10, ("Domain %s is marked as offline now.\n",
371 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
374 struct server_id server_id,
377 const char *domain_name = (const char *)data->data;
378 struct winbindd_domain *domain;
380 domain = find_domain_from_name_noinit(domain_name);
381 if (domain == NULL) {
385 domain->online = true;
387 DEBUG(10, ("Domain %s is marked as online now.\n",
391 /****************************************************************
392 Set domain offline and also add handler to put us back online
394 ****************************************************************/
396 void set_domain_offline(struct winbindd_domain *domain)
398 pid_t parent_pid = getppid();
400 DEBUG(10,("set_domain_offline: called for domain %s\n",
403 TALLOC_FREE(domain->check_online_event);
405 if (domain->internal) {
406 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
411 domain->online = False;
413 /* Offline domains are always initialized. They're
414 re-initialized when they go back online. */
416 domain->initialized = True;
418 /* We only add the timeout handler that checks and
419 allows us to go back online when we've not
420 been told to remain offline. */
422 if (get_global_winbindd_state_offline()) {
423 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
428 /* If we're in startup mode, check again in 10 seconds, not in
429 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
431 calc_new_online_timeout_check(domain);
433 domain->check_online_event = tevent_add_timer(server_event_context(),
435 timeval_current_ofs(domain->check_online_timeout,0),
436 check_domain_online_handler,
439 /* The above *has* to succeed for winbindd to work. */
440 if (!domain->check_online_event) {
441 smb_panic("set_domain_offline: failed to add online handler");
444 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
447 /* Send a message to the parent that the domain is offline. */
448 if (parent_pid > 1 && !domain->internal) {
449 messaging_send_buf(server_messaging_context(),
450 pid_to_procid(parent_pid),
451 MSG_WINBIND_DOMAIN_OFFLINE,
452 (uint8_t *)domain->name,
453 strlen(domain->name) + 1);
456 /* Send an offline message to the idmap child when our
457 primary domain goes offline */
459 if ( domain->primary ) {
460 struct winbindd_child *idmap = idmap_child();
462 if ( idmap->pid != 0 ) {
463 messaging_send_buf(server_messaging_context(),
464 pid_to_procid(idmap->pid),
466 (const uint8_t *)domain->name,
467 strlen(domain->name)+1);
474 /****************************************************************
475 Set domain online - if allowed.
476 ****************************************************************/
478 static void set_domain_online(struct winbindd_domain *domain)
480 pid_t parent_pid = getppid();
482 DEBUG(10,("set_domain_online: called for domain %s\n",
485 if (domain->internal) {
486 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
491 if (get_global_winbindd_state_offline()) {
492 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
497 winbindd_set_locator_kdc_envs(domain);
499 /* If we are waiting to get a krb5 ticket, trigger immediately. */
500 ccache_regain_all_now();
502 /* Ok, we're out of any startup mode now... */
503 domain->startup = False;
505 if (domain->online == False) {
506 /* We were offline - now we're online. We default to
507 using the MS-RPC backend if we started offline,
508 and if we're going online for the first time we
509 should really re-initialize the backends and the
510 checks to see if we're talking to an AD or NT domain.
513 domain->initialized = False;
515 /* 'reconnect_methods' is the MS-RPC backend. */
516 if (domain->backend == &reconnect_methods) {
517 domain->backend = NULL;
521 /* Ensure we have no online timeout checks. */
522 domain->check_online_timeout = 0;
523 TALLOC_FREE(domain->check_online_event);
525 /* Ensure we ignore any pending child messages. */
526 messaging_deregister(server_messaging_context(),
527 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
528 messaging_deregister(server_messaging_context(),
529 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
531 domain->online = True;
533 /* Send a message to the parent that the domain is online. */
534 if (parent_pid > 1 && !domain->internal) {
535 messaging_send_buf(server_messaging_context(),
536 pid_to_procid(parent_pid),
537 MSG_WINBIND_DOMAIN_ONLINE,
538 (uint8_t *)domain->name,
539 strlen(domain->name) + 1);
542 /* Send an online message to the idmap child when our
543 primary domain comes online */
545 if ( domain->primary ) {
546 struct winbindd_child *idmap = idmap_child();
548 if ( idmap->pid != 0 ) {
549 messaging_send_buf(server_messaging_context(),
550 pid_to_procid(idmap->pid),
552 (const uint8_t *)domain->name,
553 strlen(domain->name)+1);
560 /****************************************************************
561 Requested to set a domain online.
562 ****************************************************************/
564 void set_domain_online_request(struct winbindd_domain *domain)
568 DEBUG(10,("set_domain_online_request: called for domain %s\n",
571 if (get_global_winbindd_state_offline()) {
572 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
577 if (domain->internal) {
578 DEBUG(10, ("set_domain_online_request: Internal domains are "
583 /* We've been told it's safe to go online and
584 try and connect to a DC. But I don't believe it
585 because network manager seems to lie.
586 Wait at least 5 seconds. Heuristics suck... */
591 /* Go into "startup" mode again. */
592 domain->startup_time = time_mono(NULL);
593 domain->startup = True;
597 if (!domain->check_online_event) {
598 /* If we've come from being globally offline we
599 don't have a check online event handler set.
600 We need to add one now we're trying to go
603 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
607 TALLOC_FREE(domain->check_online_event);
609 domain->check_online_event = tevent_add_timer(server_event_context(),
612 check_domain_online_handler,
615 /* The above *has* to succeed for winbindd to work. */
616 if (!domain->check_online_event) {
617 smb_panic("set_domain_online_request: failed to add online handler");
621 /****************************************************************
622 Add -ve connection cache entries for domain and realm.
623 ****************************************************************/
625 static void winbind_add_failed_connection_entry(
626 const struct winbindd_domain *domain,
630 add_failed_connection_entry(domain->name, server, result);
631 /* If this was the saf name for the last thing we talked to,
633 saf_delete(domain->name);
634 if (domain->alt_name != NULL) {
635 add_failed_connection_entry(domain->alt_name, server, result);
636 saf_delete(domain->alt_name);
638 winbindd_unset_locator_kdc_env(domain);
641 /* Choose between anonymous or authenticated connections. We need to use
642 an authenticated connection if DCs have the RestrictAnonymous registry
643 entry set > 0, or the "Additional restrictions for anonymous
644 connections" set in the win2k Local Security Policy.
646 Caller to free() result in domain, username, password
649 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
651 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
652 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
653 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
655 if (*username && **username) {
657 if (!*domain || !**domain)
658 *domain = smb_xstrdup(lp_workgroup());
660 if (!*password || !**password)
661 *password = smb_xstrdup("");
663 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
664 *domain, *username));
667 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
668 *username = smb_xstrdup("");
669 *domain = smb_xstrdup("");
670 *password = smb_xstrdup("");
674 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
675 struct cli_credentials **_creds)
678 TALLOC_CTX *frame = talloc_stackframe();
679 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
680 struct loadparm_context *lp_ctx;
681 char *username = NULL;
682 char *netbios_domain = NULL;
683 char *password = NULL;
684 struct cli_credentials *creds = NULL;
687 cm_get_ipc_userpass(&username, &netbios_domain, &password);
689 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
690 if (lp_ctx == NULL) {
691 DEBUG(1, ("loadparm_init_s3 failed\n"));
692 status = NT_STATUS_INTERNAL_ERROR;
696 creds = cli_credentials_init(mem_ctx);
698 status = NT_STATUS_NO_MEMORY;
702 cli_credentials_set_conf(creds, lp_ctx);
703 cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
705 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
707 status = NT_STATUS_NO_MEMORY;
711 ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
713 status = NT_STATUS_NO_MEMORY;
717 ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
719 status = NT_STATUS_NO_MEMORY;
725 status = NT_STATUS_OK;
729 SAFE_FREE(netbios_domain);
735 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
737 TALLOC_CTX *frame = talloc_stackframe();
738 char *ipc_account = NULL;
739 char *ipc_domain = NULL;
740 char *ipc_password = NULL;
741 const char *creds_account = NULL;
742 const char *creds_domain = NULL;
743 const char *creds_password = NULL;
746 cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
748 creds_account = cli_credentials_get_username(creds);
749 creds_domain = cli_credentials_get_domain(creds);
750 creds_password = cli_credentials_get_password(creds);
752 if (!strequal(ipc_domain, creds_domain)) {
756 if (!strequal(ipc_account, creds_account)) {
760 if (!strcsequal(ipc_password, creds_password)) {
766 SAFE_FREE(ipc_account);
767 SAFE_FREE(ipc_domain);
768 SAFE_FREE(ipc_password);
773 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
775 struct sockaddr_storage *dc_ss,
776 uint32_t request_flags)
778 struct winbindd_domain *our_domain = NULL;
779 struct rpc_pipe_client *netlogon_pipe = NULL;
783 unsigned int orig_timeout;
784 const char *tmp = NULL;
786 struct dcerpc_binding_handle *b;
788 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
795 if (domain->primary) {
799 our_domain = find_our_domain();
801 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
805 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
806 if (!NT_STATUS_IS_OK(result)) {
807 talloc_destroy(mem_ctx);
811 b = netlogon_pipe->binding_handle;
813 /* This call can take a long time - allow the server to time out.
814 35 seconds should do it. */
816 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
818 if (our_domain->active_directory) {
819 struct netr_DsRGetDCNameInfo *domain_info = NULL;
822 * TODO request flags are not respected in the server
823 * (and in some cases, like REQUIRE_PDC, causes an error)
825 result = dcerpc_netr_DsRGetDCName(b,
831 request_flags|DS_RETURN_DNS_NAME,
834 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
836 mem_ctx, domain_info->dc_unc);
838 DEBUG(0, ("talloc_strdup failed\n"));
839 talloc_destroy(mem_ctx);
842 if (domain->alt_name == NULL) {
843 domain->alt_name = talloc_strdup(domain,
844 domain_info->domain_name);
845 if (domain->alt_name == NULL) {
846 DEBUG(0, ("talloc_strdup failed\n"));
847 talloc_destroy(mem_ctx);
851 if (domain->forest_name == NULL) {
852 domain->forest_name = talloc_strdup(domain,
853 domain_info->forest_name);
854 if (domain->forest_name == NULL) {
855 DEBUG(0, ("talloc_strdup failed\n"));
856 talloc_destroy(mem_ctx);
862 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
869 /* And restore our original timeout. */
870 rpccli_set_timeout(netlogon_pipe, orig_timeout);
872 if (!NT_STATUS_IS_OK(result)) {
873 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
875 talloc_destroy(mem_ctx);
879 if (!W_ERROR_IS_OK(werr)) {
880 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
882 talloc_destroy(mem_ctx);
886 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
887 p = strip_hostname(tmp);
891 talloc_destroy(mem_ctx);
893 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
895 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
903 * Helper function to assemble trust password and account name
905 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
908 struct cli_credentials **_creds)
910 const struct winbindd_domain *creds_domain = NULL;
911 struct cli_credentials *creds;
913 bool force_machine_account = false;
915 /* If we are a DC and this is not our own domain */
917 if (!domain->active_directory) {
920 * For non active directory domains
921 * we can only use NTLMSSP for SMB.
923 * But the trust account is not allowed
924 * to use SMB with NTLMSSP.
926 force_machine_account = true;
930 if (IS_DC && !force_machine_account) {
931 creds_domain = domain;
933 creds_domain = find_our_domain();
934 if (creds_domain == NULL) {
935 return NT_STATUS_INVALID_SERVER_STATE;
939 status = pdb_get_trust_credentials(creds_domain->name,
940 creds_domain->alt_name,
943 if (!NT_STATUS_IS_OK(status)) {
947 if (creds_domain != domain) {
949 * We can only use schannel against a direct trust
951 cli_credentials_set_secure_channel_type(creds,
960 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
963 status = cm_get_ipc_credentials(mem_ctx, &creds);
964 if (!NT_STATUS_IS_OK(status)) {
972 /************************************************************************
973 Given a fd with a just-connected TCP connection to a DC, open a connection
975 ************************************************************************/
977 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
979 const char *controller,
980 struct cli_state **cli,
983 bool try_ipc_auth = false;
984 const char *machine_principal = NULL;
985 const char *machine_realm = NULL;
986 const char *machine_account = NULL;
987 const char *machine_domain = NULL;
989 struct cli_credentials *creds = NULL;
991 struct named_mutex *mutex;
993 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
995 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
997 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
999 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
1001 * If we are connecting to our own AD domain, require
1002 * smb signing to disrupt MITM attacks
1004 if (domain->primary && lp_security() == SEC_ADS) {
1005 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1007 * If we are in or are an AD domain and connecting to another
1008 * AD domain in our forest
1009 * then require smb signing to disrupt MITM attacks
1011 } else if ((lp_security() == SEC_ADS ||
1012 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)
1013 && domain->active_directory
1014 && (domain->domain_trust_attribs
1015 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
1016 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1020 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1021 controller, domain->name ));
1025 mutex = grab_named_mutex(talloc_tos(), controller,
1026 WINBIND_SERVER_MUTEX_WAIT_TIME);
1027 if (mutex == NULL) {
1029 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1031 result = NT_STATUS_POSSIBLE_DEADLOCK;
1035 *cli = cli_state_create(NULL, sockfd, controller,
1036 smb_sign_client_connections, flags);
1039 DEBUG(1, ("Could not cli_initialize\n"));
1040 result = NT_STATUS_NO_MEMORY;
1044 cli_set_timeout(*cli, 10000); /* 10 seconds */
1046 set_socket_options(sockfd, lp_socket_options());
1048 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
1049 lp_client_ipc_min_protocol(),
1050 lp_client_ipc_max_protocol());
1052 if (!NT_STATUS_IS_OK(result)) {
1053 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
1057 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
1058 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
1059 try_ipc_auth = true;
1060 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1061 try_ipc_auth = true;
1062 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1064 * If we are forcing on SMB signing, then we must
1065 * require authentication unless this is a one-way
1066 * trust, and we have no stored user/password
1068 try_ipc_auth = true;
1072 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
1073 if (!NT_STATUS_IS_OK(result)) {
1074 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1075 domain->name, nt_errstr(result)));
1080 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1081 * would try and authentication with our machine
1082 * account password and fail. This is very rare in
1083 * the modern world however
1085 creds = cli_credentials_init_anon(talloc_tos());
1086 if (creds == NULL) {
1087 result = NT_STATUS_NO_MEMORY;
1088 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1089 domain->name, nt_errstr(result)));
1094 machine_principal = cli_credentials_get_principal(creds,
1096 machine_realm = cli_credentials_get_realm(creds);
1097 machine_account = cli_credentials_get_username(creds);
1098 machine_domain = cli_credentials_get_domain(creds);
1100 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1101 "[%s] and realm [%s]\n",
1102 controller, domain->name, domain->alt_name,
1103 machine_domain, machine_account,
1104 machine_principal, machine_realm));
1106 if (cli_credentials_is_anonymous(creds)) {
1110 winbindd_set_locator_kdc_envs(domain);
1112 result = cli_session_setup_creds(*cli, creds);
1113 if (NT_STATUS_IS_OK(result)) {
1114 goto session_setup_done;
1117 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1119 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1120 nt_errstr(result)));
1123 * If we are not going to validiate the conneciton
1124 * with SMB signing, then allow us to fall back to
1127 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1128 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1129 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1130 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1131 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1133 if (!cm_is_ipc_credentials(creds)) {
1137 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1148 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1149 if (!NT_STATUS_IS_OK(tmp_status)) {
1150 result = tmp_status;
1154 if (cli_credentials_is_anonymous(creds)) {
1158 machine_account = cli_credentials_get_username(creds);
1159 machine_domain = cli_credentials_get_domain(creds);
1161 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1162 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1163 machine_domain, machine_account));
1165 result = cli_session_setup_creds(*cli, creds);
1166 if (NT_STATUS_IS_OK(result)) {
1167 goto session_setup_done;
1170 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1172 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1173 nt_errstr(result)));
1176 * If we are not going to validiate the conneciton
1177 * with SMB signing, then allow us to fall back to
1180 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1181 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1182 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1183 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1184 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1194 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1198 /* Fall back to anonymous connection, this might fail later */
1199 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1200 "connection for DC %s\n",
1203 result = cli_session_setup_anon(*cli);
1204 if (NT_STATUS_IS_OK(result)) {
1205 DEBUG(5, ("Connected anonymously\n"));
1206 goto session_setup_done;
1209 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1210 controller, nt_errstr(result)));
1212 /* We can't session setup */
1219 * This should be a short term hack until
1220 * dynamic re-authentication is implemented.
1222 * See Bug 9175 - winbindd doesn't recover from
1223 * NT_STATUS_NETWORK_SESSION_EXPIRED
1225 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1226 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1229 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1230 if (!NT_STATUS_IS_OK(result)) {
1231 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1234 tcon_status = result;
1236 /* cache the server name for later connections */
1238 saf_store(domain->name, controller);
1239 if (domain->alt_name) {
1240 saf_store(domain->alt_name, controller);
1243 winbindd_set_locator_kdc_envs(domain);
1248 result = NT_STATUS_OK;
1254 if (NT_STATUS_IS_OK(result)) {
1255 result = tcon_status;
1258 if (!NT_STATUS_IS_OK(result)) {
1259 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1260 controller, nt_errstr(result)));
1261 winbind_add_failed_connection_entry(domain, controller, result);
1262 if ((*cli) != NULL) {
1271 /*******************************************************************
1272 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1275 Keeps the list unique by not adding duplicate entries.
1277 @param[in] mem_ctx talloc memory context to allocate from
1278 @param[in] domain_name domain of the DC
1279 @param[in] dcname name of the DC to add to the list
1280 @param[in] pss Internet address and port pair to add to the list
1281 @param[in,out] dcs array of dc_name_ip structures to add to
1282 @param[in,out] num_dcs number of dcs returned in the dcs array
1283 @return true if the list was added to, false otherwise
1284 *******************************************************************/
1286 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1287 const char *dcname, struct sockaddr_storage *pss,
1288 struct dc_name_ip **dcs, int *num)
1292 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1293 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1297 /* Make sure there's no duplicates in the list */
1298 for (i=0; i<*num; i++)
1300 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1301 (struct sockaddr *)(void *)pss))
1304 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1309 fstrcpy((*dcs)[*num].name, dcname);
1310 (*dcs)[*num].ss = *pss;
1315 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1316 struct sockaddr_storage *pss, uint16_t port,
1317 struct sockaddr_storage **addrs, int *num)
1319 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1321 if (*addrs == NULL) {
1326 (*addrs)[*num] = *pss;
1327 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1333 /*******************************************************************
1334 convert an ip to a name
1335 For an AD Domain, it checks the requirements of the request flags.
1336 *******************************************************************/
1338 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1339 const struct winbindd_domain *domain,
1340 struct sockaddr_storage *pss,
1341 char **name, uint32_t request_flags)
1343 struct ip_service ip_list;
1344 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1346 const char *dc_name;
1349 bool is_ad_domain = false;
1355 /* For active directory servers, try to get the ldap server name.
1356 None of these failures should be considered critical for now */
1358 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1359 is_ad_domain = true;
1360 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1361 is_ad_domain = domain->active_directory;
1366 ADS_STATUS ads_status;
1367 char addr[INET6_ADDRSTRLEN];
1369 print_sockaddr(addr, sizeof(addr), pss);
1371 ads = ads_init(domain->alt_name, domain->name, addr);
1372 ads->auth.flags |= ADS_AUTH_NO_BIND;
1373 ads->config.flags |= request_flags;
1374 ads->server.no_fallback = true;
1376 ads_status = ads_connect(ads);
1377 if (ADS_ERR_OK(ads_status)) {
1378 /* We got a cldap packet. */
1379 *name = talloc_strdup(mem_ctx,
1380 ads->config.ldap_server_name);
1381 if (*name == NULL) {
1384 namecache_store(*name, 0x20, 1, &ip_list);
1386 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1388 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1389 if (ads_closest_dc(ads)) {
1390 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1392 /* We're going to use this KDC for this realm/domain.
1393 If we are using sites, then force the krb5 libs
1396 create_local_private_krb5_conf_for_domain(domain->alt_name,
1401 TALLOC_FREE(sitename);
1403 /* use an off site KDC */
1404 create_local_private_krb5_conf_for_domain(domain->alt_name,
1409 winbindd_set_locator_kdc_envs(domain);
1411 /* Ensure we contact this DC also. */
1412 saf_store(domain->name, *name);
1413 saf_store(domain->alt_name, *name);
1416 ads_destroy( &ads );
1420 ads_destroy( &ads );
1425 status = nbt_getdc(server_messaging_context(), 10, pss, domain->name,
1426 &domain->sid, nt_version, mem_ctx, &nt_version,
1428 if (NT_STATUS_IS_OK(status)) {
1429 *name = talloc_strdup(mem_ctx, dc_name);
1430 if (*name == NULL) {
1433 namecache_store(*name, 0x20, 1, &ip_list);
1437 /* try node status request */
1439 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1440 namecache_store(nbtname, 0x20, 1, &ip_list);
1443 *name = talloc_strdup(mem_ctx, nbtname);
1444 if (*name == NULL) {
1454 /*******************************************************************
1455 Retrieve a list of IP addresses for domain controllers.
1457 The array is sorted in the preferred connection order.
1459 @param[in] mem_ctx talloc memory context to allocate from
1460 @param[in] domain domain to retrieve DCs for
1461 @param[out] dcs array of dcs that will be returned
1462 @param[out] num_dcs number of dcs returned in the dcs array
1464 *******************************************************************/
1466 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1467 struct dc_name_ip **dcs, int *num_dcs,
1468 uint32_t request_flags)
1471 struct sockaddr_storage ss;
1472 struct ip_service *ip_list = NULL;
1473 int iplist_size = 0;
1476 enum security_types sec = (enum security_types)lp_security();
1478 is_our_domain = strequal(domain->name, lp_workgroup());
1480 /* If not our domain, get the preferred DC, by asking our primary DC */
1482 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1483 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1486 char addr[INET6_ADDRSTRLEN];
1487 print_sockaddr(addr, sizeof(addr), &ss);
1488 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1493 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1494 char *sitename = NULL;
1496 /* We need to make sure we know the local site before
1497 doing any DNS queries, as this will restrict the
1498 get_sorted_dc_list() call below to only fetching
1499 DNS records for the correct site. */
1501 /* Find any DC to get the site record.
1502 We deliberately don't care about the
1505 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1507 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1510 /* Do the site-specific AD dns lookup first. */
1511 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1512 &iplist_size, True);
1514 /* Add ips to the DC array. We don't look up the name
1515 of the DC in this function, but we fill in the char*
1516 of the ip now to make the failed connection cache
1518 for ( i=0; i<iplist_size; i++ ) {
1519 char addr[INET6_ADDRSTRLEN];
1520 print_sockaddr(addr, sizeof(addr),
1522 add_one_dc_unique(mem_ctx,
1531 TALLOC_FREE(sitename);
1535 /* Now we add DCs from the main AD DNS lookup. */
1536 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1537 &iplist_size, True);
1539 for ( i=0; i<iplist_size; i++ ) {
1540 char addr[INET6_ADDRSTRLEN];
1541 print_sockaddr(addr, sizeof(addr),
1543 add_one_dc_unique(mem_ctx,
1555 /* Try standard netbios queries if no ADS and fall back to DNS queries
1556 * if alt_name is available */
1557 if (*num_dcs == 0) {
1558 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1560 if (iplist_size == 0) {
1561 if (domain->alt_name != NULL) {
1562 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1563 &iplist_size, true);
1567 for ( i=0; i<iplist_size; i++ ) {
1568 char addr[INET6_ADDRSTRLEN];
1569 print_sockaddr(addr, sizeof(addr),
1571 add_one_dc_unique(mem_ctx,
1586 /*******************************************************************
1587 Find and make a connection to a DC in the given domain.
1589 @param[in] mem_ctx talloc memory context to allocate from
1590 @param[in] domain domain to find a dc in
1591 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1592 @param[out] pss DC Internet address and port
1593 @param[out] fd fd of the open socket connected to the newly found dc
1594 @return true when a DC connection is made, false otherwise
1595 *******************************************************************/
1597 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1598 struct winbindd_domain *domain,
1599 char **dcname, struct sockaddr_storage *pss, int *fd,
1600 uint32_t request_flags)
1602 struct dc_name_ip *dcs = NULL;
1605 const char **dcnames = NULL;
1606 size_t num_dcnames = 0;
1608 struct sockaddr_storage *addrs = NULL;
1619 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1622 for (i=0; i<num_dcs; i++) {
1624 if (!add_string_to_array(mem_ctx, dcs[i].name,
1625 &dcnames, &num_dcnames)) {
1628 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1629 &addrs, &num_addrs)) {
1634 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1637 if ((addrs == NULL) || (dcnames == NULL))
1640 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1641 num_addrs, 0, 10, fd, &fd_index, NULL);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 for (i=0; i<num_dcs; i++) {
1644 char ab[INET6_ADDRSTRLEN];
1645 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1646 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1647 "domain %s address %s. Error was %s\n",
1648 domain->name, ab, nt_errstr(status) ));
1649 winbind_add_failed_connection_entry(domain,
1650 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1655 *pss = addrs[fd_index];
1657 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1658 /* Ok, we've got a name for the DC */
1659 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1660 if (*dcname == NULL) {
1666 /* Try to figure out the name */
1667 if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1671 /* We can not continue without the DC's name */
1672 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1673 NT_STATUS_UNSUCCESSFUL);
1675 /* Throw away all arrays as we're doing this again. */
1679 TALLOC_FREE(dcnames);
1691 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1693 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1697 static void store_current_dc_in_gencache(const char *domain_name,
1698 const char *dc_name,
1699 struct cli_state *cli)
1701 char addr[INET6_ADDRSTRLEN];
1705 if (!cli_state_is_connected(cli)) {
1709 print_sockaddr(addr, sizeof(addr),
1710 smbXcli_conn_remote_sockaddr(cli->conn));
1712 key = current_dc_key(talloc_tos(), domain_name);
1717 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1718 if (value == NULL) {
1722 gencache_set(key, value, 0x7fffffff);
1728 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1729 const char *domain_name,
1730 char **p_dc_name, char **p_dc_ip)
1735 char *dc_name = NULL;
1738 key = current_dc_key(talloc_tos(), domain_name);
1742 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1745 p = strchr(value, ' ');
1749 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1750 if (dc_ip == NULL) {
1753 dc_name = talloc_strdup(mem_ctx, p+1);
1754 if (dc_name == NULL) {
1758 if (p_dc_ip != NULL) {
1762 if (p_dc_name != NULL) {
1763 *p_dc_name = dc_name;
1768 TALLOC_FREE(dc_name);
1775 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1776 const struct ndr_interface_table *table,
1777 struct rpc_pipe_client **ret_pipe)
1779 struct rpc_pipe_client *cli = NULL;
1780 const struct auth_session_info *session_info;
1781 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1784 session_info = get_session_info_system();
1785 SMB_ASSERT(session_info != NULL);
1787 /* create a connection to the specified pipe */
1788 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1789 status = rpc_pipe_open_interface(mem_ctx,
1794 server_messaging_context(),
1797 status = rpc_pipe_open_internal(mem_ctx,
1802 server_messaging_context(),
1805 if (!NT_STATUS_IS_OK(status)) {
1806 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1807 table->name, nt_errstr(status)));
1815 return NT_STATUS_OK;
1818 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1819 struct winbindd_cm_conn *new_conn,
1822 TALLOC_CTX *mem_ctx;
1824 char *saf_servername;
1826 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1828 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1829 set_domain_offline(domain);
1830 return NT_STATUS_NO_MEMORY;
1833 saf_servername = saf_fetch(mem_ctx, domain->name );
1835 /* we have to check the server affinity cache here since
1836 later we select a DC based on response time and not preference */
1838 /* Check the negative connection cache
1839 before talking to it. It going down may have
1840 triggered the reconnection. */
1842 if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1843 struct sockaddr_storage ss;
1844 char *dcname = NULL;
1845 bool resolved = true;
1847 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1848 saf_servername, domain->name));
1850 /* convert an ip address to a name */
1851 if (is_ipaddress(saf_servername)) {
1852 if (!interpret_string_addr(&ss, saf_servername,
1854 TALLOC_FREE(mem_ctx);
1855 return NT_STATUS_UNSUCCESSFUL;
1858 if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1863 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1864 domain->dcname = talloc_strdup(domain,
1866 if (domain->dcname == NULL) {
1867 TALLOC_FREE(mem_ctx);
1868 return NT_STATUS_NO_MEMORY;
1871 domain->dcaddr = ss;
1873 winbind_add_failed_connection_entry(domain, saf_servername,
1874 NT_STATUS_UNSUCCESSFUL);
1878 for (retries = 0; retries < 3; retries++) {
1881 char *dcname = NULL;
1883 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1885 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1886 domain->dcname ? domain->dcname : "", domain->name));
1888 if (domain->dcname != NULL &&
1889 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1894 status = smbsock_connect(&domain->dcaddr, 0,
1897 if (!NT_STATUS_IS_OK(status)) {
1903 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1905 /* This is the one place where we will
1906 set the global winbindd offline state
1907 to true, if a "WINBINDD_OFFLINE" entry
1908 is found in the winbindd cache. */
1909 set_global_winbindd_state_offline();
1912 if (dcname != NULL) {
1913 talloc_free(domain->dcname);
1915 domain->dcname = talloc_move(domain, &dcname);
1916 if (domain->dcname == NULL) {
1917 result = NT_STATUS_NO_MEMORY;
1922 new_conn->cli = NULL;
1924 result = cm_prepare_connection(domain, fd, domain->dcname,
1925 &new_conn->cli, &retry);
1926 if (!NT_STATUS_IS_OK(result)) {
1927 /* Don't leak the smb connection socket */
1935 if (NT_STATUS_IS_OK(result)) {
1936 bool seal_pipes = true;
1938 winbindd_set_locator_kdc_envs(domain);
1940 if (domain->online == False) {
1941 /* We're changing state from offline to online. */
1942 set_global_winbindd_state_online();
1944 set_domain_online(domain);
1947 * Much as I hate global state, this seems to be the point
1948 * where we can be certain that we have a proper connection to
1949 * a DC. wbinfo --dc-info needs that information, store it in
1950 * gencache with a looong timeout. This will need revisiting
1951 * once we start to connect to multiple DCs, wbcDcInfo is
1952 * already prepared for that.
1954 store_current_dc_in_gencache(domain->name, domain->dcname,
1957 seal_pipes = lp_winbind_sealed_pipes();
1958 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1963 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1965 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1968 /* Ensure we setup the retry handler. */
1969 set_domain_offline(domain);
1972 talloc_destroy(mem_ctx);
1976 /* Close down all open pipes on a connection. */
1978 void invalidate_cm_connection(struct winbindd_domain *domain)
1981 struct winbindd_cm_conn *conn = &domain->conn;
1983 /* We're closing down a possibly dead
1984 connection. Don't have impossibly long (10s) timeouts. */
1987 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1990 if (conn->samr_pipe != NULL) {
1991 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1992 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1994 &conn->sam_connect_handle,
1997 TALLOC_FREE(conn->samr_pipe);
1998 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2000 cli_set_timeout(conn->cli, 500);
2004 if (conn->lsa_pipe != NULL) {
2005 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2006 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2011 TALLOC_FREE(conn->lsa_pipe);
2012 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2014 cli_set_timeout(conn->cli, 500);
2018 if (conn->lsa_pipe_tcp != NULL) {
2019 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2020 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2025 TALLOC_FREE(conn->lsa_pipe_tcp);
2026 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2028 cli_set_timeout(conn->cli, 500);
2032 if (conn->netlogon_pipe != NULL) {
2033 TALLOC_FREE(conn->netlogon_pipe);
2034 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2036 cli_set_timeout(conn->cli, 500);
2040 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2041 conn->netlogon_force_reauth = false;
2042 TALLOC_FREE(conn->netlogon_creds_ctx);
2045 cli_shutdown(conn->cli);
2051 void close_conns_after_fork(void)
2053 struct winbindd_domain *domain;
2054 struct winbindd_cli_state *cli_state;
2056 for (domain = domain_list(); domain; domain = domain->next) {
2058 * first close the low level SMB TCP connection
2059 * so that we don't generate any SMBclose
2060 * requests in invalidate_cm_connection()
2062 if (cli_state_is_connected(domain->conn.cli)) {
2063 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2066 invalidate_cm_connection(domain);
2069 for (cli_state = winbindd_client_list();
2071 cli_state = cli_state->next) {
2072 if (cli_state->sock >= 0) {
2073 close(cli_state->sock);
2074 cli_state->sock = -1;
2079 static bool connection_ok(struct winbindd_domain *domain)
2083 ok = cli_state_is_connected(domain->conn.cli);
2085 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2086 domain->dcname, domain->name));
2090 if (domain->online == False) {
2091 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2098 /* Initialize a new connection up to the RPC BIND.
2099 Bypass online status check so always does network calls. */
2101 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2104 bool skip_connection = domain->internal;
2105 if (need_rw_dc && domain->rodc) {
2106 skip_connection = false;
2109 /* Internal connections never use the network. */
2110 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2111 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2114 /* Still ask the internal LSA and SAMR server about the local domain */
2115 if (skip_connection || connection_ok(domain)) {
2116 if (!domain->initialized) {
2117 set_dc_type_and_flags(domain);
2119 return NT_STATUS_OK;
2122 invalidate_cm_connection(domain);
2124 if (!domain->primary && !domain->initialized) {
2126 * Before we connect to a trust, work out if it is an
2127 * AD domain by asking our own domain.
2129 set_dc_type_and_flags_trustinfo(domain);
2132 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2134 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2135 set_dc_type_and_flags(domain);
2141 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2143 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2144 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2147 if (domain->initialized && !domain->online) {
2148 /* We check for online status elsewhere. */
2149 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2152 return init_dc_connection_network(domain, need_rw_dc);
2155 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2159 status = init_dc_connection(domain, need_rw_dc);
2160 if (!NT_STATUS_IS_OK(status)) {
2164 if (!domain->internal && domain->conn.cli == NULL) {
2165 /* happens for trusted domains without inbound trust */
2166 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2169 return NT_STATUS_OK;
2172 /******************************************************************************
2173 Set the trust flags (direction and forest location) for a domain
2174 ******************************************************************************/
2176 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2178 struct winbindd_domain *our_domain;
2179 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2181 struct netr_DomainTrustList trusts;
2183 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2184 NETR_TRUST_FLAG_OUTBOUND |
2185 NETR_TRUST_FLAG_INBOUND);
2186 struct rpc_pipe_client *cli;
2187 TALLOC_CTX *mem_ctx = NULL;
2188 struct dcerpc_binding_handle *b;
2190 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2192 /* Our primary domain doesn't need to worry about trust flags.
2193 Force it to go through the network setup */
2194 if ( domain->primary ) {
2198 mem_ctx = talloc_stackframe();
2199 our_domain = find_our_domain();
2200 if (our_domain->internal) {
2201 result = init_dc_connection(our_domain, false);
2202 if (!NT_STATUS_IS_OK(result)) {
2203 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2204 "Not able to make a connection to our domain: %s\n",
2205 nt_errstr(result)));
2206 TALLOC_FREE(mem_ctx);
2211 /* This won't work unless our domain is AD */
2212 if ( !our_domain->active_directory ) {
2213 TALLOC_FREE(mem_ctx);
2217 if (our_domain->internal) {
2218 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2219 } else if (!connection_ok(our_domain)) {
2220 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2221 "No connection to our domain!\n"));
2222 TALLOC_FREE(mem_ctx);
2225 result = cm_connect_netlogon(our_domain, &cli);
2228 if (!NT_STATUS_IS_OK(result)) {
2229 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2230 "a connection to %s for PIPE_NETLOGON (%s)\n",
2231 domain->name, nt_errstr(result)));
2232 TALLOC_FREE(mem_ctx);
2235 b = cli->binding_handle;
2237 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2238 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2243 if (!NT_STATUS_IS_OK(result)) {
2244 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2245 "failed to query trusted domain list: %s\n",
2246 nt_errstr(result)));
2247 TALLOC_FREE(mem_ctx);
2250 if (!W_ERROR_IS_OK(werr)) {
2251 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2252 "failed to query trusted domain list: %s\n",
2254 TALLOC_FREE(mem_ctx);
2258 /* Now find the domain name and get the flags */
2260 for ( i=0; i<trusts.count; i++ ) {
2261 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2262 domain->domain_flags = trusts.array[i].trust_flags;
2263 domain->domain_type = trusts.array[i].trust_type;
2264 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2266 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2267 domain->active_directory = True;
2269 /* This flag is only set if the domain is *our*
2270 primary domain and the primary domain is in
2273 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2275 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2276 "native mode.\n", domain->name,
2277 domain->native_mode ? "" : "NOT "));
2279 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2280 "running active directory.\n", domain->name,
2281 domain->active_directory ? "" : "NOT "));
2283 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2285 domain->initialized = True;
2291 TALLOC_FREE(mem_ctx);
2293 return domain->initialized;
2296 /******************************************************************************
2297 We can 'sense' certain things about the DC by it's replies to certain
2300 This tells us if this particular remote server is Active Directory, and if it
2302 ******************************************************************************/
2304 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2306 NTSTATUS status, result;
2308 TALLOC_CTX *mem_ctx = NULL;
2309 struct rpc_pipe_client *cli = NULL;
2310 struct policy_handle pol;
2311 union dssetup_DsRoleInfo info;
2312 union lsa_PolicyInformation *lsa_info = NULL;
2314 if (!domain->internal && !connection_ok(domain)) {
2318 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2321 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2325 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2327 if (domain->internal) {
2328 status = wb_open_internal_pipe(mem_ctx,
2332 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2337 if (!NT_STATUS_IS_OK(status)) {
2338 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2339 "PI_DSSETUP on domain %s: (%s)\n",
2340 domain->name, nt_errstr(status)));
2342 /* if this is just a non-AD domain we need to continue
2343 * identifying so that we can in the end return with
2344 * domain->initialized = True - gd */
2349 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2350 DS_ROLE_BASIC_INFORMATION,
2355 if (NT_STATUS_IS_OK(status)) {
2356 result = werror_to_ntstatus(werr);
2358 if (!NT_STATUS_IS_OK(status)) {
2359 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2360 "on domain %s failed: (%s)\n",
2361 domain->name, nt_errstr(status)));
2363 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2364 * every opcode on the DSSETUP pipe, continue with
2365 * no_dssetup mode here as well to get domain->initialized
2368 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2372 TALLOC_FREE(mem_ctx);
2376 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2377 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2378 domain->native_mode = True;
2380 domain->native_mode = False;
2384 if (domain->internal) {
2385 status = wb_open_internal_pipe(mem_ctx,
2389 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2390 &ndr_table_lsarpc, &cli);
2392 if (!NT_STATUS_IS_OK(status)) {
2393 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2394 "PI_LSARPC on domain %s: (%s)\n",
2395 domain->name, nt_errstr(status)));
2397 TALLOC_FREE(mem_ctx);
2401 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2402 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2404 if (NT_STATUS_IS_OK(status)) {
2405 /* This particular query is exactly what Win2k clients use
2406 to determine that the DC is active directory */
2407 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2409 LSA_POLICY_INFO_DNS,
2414 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2415 domain->active_directory = True;
2417 if (lsa_info->dns.name.string) {
2418 if (!strequal(domain->name, lsa_info->dns.name.string))
2420 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2421 "for domain %s claimed it was a DC "
2422 "for domain %s, refusing to "
2425 lsa_info->dns.name.string));
2427 TALLOC_FREE(mem_ctx);
2430 talloc_free(domain->name);
2431 domain->name = talloc_strdup(domain,
2432 lsa_info->dns.name.string);
2433 if (domain->name == NULL) {
2438 if (lsa_info->dns.dns_domain.string) {
2439 if (domain->alt_name != NULL &&
2440 !strequal(domain->alt_name,
2441 lsa_info->dns.dns_domain.string))
2443 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2444 "for domain %s (%s) claimed it was "
2445 "a DC for domain %s, refusing to "
2447 domain->alt_name, domain->name,
2448 lsa_info->dns.dns_domain.string));
2450 TALLOC_FREE(mem_ctx);
2453 talloc_free(domain->alt_name);
2455 talloc_strdup(domain,
2456 lsa_info->dns.dns_domain.string);
2457 if (domain->alt_name == NULL) {
2462 /* See if we can set some domain trust flags about
2465 if (lsa_info->dns.dns_forest.string) {
2466 talloc_free(domain->forest_name);
2467 domain->forest_name =
2468 talloc_strdup(domain,
2469 lsa_info->dns.dns_forest.string);
2470 if (domain->forest_name == NULL) {
2474 if (strequal(domain->forest_name, domain->alt_name)) {
2475 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2479 if (lsa_info->dns.sid) {
2480 if (!is_null_sid(&domain->sid) &&
2481 !dom_sid_equal(&domain->sid,
2484 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2485 "for domain %s (%s) claimed it was "
2486 "a DC for domain %s, refusing to "
2488 dom_sid_string(talloc_tos(),
2491 dom_sid_string(talloc_tos(),
2492 lsa_info->dns.sid)));
2494 TALLOC_FREE(mem_ctx);
2497 sid_copy(&domain->sid, lsa_info->dns.sid);
2500 domain->active_directory = False;
2502 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2503 SEC_FLAG_MAXIMUM_ALLOWED,
2506 if (!NT_STATUS_IS_OK(status)) {
2510 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2512 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2515 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2517 if (lsa_info->account_domain.name.string) {
2518 if (!strequal(domain->name,
2519 lsa_info->account_domain.name.string))
2522 ("set_dc_type_and_flags_connect: "
2523 "DC for domain %s claimed it was"
2524 " a DC for domain %s, refusing "
2525 "to initialize\n", domain->name,
2527 account_domain.name.string));
2529 TALLOC_FREE(mem_ctx);
2532 talloc_free(domain->name);
2534 talloc_strdup(domain,
2535 lsa_info->account_domain.name.string);
2538 if (lsa_info->account_domain.sid) {
2539 if (!is_null_sid(&domain->sid) &&
2540 !dom_sid_equal(&domain->sid,
2541 lsa_info->account_domain.sid))
2544 ("set_dc_type_and_flags_connect: "
2545 "DC for domain %s (%s) claimed "
2546 "it was a DC for domain %s, "
2547 "refusing to initialize\n",
2548 dom_sid_string(talloc_tos(),
2551 dom_sid_string(talloc_tos(),
2552 lsa_info->account_domain.sid)));
2554 TALLOC_FREE(mem_ctx);
2557 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2563 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2564 domain->name, domain->native_mode ? "" : "NOT "));
2566 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2567 domain->name, domain->active_directory ? "" : "NOT "));
2569 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2573 TALLOC_FREE(mem_ctx);
2575 domain->initialized = True;
2578 /**********************************************************************
2579 Set the domain_flags (trust attributes, domain operating modes, etc...
2580 ***********************************************************************/
2582 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2584 /* we always have to contact our primary domain */
2586 if ( domain->primary || domain->internal) {
2587 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2588 "primary or internal domain\n"));
2589 set_dc_type_and_flags_connect( domain );
2593 /* Use our DC to get the information if possible */
2595 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2596 /* Otherwise, fallback to contacting the
2598 set_dc_type_and_flags_connect( domain );
2606 /**********************************************************************
2607 ***********************************************************************/
2609 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2610 struct netlogon_creds_cli_context **ppdc)
2612 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2613 struct rpc_pipe_client *netlogon_pipe;
2617 if ((!IS_DC) && (!domain->primary)) {
2618 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2621 if (domain->conn.netlogon_creds_ctx != NULL) {
2622 *ppdc = domain->conn.netlogon_creds_ctx;
2623 return NT_STATUS_OK;
2626 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2627 if (!NT_STATUS_IS_OK(result)) {
2631 return NT_STATUS_OK;
2634 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2636 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2638 struct winbindd_cm_conn *conn;
2639 NTSTATUS status, result;
2640 struct netlogon_creds_cli_context *p_creds;
2641 struct cli_credentials *creds = NULL;
2642 bool retry = false; /* allow one retry attempt for expired session */
2644 if (sid_check_is_our_sam(&domain->sid)) {
2645 if (domain->rodc == false || need_rw_dc == false) {
2646 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2651 status = init_dc_connection_rpc(domain, need_rw_dc);
2652 if (!NT_STATUS_IS_OK(status)) {
2656 conn = &domain->conn;
2658 if (rpccli_is_connected(conn->samr_pipe)) {
2662 TALLOC_FREE(conn->samr_pipe);
2665 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2666 * sign and sealed pipe using the machine account password by
2667 * preference. If we can't - try schannel, if that fails, try
2671 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2672 if (!NT_STATUS_IS_OK(result)) {
2673 DEBUG(10, ("cm_connect_sam: No user available for "
2674 "domain %s, trying schannel\n", domain->name));
2678 if (cli_credentials_is_anonymous(creds)) {
2683 * We have an authenticated connection. Use a SPNEGO
2684 * authenticated SAMR pipe with sign & seal.
2686 status = cli_rpc_pipe_open_with_creds(conn->cli,
2689 DCERPC_AUTH_TYPE_SPNEGO,
2691 smbXcli_conn_remote_name(conn->cli->conn),
2695 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2697 invalidate_cm_connection(domain);
2702 if (!NT_STATUS_IS_OK(status)) {
2703 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2704 "pipe for domain %s using NTLMSSP "
2705 "authenticated pipe: user %s. Error was "
2706 "%s\n", domain->name,
2707 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2708 nt_errstr(status)));
2712 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2713 "domain %s using NTLMSSP authenticated "
2714 "pipe: user %s\n", domain->name,
2715 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2717 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2718 conn->samr_pipe->desthost,
2719 SEC_FLAG_MAXIMUM_ALLOWED,
2720 &conn->sam_connect_handle,
2723 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2724 invalidate_cm_connection(domain);
2725 TALLOC_FREE(conn->samr_pipe);
2730 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2733 if (NT_STATUS_IS_OK(status)) {
2737 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2738 "failed for domain %s, error was %s. Trying schannel\n",
2739 domain->name, nt_errstr(status) ));
2740 TALLOC_FREE(conn->samr_pipe);
2744 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2746 status = cm_get_schannel_creds(domain, &p_creds);
2747 if (!NT_STATUS_IS_OK(status)) {
2748 /* If this call fails - conn->cli can now be NULL ! */
2749 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2750 "for domain %s (error %s), trying anon\n",
2752 nt_errstr(status) ));
2756 status = cli_rpc_pipe_open_schannel_with_creds(
2757 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2760 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2762 invalidate_cm_connection(domain);
2767 if (!NT_STATUS_IS_OK(status)) {
2768 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2769 "domain %s using schannel. Error was %s\n",
2770 domain->name, nt_errstr(status) ));
2773 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2774 "schannel.\n", domain->name ));
2776 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2777 conn->samr_pipe->desthost,
2778 SEC_FLAG_MAXIMUM_ALLOWED,
2779 &conn->sam_connect_handle,
2782 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2783 invalidate_cm_connection(domain);
2784 TALLOC_FREE(conn->samr_pipe);
2789 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2792 if (NT_STATUS_IS_OK(status)) {
2795 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2796 "for domain %s, error was %s. Trying anonymous\n",
2797 domain->name, nt_errstr(status) ));
2798 TALLOC_FREE(conn->samr_pipe);
2802 /* Finally fall back to anonymous. */
2803 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2804 status = NT_STATUS_DOWNGRADE_DETECTED;
2805 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2806 "without connection level security, "
2807 "must set 'winbind sealed pipes = false' and "
2808 "'require strong key = false' to proceed: %s\n",
2809 domain->name, nt_errstr(status)));
2812 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2815 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2817 invalidate_cm_connection(domain);
2822 if (!NT_STATUS_IS_OK(status)) {
2826 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2827 conn->samr_pipe->desthost,
2828 SEC_FLAG_MAXIMUM_ALLOWED,
2829 &conn->sam_connect_handle,
2832 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2833 invalidate_cm_connection(domain);
2834 TALLOC_FREE(conn->samr_pipe);
2839 if (!NT_STATUS_IS_OK(status)) {
2840 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2841 "for domain %s Error was %s\n",
2842 domain->name, nt_errstr(status) ));
2845 if (!NT_STATUS_IS_OK(result)) {
2847 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2848 "for domain %s Error was %s\n",
2849 domain->name, nt_errstr(result)));
2854 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2856 &conn->sam_connect_handle,
2857 SEC_FLAG_MAXIMUM_ALLOWED,
2859 &conn->sam_domain_handle,
2861 if (!NT_STATUS_IS_OK(status)) {
2868 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2870 * if we got access denied, we might just have no access rights
2871 * to talk to the remote samr server server (e.g. when we are a
2872 * PDC and we are connecting a w2k8 pdc via an interdomain
2873 * trust). In that case do not invalidate the whole connection
2876 TALLOC_FREE(conn->samr_pipe);
2877 ZERO_STRUCT(conn->sam_domain_handle);
2879 } else if (!NT_STATUS_IS_OK(status)) {
2880 invalidate_cm_connection(domain);
2884 *cli = conn->samr_pipe;
2885 *sam_handle = conn->sam_domain_handle;
2889 /**********************************************************************
2890 open an schanneld ncacn_ip_tcp connection to LSA
2891 ***********************************************************************/
2893 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2894 TALLOC_CTX *mem_ctx,
2895 struct rpc_pipe_client **cli)
2897 struct winbindd_cm_conn *conn;
2898 struct netlogon_creds_cli_context *p_creds = NULL;
2901 DEBUG(10,("cm_connect_lsa_tcp\n"));
2903 status = init_dc_connection_rpc(domain, false);
2904 if (!NT_STATUS_IS_OK(status)) {
2908 conn = &domain->conn;
2911 * rpccli_is_connected handles more error cases
2913 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2914 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2915 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2919 TALLOC_FREE(conn->lsa_pipe_tcp);
2921 status = cm_get_schannel_creds(domain, &p_creds);
2922 if (!NT_STATUS_IS_OK(status)) {
2926 status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
2930 &conn->lsa_pipe_tcp);
2931 if (!NT_STATUS_IS_OK(status)) {
2932 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2933 nt_errstr(status)));
2938 if (!NT_STATUS_IS_OK(status)) {
2939 TALLOC_FREE(conn->lsa_pipe_tcp);
2943 *cli = conn->lsa_pipe_tcp;
2948 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2949 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2951 struct winbindd_cm_conn *conn;
2952 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2953 struct netlogon_creds_cli_context *p_creds;
2954 struct cli_credentials *creds = NULL;
2955 bool retry = false; /* allow one retry attempt for expired session */
2958 result = init_dc_connection_rpc(domain, false);
2959 if (!NT_STATUS_IS_OK(result))
2962 conn = &domain->conn;
2964 if (rpccli_is_connected(conn->lsa_pipe)) {
2968 TALLOC_FREE(conn->lsa_pipe);
2970 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2971 if (!NT_STATUS_IS_OK(result)) {
2972 DEBUG(10, ("cm_connect_lsa: No user available for "
2973 "domain %s, trying schannel\n", domain->name));
2977 if (cli_credentials_is_anonymous(creds)) {
2982 * We have an authenticated connection. Use a SPNEGO
2983 * authenticated LSA pipe with sign & seal.
2985 result = cli_rpc_pipe_open_with_creds
2986 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2987 DCERPC_AUTH_TYPE_SPNEGO,
2989 smbXcli_conn_remote_name(conn->cli->conn),
2993 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
2995 invalidate_cm_connection(domain);
3000 if (!NT_STATUS_IS_OK(result)) {
3001 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3002 "domain %s using NTLMSSP authenticated pipe: user "
3003 "%s. Error was %s. Trying schannel.\n",
3005 cli_credentials_get_unparsed_name(creds, talloc_tos()),
3006 nt_errstr(result)));
3010 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3011 "NTLMSSP authenticated pipe: user %s\n",
3012 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3014 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3015 SEC_FLAG_MAXIMUM_ALLOWED,
3017 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3018 invalidate_cm_connection(domain);
3019 TALLOC_FREE(conn->lsa_pipe);
3024 if (NT_STATUS_IS_OK(result)) {
3028 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3031 TALLOC_FREE(conn->lsa_pipe);
3035 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3037 result = cm_get_schannel_creds(domain, &p_creds);
3038 if (!NT_STATUS_IS_OK(result)) {
3039 /* If this call fails - conn->cli can now be NULL ! */
3040 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3041 "for domain %s (error %s), trying anon\n",
3043 nt_errstr(result) ));
3048 result = cli_rpc_pipe_open_schannel_with_creds(
3049 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3052 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3054 invalidate_cm_connection(domain);
3059 if (!NT_STATUS_IS_OK(result)) {
3060 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3061 "domain %s using schannel. Error was %s\n",
3062 domain->name, nt_errstr(result) ));
3065 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3066 "schannel.\n", domain->name ));
3068 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3069 SEC_FLAG_MAXIMUM_ALLOWED,
3072 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3073 invalidate_cm_connection(domain);
3074 TALLOC_FREE(conn->lsa_pipe);
3079 if (NT_STATUS_IS_OK(result)) {
3083 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3086 TALLOC_FREE(conn->lsa_pipe);
3090 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3091 result = NT_STATUS_DOWNGRADE_DETECTED;
3092 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3093 "without connection level security, "
3094 "must set 'winbind sealed pipes = false' and "
3095 "'require strong key = false' to proceed: %s\n",
3096 domain->name, nt_errstr(result)));
3100 result = cli_rpc_pipe_open_noauth(conn->cli,
3104 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3106 invalidate_cm_connection(domain);
3111 if (!NT_STATUS_IS_OK(result)) {
3115 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3116 SEC_FLAG_MAXIMUM_ALLOWED,
3119 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3120 invalidate_cm_connection(domain);
3121 TALLOC_FREE(conn->lsa_pipe);
3127 if (!NT_STATUS_IS_OK(result)) {
3128 invalidate_cm_connection(domain);
3132 *cli = conn->lsa_pipe;
3133 *lsa_policy = conn->lsa_policy;
3137 /****************************************************************************
3138 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3139 ****************************************************************************/
3141 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3142 TALLOC_CTX *mem_ctx,
3143 struct rpc_pipe_client **cli,
3144 struct policy_handle *lsa_policy)
3148 if (domain->can_do_ncacn_ip_tcp) {
3149 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3150 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3151 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3152 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3153 invalidate_cm_connection(domain);
3154 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3156 if (NT_STATUS_IS_OK(status)) {
3161 * we tried twice to connect via ncan_ip_tcp and schannel and
3162 * failed - maybe it is a trusted domain we can't connect to ?
3163 * do not try tcp next time - gd
3165 * This also prevents NETLOGON over TCP
3167 domain->can_do_ncacn_ip_tcp = false;
3170 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3175 /****************************************************************************
3176 Open the netlogon pipe to this DC.
3177 ****************************************************************************/
3179 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3180 enum dcerpc_transport_t transport,
3181 struct rpc_pipe_client **cli)
3183 struct messaging_context *msg_ctx = server_messaging_context();
3184 struct winbindd_cm_conn *conn;
3186 enum netr_SchannelType sec_chan_type;
3187 struct cli_credentials *creds = NULL;
3191 result = init_dc_connection_rpc(domain, domain->rodc);
3192 if (!NT_STATUS_IS_OK(result)) {
3196 conn = &domain->conn;
3198 if (rpccli_is_connected(conn->netlogon_pipe)) {
3199 *cli = conn->netlogon_pipe;
3200 return NT_STATUS_OK;
3203 TALLOC_FREE(conn->netlogon_pipe);
3204 TALLOC_FREE(conn->netlogon_creds_ctx);
3206 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3207 if (!NT_STATUS_IS_OK(result)) {
3208 DBG_DEBUG("No user available for domain %s when trying "
3209 "schannel\n", domain->name);
3210 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3213 if (cli_credentials_is_anonymous(creds)) {
3214 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3215 "unable to make get NETLOGON credentials\n",
3217 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3220 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3221 if (sec_chan_type == SEC_CHAN_NULL) {
3222 if (transport == NCACN_IP_TCP) {
3223 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3224 "for %s, deny NCACN_IP_TCP and let the "
3225 "caller fallback to NCACN_NP.\n",
3227 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3230 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3231 "fallback to noauth on NCACN_NP.\n",
3234 result = cli_rpc_pipe_open_noauth_transport(
3237 &ndr_table_netlogon,
3238 &conn->netlogon_pipe);
3239 if (!NT_STATUS_IS_OK(result)) {
3240 invalidate_cm_connection(domain);
3244 *cli = conn->netlogon_pipe;
3245 return NT_STATUS_OK;
3248 result = rpccli_create_netlogon_creds_ctx(creds,
3252 &conn->netlogon_creds_ctx);
3253 if (!NT_STATUS_IS_OK(result)) {
3254 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3255 "unable to create NETLOGON credentials: %s\n",
3256 domain->name, nt_errstr(result)));
3260 result = rpccli_connect_netlogon(
3261 conn->cli, transport,
3262 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3263 &conn->netlogon_pipe);
3264 if (!NT_STATUS_IS_OK(result)) {
3265 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3270 *cli = conn->netlogon_pipe;
3271 return NT_STATUS_OK;
3274 /****************************************************************************
3275 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3276 ****************************************************************************/
3278 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3279 struct rpc_pipe_client **cli)
3283 status = init_dc_connection_rpc(domain, domain->rodc);
3284 if (!NT_STATUS_IS_OK(status)) {
3288 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3289 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3290 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3291 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3292 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3293 invalidate_cm_connection(domain);
3294 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3296 if (NT_STATUS_IS_OK(status)) {
3301 * we tried twice to connect via ncan_ip_tcp and schannel and
3302 * failed - maybe it is a trusted domain we can't connect to ?
3303 * do not try tcp next time - gd
3305 * This also prevents LSA over TCP
3307 domain->can_do_ncacn_ip_tcp = false;
3310 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3311 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3313 * SMB2 session expired, needs reauthentication. Drop
3314 * connection and retry.
3316 invalidate_cm_connection(domain);
3317 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3323 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3324 struct rpc_pipe_client **cli,
3325 struct netlogon_creds_cli_context **ppdc)
3329 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3330 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3333 status = cm_connect_netlogon(domain, cli);
3334 if (!NT_STATUS_IS_OK(status)) {
3338 if (domain->conn.netlogon_creds_ctx == NULL) {
3339 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3342 *ppdc = domain->conn.netlogon_creds_ctx;
3343 return NT_STATUS_OK;
3346 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3349 struct server_id server_id,
3352 struct winbindd_domain *domain;
3353 char *freeit = NULL;
3357 || (data->data == NULL)
3358 || (data->length == 0)
3359 || (data->data[data->length-1] != '\0')) {
3360 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3365 addr = (char *)data->data;
3366 DEBUG(10, ("IP %s dropped\n", addr));
3368 if (!is_ipaddress(addr)) {
3371 * Some code sends us ip addresses with the /netmask
3374 slash = strchr(addr, '/');
3375 if (slash == NULL) {
3376 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3380 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3381 if (freeit == NULL) {
3382 DEBUG(1, ("talloc failed\n"));
3386 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3389 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3390 char sockaddr[INET6_ADDRSTRLEN];
3392 if (!cli_state_is_connected(domain->conn.cli)) {
3396 print_sockaddr(sockaddr, sizeof(sockaddr),
3397 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3399 if (strequal(sockaddr, addr)) {
3400 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3403 TALLOC_FREE(freeit);