ctdb-scripts: Move database handling to its own event script
[samba4-gss.git] / source3 / winbindd / winbindd_cm.c
blobf33e0bcb165c659181d52500cae7b5c7cf1f4a09
1 /*
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
34 selection etc
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
46 implementation. -tpot
51 TODO:
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
57 various sam handles.
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "libsmb/namequery.h"
64 #include "../libcli/auth/libcli_auth.h"
65 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
66 #include "rpc_client/cli_pipe.h"
67 #include "rpc_client/cli_netlogon.h"
68 #include "../librpc/gen_ndr/ndr_samr_c.h"
69 #include "../librpc/gen_ndr/ndr_lsa_c.h"
70 #include "rpc_client/cli_lsarpc.h"
71 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
72 #include "libads/sitename_cache.h"
73 #include "libsmb/libsmb.h"
74 #include "libsmb/clidgram.h"
75 #include "ads.h"
76 #include "secrets.h"
77 #include "../libcli/security/security.h"
78 #include "passdb.h"
79 #include "messages.h"
80 #include "auth/gensec/gensec.h"
81 #include "../libcli/smb/smbXcli_base.h"
82 #include "libcli/auth/netlogon_creds_cli.h"
83 #include "auth.h"
84 #include "rpc_server/rpc_ncacn_np.h"
85 #include "auth/credentials/credentials.h"
86 #include "lib/param/param.h"
87 #include "lib/gencache.h"
88 #include "lib/util/string_wrappers.h"
89 #include "lib/global_contexts.h"
90 #include "librpc/gen_ndr/ndr_winbind_c.h"
92 #undef DBGC_CLASS
93 #define DBGC_CLASS DBGC_WINBIND
95 struct dc_name_ip {
96 fstring name;
97 struct sockaddr_storage ss;
100 extern struct winbindd_methods reconnect_methods;
102 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
103 static void set_dc_type_and_flags( struct winbindd_domain *domain );
104 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
105 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
106 struct dc_name_ip **dcs, int *num_dcs,
107 uint32_t request_flags);
109 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
110 void *private_data,
111 uint32_t msg_type,
112 struct server_id server_id,
113 DATA_BLOB *data)
115 const char *domain_name = (const char *)data->data;
116 struct winbindd_domain *domain;
118 domain = find_domain_from_name_noinit(domain_name);
119 if (domain == NULL) {
120 DBG_DEBUG("Domain %s not found!\n", domain_name);
121 return;
124 DBG_DEBUG("Domain %s was %s, change to offline now.\n",
125 domain_name,
126 domain->online ? "online" : "offline");
128 domain->online = false;
131 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
132 void *private_data,
133 uint32_t msg_type,
134 struct server_id server_id,
135 DATA_BLOB *data)
137 const char *domain_name = (const char *)data->data;
138 struct winbindd_domain *domain;
140 domain = find_domain_from_name_noinit(domain_name);
141 if (domain == NULL) {
142 return;
145 SMB_ASSERT(wb_child_domain() == NULL);
147 DBG_DEBUG("Domain %s was %s, marking as online now!\n",
148 domain_name,
149 domain->online ? "online" : "offline");
151 domain->online = true;
154 /****************************************************************
155 Set domain offline and also add handler to put us back online
156 if we detect a DC.
157 ****************************************************************/
159 void set_domain_offline(struct winbindd_domain *domain)
161 pid_t parent_pid = getppid();
163 DEBUG(10,("set_domain_offline: called for domain %s\n",
164 domain->name ));
166 if (domain->internal) {
167 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
168 domain->name ));
169 return;
172 domain->online = False;
174 /* Offline domains are always initialized. They're
175 re-initialized when they go back online. */
177 domain->initialized = True;
179 /* Send a message to the parent that the domain is offline. */
180 if (parent_pid > 1 && !domain->internal) {
181 messaging_send_buf(global_messaging_context(),
182 pid_to_procid(parent_pid),
183 MSG_WINBIND_DOMAIN_OFFLINE,
184 (uint8_t *)domain->name,
185 strlen(domain->name) + 1);
188 /* Send an offline message to the idmap child when our
189 primary domain goes offline */
190 if ( domain->primary ) {
191 pid_t idmap_pid = idmap_child_pid();
193 if (idmap_pid != 0) {
194 messaging_send_buf(global_messaging_context(),
195 pid_to_procid(idmap_pid),
196 MSG_WINBIND_OFFLINE,
197 (const uint8_t *)domain->name,
198 strlen(domain->name)+1);
202 return;
205 /****************************************************************
206 Set domain online - if allowed.
207 ****************************************************************/
209 static void set_domain_online(struct winbindd_domain *domain)
211 pid_t parent_pid = getppid();
213 DEBUG(10,("set_domain_online: called for domain %s\n",
214 domain->name ));
216 if (domain->internal) {
217 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
218 domain->name ));
219 return;
222 if (get_global_winbindd_state_offline()) {
223 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
224 domain->name ));
225 return;
228 winbindd_set_locator_kdc_envs(domain);
230 /* If we are waiting to get a krb5 ticket, trigger immediately. */
231 ccache_regain_all_now();
233 /* Ok, we're out of any startup mode now... */
234 domain->startup = False;
236 if (domain->online == False) {
237 /* We were offline - now we're online. We default to
238 using the MS-RPC backend if we started offline,
239 and if we're going online for the first time we
240 should really re-initialize the backends and the
241 checks to see if we're talking to an AD or NT domain.
244 domain->initialized = False;
246 /* 'reconnect_methods' is the MS-RPC backend. */
247 if (domain->backend == &reconnect_methods) {
248 domain->backend = NULL;
252 domain->online = True;
254 /* Send a message to the parent that the domain is online. */
255 if (parent_pid > 1 && !domain->internal) {
256 messaging_send_buf(global_messaging_context(),
257 pid_to_procid(parent_pid),
258 MSG_WINBIND_DOMAIN_ONLINE,
259 (uint8_t *)domain->name,
260 strlen(domain->name) + 1);
263 /* Send an online message to the idmap child when our
264 primary domain comes online */
266 if ( domain->primary ) {
267 pid_t idmap_pid = idmap_child_pid();
269 if (idmap_pid != 0) {
270 messaging_send_buf(global_messaging_context(),
271 pid_to_procid(idmap_pid),
272 MSG_WINBIND_ONLINE,
273 (const uint8_t *)domain->name,
274 strlen(domain->name)+1);
278 return;
281 /****************************************************************
282 Requested to set a domain online.
283 ****************************************************************/
285 void set_domain_online_request(struct winbindd_domain *domain)
287 NTSTATUS status;
289 SMB_ASSERT(wb_child_domain() || idmap_child());
291 DEBUG(10,("set_domain_online_request: called for domain %s\n",
292 domain->name ));
294 if (get_global_winbindd_state_offline()) {
295 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
296 domain->name ));
297 return;
300 if (domain->internal) {
301 DEBUG(10, ("set_domain_online_request: Internal domains are "
302 "always online\n"));
303 return;
307 * This call takes care of setting the online flag to true if we
308 * connected, or tell the parent to ping us back if false. Bypasses
309 * online check so always does network calls.
311 status = init_dc_connection_network(domain, true);
312 DBG_DEBUG("init_dc_connection_network(), returned %s, called for "
313 "domain %s (online = %s)\n",
314 nt_errstr(status),
315 domain->name,
316 domain->online ? "true" : "false");
319 /****************************************************************
320 Add -ve connection cache entries for domain and realm.
321 ****************************************************************/
323 static void winbind_add_failed_connection_entry(
324 const struct winbindd_domain *domain,
325 const char *server,
326 NTSTATUS result)
328 add_failed_connection_entry(domain->name, server, result);
329 /* If this was the saf name for the last thing we talked to,
330 remove it. */
331 saf_delete(domain->name);
332 if (domain->alt_name != NULL) {
333 add_failed_connection_entry(domain->alt_name, server, result);
334 saf_delete(domain->alt_name);
336 winbindd_unset_locator_kdc_env(domain);
339 /* Choose between anonymous or authenticated connections. We need to use
340 an authenticated connection if DCs have the RestrictAnonymous registry
341 entry set > 0, or the "Additional restrictions for anonymous
342 connections" set in the win2k Local Security Policy.
344 Caller to free() result in domain, username, password
347 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
349 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
350 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
351 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
353 if (*username && **username) {
355 if (!*domain || !**domain)
356 *domain = smb_xstrdup(lp_workgroup());
358 if (!*password || !**password)
359 *password = smb_xstrdup("");
361 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
362 *domain, *username));
364 } else {
365 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
366 *username = smb_xstrdup("");
367 *domain = smb_xstrdup("");
368 *password = smb_xstrdup("");
372 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
373 struct cli_credentials **_creds)
376 TALLOC_CTX *frame = talloc_stackframe();
377 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
378 struct loadparm_context *lp_ctx;
379 char *username = NULL;
380 char *netbios_domain = NULL;
381 char *password = NULL;
382 struct cli_credentials *creds = NULL;
383 bool ok;
385 cm_get_ipc_userpass(&username, &netbios_domain, &password);
387 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
388 if (lp_ctx == NULL) {
389 DEBUG(1, ("loadparm_init_s3 failed\n"));
390 status = NT_STATUS_INTERNAL_ERROR;
391 goto fail;
394 creds = cli_credentials_init(mem_ctx);
395 if (creds == NULL) {
396 status = NT_STATUS_NO_MEMORY;
397 goto fail;
400 ok = cli_credentials_set_conf(creds, lp_ctx);
401 if (!ok) {
402 status = NT_STATUS_INTERNAL_ERROR;
403 goto fail;
406 cli_credentials_set_kerberos_state(creds,
407 CRED_USE_KERBEROS_DISABLED,
408 CRED_SPECIFIED);
410 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
411 if (!ok) {
412 status = NT_STATUS_NO_MEMORY;
413 goto fail;
416 ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
417 if (!ok) {
418 status = NT_STATUS_NO_MEMORY;
419 goto fail;
422 ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
423 if (!ok) {
424 status = NT_STATUS_NO_MEMORY;
425 goto fail;
428 *_creds = creds;
429 creds = NULL;
430 status = NT_STATUS_OK;
431 fail:
432 TALLOC_FREE(creds);
433 SAFE_FREE(username);
434 SAFE_FREE(netbios_domain);
435 SAFE_FREE(password);
436 TALLOC_FREE(frame);
437 return status;
440 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
442 TALLOC_CTX *frame = talloc_stackframe();
443 char *ipc_account = NULL;
444 char *ipc_domain = NULL;
445 char *ipc_password = NULL;
446 const char *creds_account = NULL;
447 const char *creds_domain = NULL;
448 const char *creds_password = NULL;
449 bool ret = false;
451 cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
453 creds_account = cli_credentials_get_username(creds);
454 creds_domain = cli_credentials_get_domain(creds);
455 creds_password = cli_credentials_get_password(creds);
457 if (!strequal(ipc_domain, creds_domain)) {
458 goto done;
461 if (!strequal(ipc_account, creds_account)) {
462 goto done;
465 if (!strcsequal(ipc_password, creds_password)) {
466 goto done;
469 ret = true;
470 done:
471 SAFE_FREE(ipc_account);
472 SAFE_FREE(ipc_domain);
473 SAFE_FREE(ipc_password);
474 TALLOC_FREE(frame);
475 return ret;
478 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
479 fstring dcname,
480 struct sockaddr_storage *dc_ss,
481 uint32_t request_flags)
483 struct winbindd_domain *our_domain = NULL;
484 struct rpc_pipe_client *netlogon_pipe = NULL;
485 NTSTATUS result;
486 WERROR werr;
487 TALLOC_CTX *mem_ctx;
488 unsigned int orig_timeout;
489 const char *tmp = NULL;
490 const char *p;
491 struct dcerpc_binding_handle *b;
493 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
494 * moment.... */
496 if (IS_DC) {
497 return False;
500 if (domain->primary) {
501 return False;
504 our_domain = find_our_domain();
506 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
507 return False;
510 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
511 if (!NT_STATUS_IS_OK(result)) {
512 talloc_destroy(mem_ctx);
513 return False;
516 b = netlogon_pipe->binding_handle;
518 /* This call can take a long time - allow the server to time out.
519 35 seconds should do it. */
521 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
523 if (our_domain->active_directory) {
524 struct netr_DsRGetDCNameInfo *domain_info = NULL;
527 * TODO request flags are not respected in the server
528 * (and in some cases, like REQUIRE_PDC, causes an error)
530 result = dcerpc_netr_DsRGetDCName(b,
531 mem_ctx,
532 our_domain->dcname,
533 domain->name,
534 NULL,
535 NULL,
536 request_flags|DS_RETURN_DNS_NAME,
537 &domain_info,
538 &werr);
539 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
540 tmp = talloc_strdup(
541 mem_ctx, domain_info->dc_unc);
542 if (tmp == NULL) {
543 DBG_ERR("talloc_strdup failed for dc_unc[%s]\n",
544 domain_info->dc_unc);
545 talloc_destroy(mem_ctx);
546 return false;
548 if (domain->alt_name == NULL) {
549 domain->alt_name = talloc_strdup(domain,
550 domain_info->domain_name);
551 if (domain->alt_name == NULL) {
552 DBG_ERR("talloc_strdup failed for "
553 "domain_info->domain_name[%s]\n",
554 domain_info->domain_name);
555 talloc_destroy(mem_ctx);
556 return false;
559 if (domain->forest_name == NULL) {
560 domain->forest_name = talloc_strdup(domain,
561 domain_info->forest_name);
562 if (domain->forest_name == NULL) {
563 DBG_ERR("talloc_strdup failed for "
564 "domain_info->forest_name[%s]\n",
565 domain_info->forest_name);
566 talloc_destroy(mem_ctx);
567 return false;
571 } else {
572 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
573 our_domain->dcname,
574 domain->name,
575 &tmp,
576 &werr);
579 /* And restore our original timeout. */
580 rpccli_set_timeout(netlogon_pipe, orig_timeout);
582 if (!NT_STATUS_IS_OK(result)) {
583 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
584 nt_errstr(result)));
585 talloc_destroy(mem_ctx);
586 return false;
589 if (!W_ERROR_IS_OK(werr)) {
590 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
591 win_errstr(werr)));
592 talloc_destroy(mem_ctx);
593 return false;
596 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
597 p = strip_hostname(tmp);
599 fstrcpy(dcname, p);
601 talloc_destroy(mem_ctx);
603 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
605 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
606 return False;
609 return True;
613 * Helper function to assemble trust password and account name
615 NTSTATUS winbindd_get_trust_credentials(struct winbindd_domain *domain,
616 TALLOC_CTX *mem_ctx,
617 bool netlogon,
618 bool allow_ipc_fallback,
619 struct cli_credentials **_creds)
621 const struct winbindd_domain *creds_domain = NULL;
622 struct cli_credentials *creds;
623 NTSTATUS status;
624 bool force_machine_account = false;
626 /* If we are a DC and this is not our own domain */
628 if (!domain->active_directory) {
629 if (!netlogon) {
631 * For non active directory domains
632 * we can only use NTLMSSP for SMB.
634 * But the trust account is not allowed
635 * to use SMB with NTLMSSP.
637 force_machine_account = true;
641 if (IS_DC && !force_machine_account) {
642 creds_domain = domain;
643 } else {
644 creds_domain = find_our_domain();
645 if (creds_domain == NULL) {
646 return NT_STATUS_INVALID_SERVER_STATE;
650 status = pdb_get_trust_credentials(creds_domain->name,
651 creds_domain->alt_name,
652 mem_ctx,
653 &creds);
654 if (!NT_STATUS_IS_OK(status)) {
655 goto ipc_fallback;
658 if (creds_domain != domain) {
660 * We can only use schannel against a direct trust
662 cli_credentials_set_secure_channel_type(creds,
663 SEC_CHAN_NULL);
666 *_creds = creds;
667 return NT_STATUS_OK;
669 ipc_fallback:
670 if (netlogon) {
671 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
674 if (!allow_ipc_fallback) {
675 return status;
678 status = cm_get_ipc_credentials(mem_ctx, &creds);
679 if (!NT_STATUS_IS_OK(status)) {
680 return status;
683 *_creds = creds;
684 return NT_STATUS_OK;
687 /************************************************************************
688 Given a fd with a just-connected TCP connection to a DC, open a connection
689 to the pipe.
690 ************************************************************************/
692 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
693 const int sockfd,
694 const char *controller,
695 struct cli_state **cli,
696 bool *retry)
698 bool try_ipc_auth = false;
699 const char *machine_principal = NULL;
700 const char *machine_realm = NULL;
701 const char *machine_account = NULL;
702 const char *machine_domain = NULL;
703 int flags = 0;
704 struct cli_credentials *creds = NULL;
706 struct named_mutex *mutex;
708 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
709 NTSTATUS tmp_status;
710 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
712 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
714 if (IS_DC) {
715 if (domain->secure_channel_type == SEC_CHAN_NULL) {
717 * Make sure we don't even try to
718 * connect to a foreign domain
719 * without a direct outbound trust.
721 close(sockfd);
722 return NT_STATUS_NO_TRUST_LSA_SECRET;
726 * As AD DC we only use netlogon and lsa
727 * using schannel over an anonymous transport
728 * (ncacn_ip_tcp or ncacn_np).
730 * Currently we always establish the SMB connection,
731 * even if we don't use it, because we later use ncacn_ip_tcp.
733 * As we won't use the SMB connection there's no
734 * need to try kerberos. And NT4 domains expect
735 * an anonymous IPC$ connection anyway.
737 smb_sign_client_connections = SMB_SIGNING_OFF;
740 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
742 * If we are connecting to our own AD domain, require
743 * smb signing to disrupt MITM attacks
745 if (domain->primary && lp_security() == SEC_ADS) {
746 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
748 * If we are in or are an AD domain and connecting to another
749 * AD domain in our forest
750 * then require smb signing to disrupt MITM attacks
752 } else if ((lp_security() == SEC_ADS)
753 && domain->active_directory
754 && (domain->domain_trust_attribs
755 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
756 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
760 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
761 controller, domain->name ));
763 *retry = True;
765 mutex = grab_named_mutex(talloc_tos(), controller,
766 WINBIND_SERVER_MUTEX_WAIT_TIME);
767 if (mutex == NULL) {
768 close(sockfd);
769 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
770 controller));
771 result = NT_STATUS_POSSIBLE_DEADLOCK;
772 goto done;
776 * cm_prepare_connection() is responsible that sockfd does not leak.
777 * Once cli_state_create() returns with success, the
778 * smbXcli_conn_destructor() makes sure that close(sockfd) is finally
779 * called. Till that, close(sockfd) must be called on every unsuccessful
780 * return.
782 *cli = cli_state_create(NULL, sockfd, controller,
783 smb_sign_client_connections, flags);
784 if (*cli == NULL) {
785 close(sockfd);
786 DEBUG(1, ("Could not cli_initialize\n"));
787 result = NT_STATUS_NO_MEMORY;
788 goto done;
791 cli_set_timeout(*cli, 10000); /* 10 seconds */
793 set_socket_options(sockfd, lp_socket_options());
795 result = smbXcli_negprot((*cli)->conn,
796 (*cli)->timeout,
797 lp_client_ipc_min_protocol(),
798 lp_client_ipc_max_protocol(),
799 NULL,
800 NULL,
801 NULL);
803 if (!NT_STATUS_IS_OK(result)) {
804 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
805 goto done;
808 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
809 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
810 try_ipc_auth = true;
811 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
812 try_ipc_auth = true;
813 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
815 * If we are forcing on SMB signing, then we must
816 * require authentication unless this is a one-way
817 * trust, and we have no stored user/password
819 try_ipc_auth = true;
822 if (IS_DC) {
824 * As AD DC we only use netlogon and lsa
825 * using schannel over an anonymous transport
826 * (ncacn_ip_tcp or ncacn_np).
828 * Currently we always establish the SMB connection,
829 * even if we don't use it, because we later use ncacn_ip_tcp.
831 * As we won't use the SMB connection there's no
832 * need to try kerberos. And NT4 domains expect
833 * an anonymous IPC$ connection anyway.
835 try_ipc_auth = false;
838 if (try_ipc_auth) {
839 result = winbindd_get_trust_credentials(domain,
840 talloc_tos(),
841 false, /* netlogon */
842 true, /* ipc_fallback */
843 &creds);
844 if (!NT_STATUS_IS_OK(result)) {
845 DBG_WARNING("winbindd_get_trust_credentials(%s) "
846 "failed: %s\n",
847 domain->name,
848 nt_errstr(result));
849 goto done;
851 } else {
853 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
854 * would try and authentication with our machine
855 * account password and fail. This is very rare in
856 * the modern world however
858 creds = cli_credentials_init_anon(talloc_tos());
859 if (creds == NULL) {
860 result = NT_STATUS_NO_MEMORY;
861 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
862 domain->name, nt_errstr(result)));
863 goto done;
867 machine_principal = cli_credentials_get_principal(creds,
868 talloc_tos());
869 machine_realm = cli_credentials_get_realm(creds);
870 machine_account = cli_credentials_get_username(creds);
871 machine_domain = cli_credentials_get_domain(creds);
873 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
874 "[%s] and realm [%s]\n",
875 controller, domain->name, domain->alt_name,
876 machine_domain, machine_account,
877 machine_principal, machine_realm));
879 if (cli_credentials_is_anonymous(creds)) {
880 goto anon_fallback;
883 winbindd_set_locator_kdc_envs(domain);
885 result = cli_session_setup_creds(*cli, creds);
886 if (NT_STATUS_IS_OK(result)) {
887 goto session_setup_done;
890 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
891 controller,
892 cli_credentials_get_unparsed_name(creds, talloc_tos()),
893 nt_errstr(result)));
896 * If we are not going to validate the connection
897 * with SMB signing, then allow us to fall back to
898 * anonymous
900 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
901 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
902 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
903 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
904 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
905 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
906 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
908 if (!cm_is_ipc_credentials(creds)) {
909 goto ipc_fallback;
912 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
913 goto done;
916 goto anon_fallback;
919 goto done;
921 ipc_fallback:
922 TALLOC_FREE(creds);
923 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
924 if (!NT_STATUS_IS_OK(tmp_status)) {
925 result = tmp_status;
926 goto done;
929 if (cli_credentials_is_anonymous(creds)) {
930 goto anon_fallback;
933 machine_account = cli_credentials_get_username(creds);
934 machine_domain = cli_credentials_get_domain(creds);
936 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
937 "[%s]\\[%s]\n", controller, lp_netbios_name(),
938 machine_domain, machine_account));
940 result = cli_session_setup_creds(*cli, creds);
941 if (NT_STATUS_IS_OK(result)) {
942 goto session_setup_done;
945 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
946 controller,
947 cli_credentials_get_unparsed_name(creds, talloc_tos()),
948 nt_errstr(result)));
951 * If we are not going to validate the connection
952 * with SMB signing, then allow us to fall back to
953 * anonymous
955 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
956 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
957 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
958 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
959 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
960 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
961 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
963 goto anon_fallback;
966 goto done;
968 anon_fallback:
969 TALLOC_FREE(creds);
971 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
972 goto done;
975 /* Fall back to anonymous connection, this might fail later */
976 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
977 "connection for DC %s\n",
978 controller ));
980 result = cli_session_setup_anon(*cli);
981 if (NT_STATUS_IS_OK(result)) {
982 DEBUG(5, ("Connected anonymously\n"));
983 goto session_setup_done;
986 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
987 controller, nt_errstr(result)));
989 /* We can't session setup */
990 goto done;
992 session_setup_done:
993 TALLOC_FREE(creds);
996 * This should be a short term hack until
997 * dynamic re-authentication is implemented.
999 * See Bug 9175 - winbindd doesn't recover from
1000 * NT_STATUS_NETWORK_SESSION_EXPIRED
1002 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1003 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1006 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1007 if (!NT_STATUS_IS_OK(result)) {
1008 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1009 goto done;
1011 tcon_status = result;
1013 /* cache the server name for later connections */
1015 saf_store(domain->name, controller);
1016 if (domain->alt_name) {
1017 saf_store(domain->alt_name, controller);
1020 winbindd_set_locator_kdc_envs(domain);
1022 TALLOC_FREE(mutex);
1023 *retry = False;
1025 result = NT_STATUS_OK;
1027 done:
1028 TALLOC_FREE(mutex);
1029 TALLOC_FREE(creds);
1031 if (NT_STATUS_IS_OK(result)) {
1032 result = tcon_status;
1035 if (!NT_STATUS_IS_OK(result)) {
1036 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1037 controller, nt_errstr(result)));
1038 winbind_add_failed_connection_entry(domain, controller, result);
1039 if ((*cli) != NULL) {
1040 cli_shutdown(*cli);
1041 *cli = NULL;
1045 return result;
1048 /*******************************************************************
1049 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1050 array.
1052 Keeps the list unique by not adding duplicate entries.
1054 @param[in] mem_ctx talloc memory context to allocate from
1055 @param[in] domain_name domain of the DC
1056 @param[in] dcname name of the DC to add to the list
1057 @param[in] pss Internet address and port pair to add to the list
1058 @param[in,out] dcs array of dc_name_ip structures to add to
1059 @param[in,out] num_dcs number of dcs returned in the dcs array
1060 @return true if the list was added to, false otherwise
1061 *******************************************************************/
1063 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1064 const char *dcname, struct sockaddr_storage *pss,
1065 struct dc_name_ip **dcs, int *num)
1067 int i = 0;
1069 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1070 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1071 return False;
1074 /* Make sure there's no duplicates in the list */
1075 for (i=0; i<*num; i++)
1076 if (sockaddr_equal(
1077 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1078 (struct sockaddr *)(void *)pss))
1079 return False;
1081 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1083 if (*dcs == NULL)
1084 return False;
1086 fstrcpy((*dcs)[*num].name, dcname);
1087 (*dcs)[*num].ss = *pss;
1088 *num += 1;
1089 return True;
1092 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1093 struct sockaddr_storage *pss, uint16_t port,
1094 struct sockaddr_storage **addrs, int *num)
1096 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1098 if (*addrs == NULL) {
1099 *num = 0;
1100 return False;
1103 (*addrs)[*num] = *pss;
1104 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1106 *num += 1;
1107 return True;
1110 #ifdef HAVE_ADS
1111 static bool dcip_check_name_ads(const struct winbindd_domain *domain,
1112 struct samba_sockaddr *sa,
1113 uint32_t request_flags,
1114 TALLOC_CTX *mem_ctx,
1115 char **namep)
1117 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1118 char *name = NULL;
1119 ADS_STRUCT *ads = NULL;
1120 ADS_STATUS ads_status;
1121 char addr[INET6_ADDRSTRLEN];
1123 print_sockaddr(addr, sizeof(addr), &sa->u.ss);
1124 D_DEBUG("Trying to figure out the DC name for domain '%s' at IP '%s'.\n",
1125 domain->name,
1126 addr);
1128 ads = ads_init(tmp_ctx,
1129 domain->alt_name,
1130 domain->name,
1131 addr,
1132 ADS_SASL_PLAIN);
1133 if (ads == NULL) {
1134 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1135 goto out;
1137 ads->config.flags |= request_flags;
1138 ads->server.no_fallback = true;
1140 ads_status = ads_connect_cldap_only(ads);
1141 if (!ADS_ERR_OK(ads_status)) {
1142 goto out;
1145 /* We got a cldap packet. */
1146 name = talloc_strdup(tmp_ctx, ads->config.ldap_server_name);
1147 if (name == NULL) {
1148 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1149 goto out;
1151 namecache_store(name, 0x20, 1, sa);
1153 DBG_DEBUG("CLDAP flags = 0x%"PRIx32"\n", ads->config.flags);
1155 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1156 if (ads_closest_dc(ads)) {
1157 char *sitename = sitename_fetch(tmp_ctx,
1158 ads->config.realm);
1160 /* We're going to use this KDC for this realm/domain.
1161 If we are using sites, then force the krb5 libs
1162 to use this KDC. */
1164 create_local_private_krb5_conf_for_domain(domain->alt_name,
1165 domain->name,
1166 sitename,
1167 &sa->u.ss);
1169 TALLOC_FREE(sitename);
1170 } else {
1171 /* use an off site KDC */
1172 create_local_private_krb5_conf_for_domain(domain->alt_name,
1173 domain->name,
1174 NULL,
1175 &sa->u.ss);
1177 winbindd_set_locator_kdc_envs(domain);
1179 /* Ensure we contact this DC also. */
1180 saf_store(domain->name, name);
1181 saf_store(domain->alt_name, name);
1184 D_DEBUG("DC name for domain '%s' at IP '%s' is '%s'\n",
1185 domain->name,
1186 addr,
1187 name);
1188 *namep = talloc_move(mem_ctx, &name);
1190 out:
1191 TALLOC_FREE(tmp_ctx);
1193 return ADS_ERR_OK(ads_status) ? true : false;
1195 #endif
1197 /*******************************************************************
1198 convert an ip to a name
1199 For an AD Domain, it checks the requirements of the request flags.
1200 *******************************************************************/
1202 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1203 const struct winbindd_domain *domain,
1204 struct sockaddr_storage *pss,
1205 char **name, uint32_t request_flags)
1207 struct samba_sockaddr sa = {0};
1208 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1209 NTSTATUS status;
1210 const char *dc_name;
1211 fstring nbtname;
1212 #ifdef HAVE_ADS
1213 bool is_ad_domain = false;
1214 #endif
1215 bool ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
1216 if (!ok) {
1217 return false;
1220 #ifdef HAVE_ADS
1221 /* For active directory servers, try to get the ldap server name.
1222 None of these failures should be considered critical for now */
1224 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1225 is_ad_domain = true;
1226 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1227 is_ad_domain = domain->active_directory;
1230 if (is_ad_domain) {
1231 return dcip_check_name_ads(domain,
1232 &sa,
1233 request_flags,
1234 mem_ctx,
1235 name);
1237 #endif
1240 size_t len = strlen(lp_netbios_name());
1241 char my_acct_name[len+2];
1243 snprintf(my_acct_name,
1244 sizeof(my_acct_name),
1245 "%s$",
1246 lp_netbios_name());
1248 status = nbt_getdc(global_messaging_context(), 10, &sa.u.ss,
1249 domain->name, &domain->sid,
1250 my_acct_name, ACB_WSTRUST,
1251 nt_version, mem_ctx, &nt_version,
1252 &dc_name, NULL);
1254 if (NT_STATUS_IS_OK(status)) {
1255 *name = talloc_strdup(mem_ctx, dc_name);
1256 if (*name == NULL) {
1257 return false;
1259 namecache_store(*name, 0x20, 1, &sa);
1260 return True;
1263 /* try node status request */
1265 if (name_status_find(domain->name, 0x1c, 0x20, &sa.u.ss, nbtname) ) {
1266 namecache_store(nbtname, 0x20, 1, &sa);
1268 if (name != NULL) {
1269 *name = talloc_strdup(mem_ctx, nbtname);
1270 if (*name == NULL) {
1271 return false;
1275 return true;
1277 return False;
1280 /*******************************************************************
1281 Retrieve a list of IP addresses for domain controllers.
1283 The array is sorted in the preferred connection order.
1285 @param[in] mem_ctx talloc memory context to allocate from
1286 @param[in] domain domain to retrieve DCs for
1287 @param[out] dcs array of dcs that will be returned
1288 @param[out] num_dcs number of dcs returned in the dcs array
1289 @return always true
1290 *******************************************************************/
1292 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1293 struct dc_name_ip **dcs, int *num_dcs,
1294 uint32_t request_flags)
1296 fstring dcname;
1297 struct sockaddr_storage ss;
1298 struct samba_sockaddr *sa_list = NULL;
1299 size_t salist_size = 0;
1300 size_t i;
1301 bool is_our_domain;
1302 enum security_types sec = (enum security_types)lp_security();
1304 is_our_domain = strequal(domain->name, lp_workgroup());
1306 /* If not our domain, get the preferred DC, by asking our primary DC */
1307 if ( !is_our_domain
1308 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1309 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1310 num_dcs) )
1312 char addr[INET6_ADDRSTRLEN];
1313 print_sockaddr(addr, sizeof(addr), &ss);
1314 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1315 dcname, addr));
1316 return True;
1319 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1320 char *sitename = NULL;
1322 /* We need to make sure we know the local site before
1323 doing any DNS queries, as this will restrict the
1324 get_sorted_dc_list() call below to only fetching
1325 DNS records for the correct site. */
1327 /* Find any DC to get the site record.
1328 We deliberately don't care about the
1329 return here. */
1331 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1333 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1334 if (sitename) {
1336 /* Do the site-specific AD dns lookup first. */
1337 (void)get_sorted_dc_list(mem_ctx,
1338 domain->alt_name,
1339 sitename,
1340 &sa_list,
1341 &salist_size,
1342 true);
1344 /* Add ips to the DC array. We don't look up the name
1345 of the DC in this function, but we fill in the char*
1346 of the ip now to make the failed connection cache
1347 work */
1348 for ( i=0; i<salist_size; i++ ) {
1349 char addr[INET6_ADDRSTRLEN];
1350 print_sockaddr(addr, sizeof(addr),
1351 &sa_list[i].u.ss);
1352 add_one_dc_unique(mem_ctx,
1353 domain->name,
1354 addr,
1355 &sa_list[i].u.ss,
1356 dcs,
1357 num_dcs);
1360 TALLOC_FREE(sa_list);
1361 TALLOC_FREE(sitename);
1362 salist_size = 0;
1365 /* Now we add DCs from the main AD DNS lookup. */
1366 (void)get_sorted_dc_list(mem_ctx,
1367 domain->alt_name,
1368 NULL,
1369 &sa_list,
1370 &salist_size,
1371 true);
1373 for ( i=0; i<salist_size; i++ ) {
1374 char addr[INET6_ADDRSTRLEN];
1375 print_sockaddr(addr, sizeof(addr),
1376 &sa_list[i].u.ss);
1377 add_one_dc_unique(mem_ctx,
1378 domain->name,
1379 addr,
1380 &sa_list[i].u.ss,
1381 dcs,
1382 num_dcs);
1385 TALLOC_FREE(sa_list);
1386 salist_size = 0;
1389 /* Try standard netbios queries if no ADS and fall back to DNS queries
1390 * if alt_name is available */
1391 if (*num_dcs == 0) {
1392 (void)get_sorted_dc_list(mem_ctx,
1393 domain->name,
1394 NULL,
1395 &sa_list,
1396 &salist_size,
1397 false);
1398 if (salist_size == 0) {
1399 if (domain->alt_name != NULL) {
1400 (void)get_sorted_dc_list(mem_ctx,
1401 domain->alt_name,
1402 NULL,
1403 &sa_list,
1404 &salist_size,
1405 true);
1409 for ( i=0; i<salist_size; i++ ) {
1410 char addr[INET6_ADDRSTRLEN];
1411 print_sockaddr(addr, sizeof(addr),
1412 &sa_list[i].u.ss);
1413 add_one_dc_unique(mem_ctx,
1414 domain->name,
1415 addr,
1416 &sa_list[i].u.ss,
1417 dcs,
1418 num_dcs);
1421 TALLOC_FREE(sa_list);
1422 salist_size = 0;
1425 return True;
1428 static bool connect_preferred_dc(TALLOC_CTX *mem_ctx,
1429 struct winbindd_domain *domain,
1430 uint32_t request_flags,
1431 int *fd)
1433 char *saf_servername = NULL;
1434 NTSTATUS status;
1435 bool ok;
1438 * We have to check the server affinity cache here since later we select
1439 * a DC based on response time and not preference.
1441 if (domain->force_dc) {
1442 saf_servername = domain->dcname;
1443 } else {
1444 saf_servername = saf_fetch(mem_ctx, domain->name);
1448 * Check the negative connection cache before talking to it. It going
1449 * down may have triggered the reconnection.
1451 if (saf_servername != NULL) {
1452 status = check_negative_conn_cache(domain->name,
1453 saf_servername);
1454 if (!NT_STATUS_IS_OK(status)) {
1455 saf_servername = NULL;
1459 if (saf_servername != NULL) {
1460 DBG_DEBUG("saf_servername is '%s' for domain %s\n",
1461 saf_servername, domain->name);
1463 /* convert an ip address to a name */
1464 if (is_ipaddress(saf_servername)) {
1465 ok = interpret_string_addr(&domain->dcaddr,
1466 saf_servername,
1467 AI_NUMERICHOST);
1468 if (!ok) {
1469 return false;
1471 } else {
1472 ok = resolve_name(saf_servername,
1473 &domain->dcaddr,
1474 0x20,
1475 true);
1476 if (!ok) {
1477 goto fail;
1481 TALLOC_FREE(domain->dcname);
1482 ok = dcip_check_name(domain,
1483 domain,
1484 &domain->dcaddr,
1485 &domain->dcname,
1486 request_flags);
1487 if (!ok) {
1488 goto fail;
1492 if (domain->dcname == NULL) {
1493 return false;
1496 status = check_negative_conn_cache(domain->name, domain->dcname);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 return false;
1501 status = smbsock_connect(&domain->dcaddr, 0,
1502 NULL, -1, NULL, -1,
1503 fd, NULL, 10);
1504 if (!NT_STATUS_IS_OK(status)) {
1505 winbind_add_failed_connection_entry(domain,
1506 domain->dcname,
1507 NT_STATUS_UNSUCCESSFUL);
1508 return false;
1510 return true;
1512 fail:
1513 winbind_add_failed_connection_entry(domain,
1514 saf_servername,
1515 NT_STATUS_UNSUCCESSFUL);
1516 return false;
1520 /*******************************************************************
1521 Find and make a connection to a DC in the given domain.
1523 @param[in] mem_ctx talloc memory context to allocate from
1524 @param[in] domain domain to find a dc in
1525 @param[out] fd fd of the open socket connected to the newly found dc
1526 @return true when a DC connection is made, false otherwise
1527 *******************************************************************/
1529 static bool find_dc(TALLOC_CTX *mem_ctx,
1530 struct winbindd_domain *domain,
1531 uint32_t request_flags,
1532 int *fd)
1534 struct dc_name_ip *dcs = NULL;
1535 int num_dcs = 0;
1537 const char **dcnames = NULL;
1538 size_t num_dcnames = 0;
1540 struct sockaddr_storage *addrs = NULL;
1541 int num_addrs = 0;
1543 int i;
1544 size_t fd_index;
1546 NTSTATUS status;
1547 bool ok;
1549 *fd = -1;
1551 D_NOTICE("First try to connect to the closest DC (using server "
1552 "affinity cache). If this fails, try to lookup the DC using "
1553 "DNS afterwards.\n");
1554 ok = connect_preferred_dc(mem_ctx, domain, request_flags, fd);
1555 if (ok) {
1556 return true;
1559 if (domain->force_dc) {
1560 return false;
1563 again:
1564 D_DEBUG("Retrieving a list of IP addresses for DCs.\n");
1565 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1566 return False;
1568 D_DEBUG("Retrieved IP addresses for %d DCs.\n", num_dcs);
1569 for (i=0; i<num_dcs; i++) {
1571 if (!add_string_to_array(mem_ctx, dcs[i].name,
1572 &dcnames, &num_dcnames)) {
1573 return False;
1575 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1576 &addrs, &num_addrs)) {
1577 return False;
1581 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1582 return False;
1584 if ((addrs == NULL) || (dcnames == NULL))
1585 return False;
1587 D_DEBUG("Trying to establish a connection to one of the %d DCs "
1588 "(timeout of 10 sec for each DC).\n",
1589 num_dcs);
1590 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1591 num_addrs, 0, 10, fd, &fd_index, NULL);
1592 if (!NT_STATUS_IS_OK(status)) {
1593 for (i=0; i<num_dcs; i++) {
1594 char ab[INET6_ADDRSTRLEN];
1595 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1596 DBG_DEBUG("smbsock_any_connect failed for "
1597 "domain %s address %s. Error was %s\n",
1598 domain->name, ab, nt_errstr(status));
1599 winbind_add_failed_connection_entry(domain,
1600 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1602 return False;
1604 D_NOTICE("Successfully connected to DC '%s'.\n", dcs[fd_index].name);
1606 domain->dcaddr = addrs[fd_index];
1608 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1609 /* Ok, we've got a name for the DC */
1610 TALLOC_FREE(domain->dcname);
1611 domain->dcname = talloc_strdup(domain, dcnames[fd_index]);
1612 if (domain->dcname == NULL) {
1613 return false;
1615 return true;
1618 /* Try to figure out the name */
1619 TALLOC_FREE(domain->dcname);
1620 ok = dcip_check_name(domain,
1621 domain,
1622 &domain->dcaddr,
1623 &domain->dcname,
1624 request_flags);
1625 if (ok) {
1626 return true;
1629 /* We can not continue without the DC's name */
1630 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1631 NT_STATUS_UNSUCCESSFUL);
1633 /* Throw away all arrays as we're doing this again. */
1634 TALLOC_FREE(dcs);
1635 num_dcs = 0;
1637 TALLOC_FREE(dcnames);
1638 num_dcnames = 0;
1640 TALLOC_FREE(addrs);
1641 num_addrs = 0;
1643 if (*fd != -1) {
1644 close(*fd);
1645 *fd = -1;
1649 * This should not be an infinite loop, since get_dcs() will not return
1650 * the DC added to the negative connection cache in the above
1651 * winbind_add_failed_connection_entry() call.
1653 goto again;
1656 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1658 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1659 domain_name);
1662 static void store_current_dc_in_gencache(const char *domain_name,
1663 const char *dc_name,
1664 struct cli_state *cli)
1666 char addr[INET6_ADDRSTRLEN];
1667 char *key = NULL;
1668 char *value = NULL;
1670 if (!cli_state_is_connected(cli)) {
1671 return;
1674 print_sockaddr(addr, sizeof(addr),
1675 smbXcli_conn_remote_sockaddr(cli->conn));
1677 key = current_dc_key(talloc_tos(), domain_name);
1678 if (key == NULL) {
1679 goto done;
1682 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1683 if (value == NULL) {
1684 goto done;
1687 gencache_set(key, value, 0x7fffffff);
1688 done:
1689 TALLOC_FREE(value);
1690 TALLOC_FREE(key);
1693 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1694 const char *domain_name,
1695 char **p_dc_name, char **p_dc_ip)
1697 char *key, *p;
1698 char *value = NULL;
1699 bool ret = false;
1700 char *dc_name = NULL;
1701 char *dc_ip = NULL;
1703 key = current_dc_key(talloc_tos(), domain_name);
1704 if (key == NULL) {
1705 goto done;
1707 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1708 goto done;
1710 p = strchr(value, ' ');
1711 if (p == NULL) {
1712 goto done;
1714 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1715 if (dc_ip == NULL) {
1716 goto done;
1718 dc_name = talloc_strdup(mem_ctx, p+1);
1719 if (dc_name == NULL) {
1720 goto done;
1723 if (p_dc_ip != NULL) {
1724 *p_dc_ip = dc_ip;
1725 dc_ip = NULL;
1727 if (p_dc_name != NULL) {
1728 *p_dc_name = dc_name;
1729 dc_name = NULL;
1731 ret = true;
1732 done:
1733 TALLOC_FREE(dc_name);
1734 TALLOC_FREE(dc_ip);
1735 TALLOC_FREE(key);
1736 TALLOC_FREE(value);
1737 return ret;
1740 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1741 const struct ndr_interface_table *table,
1742 struct rpc_pipe_client **ret_pipe)
1744 struct rpc_pipe_client *cli = NULL;
1745 const struct auth_session_info *session_info = NULL;
1746 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1749 session_info = get_session_info_system();
1750 SMB_ASSERT(session_info != NULL);
1752 status = rpc_pipe_open_local_np(
1753 mem_ctx, table, NULL, NULL, NULL, NULL, session_info, &cli);
1754 if (!NT_STATUS_IS_OK(status)) {
1755 return status;
1758 if (ret_pipe) {
1759 *ret_pipe = cli;
1762 return NT_STATUS_OK;
1765 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1766 struct winbindd_cm_conn *new_conn,
1767 bool need_rw_dc)
1769 TALLOC_CTX *mem_ctx;
1770 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1771 int retries;
1772 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1773 int fd = -1;
1774 bool retry = false;
1775 bool seal_pipes = true;
1777 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1778 set_domain_offline(domain);
1779 return NT_STATUS_NO_MEMORY;
1782 D_NOTICE("Creating connection to domain controller. This is a start of "
1783 "a new connection or a DC failover. The failover only happens "
1784 "if the domain has more than one DC. We will try to connect 3 "
1785 "times at most.\n");
1786 for (retries = 0; retries < 3; retries++) {
1787 bool found_dc;
1789 D_DEBUG("Attempt %d/3: DC '%s' of domain '%s'.\n",
1790 retries,
1791 domain->dcname ? domain->dcname : "",
1792 domain->name);
1794 found_dc = find_dc(mem_ctx, domain, request_flags, &fd);
1795 if (!found_dc) {
1796 /* This is the one place where we will
1797 set the global winbindd offline state
1798 to true, if a "WINBINDD_OFFLINE" entry
1799 is found in the winbindd cache. */
1800 set_global_winbindd_state_offline();
1801 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1802 break;
1805 new_conn->cli = NULL;
1807 result = cm_prepare_connection(domain, fd, domain->dcname,
1808 &new_conn->cli, &retry);
1809 if (NT_STATUS_IS_OK(result)) {
1810 break;
1812 if (!retry) {
1813 break;
1817 if (!NT_STATUS_IS_OK(result)) {
1818 /* Ensure we setup the retry handler. */
1819 set_domain_offline(domain);
1820 goto out;
1823 winbindd_set_locator_kdc_envs(domain);
1825 if (domain->online == False) {
1826 /* We're changing state from offline to online. */
1827 set_global_winbindd_state_online();
1829 set_domain_online(domain);
1832 * Much as I hate global state, this seems to be the point
1833 * where we can be certain that we have a proper connection to
1834 * a DC. wbinfo --dc-info needs that information, store it in
1835 * gencache with a looong timeout. This will need revisiting
1836 * once we start to connect to multiple DCs, wbcDcInfo is
1837 * already prepared for that.
1839 store_current_dc_in_gencache(domain->name, domain->dcname,
1840 new_conn->cli);
1842 seal_pipes = lp_winbind_sealed_pipes();
1843 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1844 domain->name,
1845 seal_pipes);
1847 if (seal_pipes) {
1848 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1849 } else {
1850 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1853 out:
1854 talloc_destroy(mem_ctx);
1855 return result;
1858 /* Close down all open pipes on a connection. */
1860 void invalidate_cm_connection(struct winbindd_domain *domain)
1862 NTSTATUS result;
1863 struct winbindd_cm_conn *conn = &domain->conn;
1865 domain->sequence_number = DOM_SEQUENCE_NONE;
1866 domain->last_seq_check = 0;
1867 domain->last_status = NT_STATUS_SERVER_DISABLED;
1869 /* We're closing down a possibly dead
1870 connection. Don't have impossibly long (10s) timeouts. */
1872 if (conn->cli) {
1873 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1876 if (conn->samr_pipe != NULL) {
1877 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1878 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1879 talloc_tos(),
1880 &conn->sam_connect_handle,
1881 &result);
1883 TALLOC_FREE(conn->samr_pipe);
1884 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1885 if (conn->cli) {
1886 cli_set_timeout(conn->cli, 500);
1890 if (conn->lsa_pipe != NULL) {
1891 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1892 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1893 talloc_tos(),
1894 &conn->lsa_policy,
1895 &result);
1897 TALLOC_FREE(conn->lsa_pipe);
1898 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1899 if (conn->cli) {
1900 cli_set_timeout(conn->cli, 500);
1904 if (conn->lsa_pipe_tcp != NULL) {
1905 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1906 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1907 talloc_tos(),
1908 &conn->lsa_policy,
1909 &result);
1911 TALLOC_FREE(conn->lsa_pipe_tcp);
1912 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1913 if (conn->cli) {
1914 cli_set_timeout(conn->cli, 500);
1918 if (conn->netlogon_pipe != NULL) {
1919 TALLOC_FREE(conn->netlogon_pipe);
1920 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1921 if (conn->cli) {
1922 cli_set_timeout(conn->cli, 500);
1926 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1927 TALLOC_FREE(conn->netlogon_creds_ctx);
1929 if (conn->cli) {
1930 cli_shutdown(conn->cli);
1933 conn->cli = NULL;
1936 void close_conns_after_fork(void)
1938 struct winbindd_domain *domain;
1939 struct winbindd_cli_state *cli_state;
1941 for (domain = domain_list(); domain; domain = domain->next) {
1943 * first close the low level SMB TCP connection
1944 * so that we don't generate any SMBclose
1945 * requests in invalidate_cm_connection()
1947 if (cli_state_is_connected(domain->conn.cli)) {
1948 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1951 invalidate_cm_connection(domain);
1954 for (cli_state = winbindd_client_list();
1955 cli_state != NULL;
1956 cli_state = cli_state->next) {
1957 if (cli_state->sock >= 0) {
1958 close(cli_state->sock);
1959 cli_state->sock = -1;
1964 static bool connection_ok(struct winbindd_domain *domain)
1966 bool ok;
1968 ok = cli_state_is_connected(domain->conn.cli);
1969 if (!ok) {
1970 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1971 domain->dcname, domain->name));
1972 return False;
1975 if (!domain->online) {
1976 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1977 return False;
1980 return True;
1983 /* Initialize a new connection up to the RPC BIND.
1984 Bypass online status check so always does network calls. */
1986 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
1988 NTSTATUS result;
1989 bool skip_connection = domain->internal;
1990 if (need_rw_dc && domain->rodc) {
1991 skip_connection = false;
1994 /* Internal connections never use the network. */
1995 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
1996 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1999 /* Still ask the internal LSA and SAMR server about the local domain */
2000 if (skip_connection || connection_ok(domain)) {
2001 if (!domain->initialized) {
2002 set_dc_type_and_flags(domain);
2004 return NT_STATUS_OK;
2007 invalidate_cm_connection(domain);
2009 if (!domain->primary && !domain->initialized) {
2011 * Before we connect to a trust, work out if it is an
2012 * AD domain by asking our own domain.
2014 set_dc_type_and_flags_trustinfo(domain);
2017 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2019 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2020 set_dc_type_and_flags(domain);
2023 return result;
2026 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2028 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2029 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2032 SMB_ASSERT(wb_child_domain() || idmap_child());
2034 return init_dc_connection_network(domain, need_rw_dc);
2037 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2039 NTSTATUS status;
2041 status = init_dc_connection(domain, need_rw_dc);
2042 if (!NT_STATUS_IS_OK(status)) {
2043 return status;
2046 if (!domain->internal && domain->conn.cli == NULL) {
2047 /* happens for trusted domains without inbound trust */
2048 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2051 return NT_STATUS_OK;
2054 /******************************************************************************
2055 Set the trust flags (direction and forest location) for a domain
2056 ******************************************************************************/
2058 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2060 struct winbindd_domain *our_domain;
2061 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2062 WERROR werr;
2063 struct netr_DomainTrustList trusts;
2064 int i;
2065 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2066 NETR_TRUST_FLAG_OUTBOUND |
2067 NETR_TRUST_FLAG_INBOUND);
2068 struct rpc_pipe_client *cli;
2069 TALLOC_CTX *mem_ctx = NULL;
2070 struct dcerpc_binding_handle *b;
2072 if (IS_DC) {
2074 * On a DC we loaded all trusts
2075 * from configuration and never learn
2076 * new domains.
2078 return true;
2081 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2083 /* Our primary domain doesn't need to worry about trust flags.
2084 Force it to go through the network setup */
2085 if ( domain->primary ) {
2086 return False;
2089 mem_ctx = talloc_stackframe();
2090 our_domain = find_our_domain();
2091 if (our_domain->internal) {
2092 result = init_dc_connection(our_domain, false);
2093 if (!NT_STATUS_IS_OK(result)) {
2094 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2095 "Not able to make a connection to our domain: %s\n",
2096 nt_errstr(result)));
2097 TALLOC_FREE(mem_ctx);
2098 return false;
2102 /* This won't work unless our domain is AD */
2103 if ( !our_domain->active_directory ) {
2104 TALLOC_FREE(mem_ctx);
2105 return False;
2108 if (our_domain->internal) {
2109 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2110 } else if (!connection_ok(our_domain)) {
2111 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2112 "No connection to our domain!\n"));
2113 TALLOC_FREE(mem_ctx);
2114 return False;
2115 } else {
2116 result = cm_connect_netlogon(our_domain, &cli);
2119 if (!NT_STATUS_IS_OK(result)) {
2120 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2121 "a connection to %s for PIPE_NETLOGON (%s)\n",
2122 domain->name, nt_errstr(result)));
2123 TALLOC_FREE(mem_ctx);
2124 return False;
2126 b = cli->binding_handle;
2128 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2129 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2130 cli->desthost,
2131 flags,
2132 &trusts,
2133 &werr);
2134 if (!NT_STATUS_IS_OK(result)) {
2135 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2136 "failed to query trusted domain list: %s\n",
2137 nt_errstr(result)));
2138 TALLOC_FREE(mem_ctx);
2139 return false;
2141 if (!W_ERROR_IS_OK(werr)) {
2142 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2143 "failed to query trusted domain list: %s\n",
2144 win_errstr(werr)));
2145 TALLOC_FREE(mem_ctx);
2146 return false;
2149 /* Now find the domain name and get the flags */
2151 for ( i=0; i<trusts.count; i++ ) {
2152 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2153 domain->domain_flags = trusts.array[i].trust_flags;
2154 domain->domain_type = trusts.array[i].trust_type;
2155 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2157 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2158 domain->active_directory = True;
2160 /* This flag is only set if the domain is *our*
2161 primary domain and the primary domain is in
2162 native mode */
2164 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2166 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2167 "native mode.\n", domain->name,
2168 domain->native_mode ? "" : "NOT "));
2170 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2171 "running active directory.\n", domain->name,
2172 domain->active_directory ? "" : "NOT "));
2174 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2176 domain->initialized = True;
2178 break;
2182 TALLOC_FREE(mem_ctx);
2184 return domain->initialized;
2187 /******************************************************************************
2188 We can 'sense' certain things about the DC by it's replies to certain
2189 questions.
2191 This tells us if this particular remote server is Active Directory, and if it
2192 is native mode.
2193 ******************************************************************************/
2195 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2197 NTSTATUS status, result;
2198 NTSTATUS close_status = NT_STATUS_UNSUCCESSFUL;
2199 WERROR werr;
2200 TALLOC_CTX *mem_ctx = NULL;
2201 struct rpc_pipe_client *cli = NULL;
2202 struct policy_handle pol = { .handle_type = 0 };
2203 union dssetup_DsRoleInfo info;
2204 union lsa_PolicyInformation *lsa_info = NULL;
2205 union lsa_revision_info out_revision_info = {
2206 .info1 = {
2207 .revision = 0,
2210 uint32_t out_version = 0;
2212 if (!domain->internal && !connection_ok(domain)) {
2213 return;
2216 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2217 domain->name);
2218 if (!mem_ctx) {
2219 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2220 return;
2223 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2225 if (domain->internal) {
2226 status = wb_open_internal_pipe(mem_ctx,
2227 &ndr_table_dssetup,
2228 &cli);
2229 } else {
2230 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2231 &ndr_table_dssetup,
2232 &cli);
2235 if (!NT_STATUS_IS_OK(status)) {
2236 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2237 "PI_DSSETUP on domain %s: (%s)\n",
2238 domain->name, nt_errstr(status)));
2240 /* if this is just a non-AD domain we need to continue
2241 * identifying so that we can in the end return with
2242 * domain->initialized = True - gd */
2244 goto no_dssetup;
2247 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2248 DS_ROLE_BASIC_INFORMATION,
2249 &info,
2250 &werr);
2251 TALLOC_FREE(cli);
2253 if (NT_STATUS_IS_OK(status)) {
2254 result = werror_to_ntstatus(werr);
2256 if (!NT_STATUS_IS_OK(status)) {
2257 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2258 "on domain %s failed: (%s)\n",
2259 domain->name, nt_errstr(status)));
2261 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2262 * every opcode on the DSSETUP pipe, continue with
2263 * no_dssetup mode here as well to get domain->initialized
2264 * set - gd */
2266 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2267 goto no_dssetup;
2270 TALLOC_FREE(mem_ctx);
2271 return;
2274 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2275 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2276 domain->native_mode = True;
2277 } else {
2278 domain->native_mode = False;
2281 no_dssetup:
2282 if (domain->internal) {
2283 status = wb_open_internal_pipe(mem_ctx,
2284 &ndr_table_lsarpc,
2285 &cli);
2286 } else {
2287 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2288 &ndr_table_lsarpc, &cli);
2290 if (!NT_STATUS_IS_OK(status)) {
2291 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2292 "PI_LSARPC on domain %s: (%s)\n",
2293 domain->name, nt_errstr(status)));
2294 TALLOC_FREE(cli);
2295 TALLOC_FREE(mem_ctx);
2296 return;
2299 status = dcerpc_lsa_open_policy_fallback(cli->binding_handle,
2300 mem_ctx,
2301 cli->srv_name_slash,
2302 true,
2303 SEC_FLAG_MAXIMUM_ALLOWED,
2304 &out_version,
2305 &out_revision_info,
2306 &pol,
2307 &result);
2309 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2310 /* This particular query is exactly what Win2k clients use
2311 to determine that the DC is active directory */
2312 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2313 &pol,
2314 LSA_POLICY_INFO_DNS,
2315 &lsa_info,
2316 &result);
2320 * If the status and result will not be OK we will fallback to
2321 * OpenPolicy.
2323 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2324 domain->active_directory = True;
2326 if (lsa_info->dns.name.string) {
2327 if (!strequal(domain->name, lsa_info->dns.name.string))
2329 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2330 "for domain %s claimed it was a DC "
2331 "for domain %s, refusing to "
2332 "initialize\n",
2333 domain->name,
2334 lsa_info->dns.name.string));
2335 TALLOC_FREE(cli);
2336 TALLOC_FREE(mem_ctx);
2337 return;
2339 talloc_free(domain->name);
2340 domain->name = talloc_strdup(domain,
2341 lsa_info->dns.name.string);
2342 if (domain->name == NULL) {
2343 goto done;
2347 if (lsa_info->dns.dns_domain.string) {
2348 if (domain->alt_name != NULL &&
2349 !strequal(domain->alt_name,
2350 lsa_info->dns.dns_domain.string))
2352 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2353 "for domain %s (%s) claimed it was "
2354 "a DC for domain %s, refusing to "
2355 "initialize\n",
2356 domain->alt_name, domain->name,
2357 lsa_info->dns.dns_domain.string));
2358 TALLOC_FREE(cli);
2359 TALLOC_FREE(mem_ctx);
2360 return;
2362 talloc_free(domain->alt_name);
2363 domain->alt_name =
2364 talloc_strdup(domain,
2365 lsa_info->dns.dns_domain.string);
2366 if (domain->alt_name == NULL) {
2367 goto done;
2371 /* See if we can set some domain trust flags about
2372 ourself */
2374 if (lsa_info->dns.dns_forest.string) {
2375 talloc_free(domain->forest_name);
2376 domain->forest_name =
2377 talloc_strdup(domain,
2378 lsa_info->dns.dns_forest.string);
2379 if (domain->forest_name == NULL) {
2380 goto done;
2383 if (strequal(domain->forest_name, domain->alt_name)) {
2384 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2388 if (lsa_info->dns.sid) {
2389 if (!is_null_sid(&domain->sid) &&
2390 !dom_sid_equal(&domain->sid,
2391 lsa_info->dns.sid))
2393 struct dom_sid_buf buf1, buf2;
2394 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2395 "for domain %s (%s) claimed it was "
2396 "a DC for domain %s, refusing to "
2397 "initialize\n",
2398 dom_sid_str_buf(&domain->sid, &buf1),
2399 domain->name,
2400 dom_sid_str_buf(lsa_info->dns.sid,
2401 &buf2)));
2402 TALLOC_FREE(cli);
2403 TALLOC_FREE(mem_ctx);
2404 return;
2406 sid_copy(&domain->sid, lsa_info->dns.sid);
2408 } else {
2409 domain->active_directory = False;
2411 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2412 SEC_FLAG_MAXIMUM_ALLOWED,
2413 &pol);
2415 if (!NT_STATUS_IS_OK(status)) {
2416 goto done;
2419 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2420 &pol,
2421 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2422 &lsa_info,
2423 &result);
2424 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2426 if (lsa_info->account_domain.name.string) {
2427 if (!strequal(domain->name,
2428 lsa_info->account_domain.name.string))
2430 DEBUG(1,
2431 ("set_dc_type_and_flags_connect: "
2432 "DC for domain %s claimed it was"
2433 " a DC for domain %s, refusing "
2434 "to initialize\n", domain->name,
2435 lsa_info->
2436 account_domain.name.string));
2437 TALLOC_FREE(cli);
2438 TALLOC_FREE(mem_ctx);
2439 return;
2441 talloc_free(domain->name);
2442 domain->name =
2443 talloc_strdup(domain,
2444 lsa_info->account_domain.name.string);
2447 if (lsa_info->account_domain.sid) {
2448 if (!is_null_sid(&domain->sid) &&
2449 !dom_sid_equal(&domain->sid,
2450 lsa_info->account_domain.sid))
2452 struct dom_sid_buf buf1, buf2;
2453 DEBUG(1,
2454 ("set_dc_type_and_flags_connect: "
2455 "DC for domain %s (%s) claimed "
2456 "it was a DC for domain %s, "
2457 "refusing to initialize\n",
2458 dom_sid_str_buf(
2459 &domain->sid, &buf1),
2460 domain->name,
2461 dom_sid_str_buf(
2462 lsa_info->account_domain.sid,
2463 &buf2)));
2464 TALLOC_FREE(cli);
2465 TALLOC_FREE(mem_ctx);
2466 return;
2468 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2472 done:
2473 if (is_valid_policy_hnd(&pol)) {
2474 dcerpc_lsa_Close(cli->binding_handle,
2475 mem_ctx,
2476 &pol,
2477 &close_status);
2480 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2481 domain->name, domain->native_mode ? "" : "NOT "));
2483 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2484 domain->name, domain->active_directory ? "" : "NOT "));
2486 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2488 TALLOC_FREE(cli);
2490 TALLOC_FREE(mem_ctx);
2492 domain->initialized = True;
2495 /**********************************************************************
2496 Set the domain_flags (trust attributes, domain operating modes, etc...
2497 ***********************************************************************/
2499 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2501 if (IS_DC) {
2503 * On a DC we loaded all trusts
2504 * from configuration and never learn
2505 * new domains.
2507 return;
2510 /* we always have to contact our primary domain */
2512 if ( domain->primary || domain->internal) {
2513 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2514 "primary or internal domain\n"));
2515 set_dc_type_and_flags_connect( domain );
2516 return;
2519 /* Use our DC to get the information if possible */
2521 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2522 /* Otherwise, fallback to contacting the
2523 domain directly */
2524 set_dc_type_and_flags_connect( domain );
2527 return;
2532 /**********************************************************************
2533 ***********************************************************************/
2535 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2536 struct netlogon_creds_cli_context **ppdc)
2538 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2539 struct rpc_pipe_client *netlogon_pipe;
2541 *ppdc = NULL;
2543 if ((!IS_DC) && (!domain->primary)) {
2544 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2547 if (domain->conn.netlogon_creds_ctx != NULL) {
2548 *ppdc = domain->conn.netlogon_creds_ctx;
2549 return NT_STATUS_OK;
2552 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2553 if (!NT_STATUS_IS_OK(result)) {
2554 return result;
2557 return NT_STATUS_OK;
2560 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2561 bool need_rw_dc,
2562 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2564 struct winbindd_cm_conn *conn;
2565 NTSTATUS status, result;
2566 struct netlogon_creds_cli_context *p_creds;
2567 struct cli_credentials *creds = NULL;
2568 bool retry = false; /* allow one retry attempt for expired session */
2569 const char *remote_name = NULL;
2570 const struct sockaddr_storage *remote_sockaddr = NULL;
2571 bool sealed_pipes = true;
2572 bool strong_key = true;
2574 if (sid_check_is_our_sam(&domain->sid)) {
2575 if (domain->rodc == false || need_rw_dc == false) {
2576 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2580 if (IS_AD_DC) {
2582 * In theory we should not use SAMR within
2583 * winbindd at all, but that's a larger task to
2584 * remove this and avoid breaking existing
2585 * setups.
2587 * At least as AD DC we have the restriction
2588 * to avoid SAMR against trusted domains,
2589 * as there're no existing setups.
2591 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2594 retry:
2595 status = init_dc_connection_rpc(domain, need_rw_dc);
2596 if (!NT_STATUS_IS_OK(status)) {
2597 return status;
2600 conn = &domain->conn;
2602 if (rpccli_is_connected(conn->samr_pipe)) {
2603 goto done;
2606 TALLOC_FREE(conn->samr_pipe);
2609 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2610 * sign and sealed pipe using the machine account password by
2611 * preference. If we can't - try schannel, if that fails, try
2612 * anonymous.
2615 result = winbindd_get_trust_credentials(domain,
2616 talloc_tos(),
2617 false, /* netlogon */
2618 true, /* ipc_fallback */
2619 &creds);
2620 if (!NT_STATUS_IS_OK(result)) {
2621 DEBUG(10, ("cm_connect_sam: No user available for "
2622 "domain %s, trying schannel\n", domain->name));
2623 goto schannel;
2626 if (cli_credentials_is_anonymous(creds)) {
2627 goto anonymous;
2630 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2631 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2634 * We have an authenticated connection. Use a SPNEGO
2635 * authenticated SAMR pipe with sign & seal.
2637 status = cli_rpc_pipe_open_with_creds(conn->cli,
2638 &ndr_table_samr,
2639 NCACN_NP,
2640 DCERPC_AUTH_TYPE_SPNEGO,
2641 conn->auth_level,
2642 remote_name,
2643 remote_sockaddr,
2644 creds,
2645 &conn->samr_pipe);
2647 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2648 && !retry) {
2649 invalidate_cm_connection(domain);
2650 retry = true;
2651 goto retry;
2654 if (!NT_STATUS_IS_OK(status)) {
2655 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2656 "pipe for domain %s using NTLMSSP "
2657 "authenticated pipe: user %s. Error was "
2658 "%s\n", domain->name,
2659 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2660 nt_errstr(status)));
2661 goto schannel;
2664 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2665 "domain %s using NTLMSSP authenticated "
2666 "pipe: user %s\n", domain->name,
2667 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2669 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2670 conn->samr_pipe->desthost,
2671 SEC_FLAG_MAXIMUM_ALLOWED,
2672 &conn->sam_connect_handle,
2673 &result);
2675 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2676 invalidate_cm_connection(domain);
2677 TALLOC_FREE(conn->samr_pipe);
2678 retry = true;
2679 goto retry;
2682 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2683 goto open_domain;
2685 if (NT_STATUS_IS_OK(status)) {
2686 status = result;
2689 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2690 "failed for domain %s, error was %s. Trying schannel\n",
2691 domain->name, nt_errstr(status) ));
2692 TALLOC_FREE(conn->samr_pipe);
2694 schannel:
2696 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2698 status = cm_get_schannel_creds(domain, &p_creds);
2699 if (!NT_STATUS_IS_OK(status)) {
2700 /* If this call fails - conn->cli can now be NULL ! */
2701 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2702 "for domain %s (error %s), trying anon\n",
2703 domain->name,
2704 nt_errstr(status) ));
2705 goto anonymous;
2707 TALLOC_FREE(creds);
2708 status = cli_rpc_pipe_open_schannel_with_creds(
2709 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2710 remote_name,
2711 remote_sockaddr,
2712 &conn->samr_pipe);
2714 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2715 && !retry) {
2716 invalidate_cm_connection(domain);
2717 retry = true;
2718 goto retry;
2721 if (!NT_STATUS_IS_OK(status)) {
2722 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2723 "domain %s using schannel. Error was %s\n",
2724 domain->name, nt_errstr(status) ));
2725 goto anonymous;
2727 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2728 "schannel.\n", domain->name ));
2730 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2731 conn->samr_pipe->desthost,
2732 SEC_FLAG_MAXIMUM_ALLOWED,
2733 &conn->sam_connect_handle,
2734 &result);
2736 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2737 invalidate_cm_connection(domain);
2738 TALLOC_FREE(conn->samr_pipe);
2739 retry = true;
2740 goto retry;
2743 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2744 goto open_domain;
2746 if (NT_STATUS_IS_OK(status)) {
2747 status = result;
2749 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2750 "for domain %s, error was %s. Trying anonymous\n",
2751 domain->name, nt_errstr(status) ));
2752 TALLOC_FREE(conn->samr_pipe);
2754 anonymous:
2756 sealed_pipes = lp_winbind_sealed_pipes();
2757 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2758 domain->name,
2759 sealed_pipes);
2760 strong_key = lp_require_strong_key();
2761 strong_key = lp_parm_bool(-1, "require strong key",
2762 domain->name,
2763 strong_key);
2765 /* Finally fall back to anonymous. */
2766 if (sealed_pipes || strong_key) {
2767 status = NT_STATUS_DOWNGRADE_DETECTED;
2768 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2769 "without connection level security, "
2770 "must set 'winbind sealed pipes:%s = false' and "
2771 "'require strong key:%s = false' to proceed: %s\n",
2772 domain->name, domain->name, domain->name,
2773 nt_errstr(status)));
2774 goto done;
2776 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2777 &conn->samr_pipe);
2779 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2780 && !retry) {
2781 invalidate_cm_connection(domain);
2782 retry = true;
2783 goto retry;
2786 if (!NT_STATUS_IS_OK(status)) {
2787 goto done;
2790 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2791 conn->samr_pipe->desthost,
2792 SEC_FLAG_MAXIMUM_ALLOWED,
2793 &conn->sam_connect_handle,
2794 &result);
2796 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2797 invalidate_cm_connection(domain);
2798 TALLOC_FREE(conn->samr_pipe);
2799 retry = true;
2800 goto retry;
2803 if (!NT_STATUS_IS_OK(status)) {
2804 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2805 "for domain %s Error was %s\n",
2806 domain->name, nt_errstr(status) ));
2807 goto done;
2809 if (!NT_STATUS_IS_OK(result)) {
2810 status = result;
2811 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2812 "for domain %s Error was %s\n",
2813 domain->name, nt_errstr(result)));
2814 goto done;
2817 open_domain:
2818 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2819 mem_ctx,
2820 &conn->sam_connect_handle,
2821 SEC_FLAG_MAXIMUM_ALLOWED,
2822 &domain->sid,
2823 &conn->sam_domain_handle,
2824 &result);
2825 if (!NT_STATUS_IS_OK(status)) {
2826 goto done;
2829 status = result;
2830 done:
2832 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2834 * if we got access denied, we might just have no access rights
2835 * to talk to the remote samr server server (e.g. when we are a
2836 * PDC and we are connecting a w2k8 pdc via an interdomain
2837 * trust). In that case do not invalidate the whole connection
2838 * stack
2840 TALLOC_FREE(conn->samr_pipe);
2841 ZERO_STRUCT(conn->sam_domain_handle);
2842 return status;
2843 } else if (!NT_STATUS_IS_OK(status)) {
2844 invalidate_cm_connection(domain);
2845 return status;
2848 *cli = conn->samr_pipe;
2849 *sam_handle = conn->sam_domain_handle;
2850 return status;
2853 /**********************************************************************
2854 open an schanneld ncacn_ip_tcp connection to LSA
2855 ***********************************************************************/
2857 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2858 TALLOC_CTX *mem_ctx,
2859 struct rpc_pipe_client **cli)
2861 struct winbindd_cm_conn *conn;
2862 struct netlogon_creds_cli_context *p_creds = NULL;
2863 NTSTATUS status;
2864 const char *remote_name = NULL;
2865 const struct sockaddr_storage *remote_sockaddr = NULL;
2867 DEBUG(10,("cm_connect_lsa_tcp\n"));
2869 status = init_dc_connection_rpc(domain, false);
2870 if (!NT_STATUS_IS_OK(status)) {
2871 return status;
2874 conn = &domain->conn;
2877 * rpccli_is_connected handles more error cases
2879 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2880 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2881 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2882 goto done;
2885 TALLOC_FREE(conn->lsa_pipe_tcp);
2887 status = cm_get_schannel_creds(domain, &p_creds);
2888 if (!NT_STATUS_IS_OK(status)) {
2889 goto done;
2892 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2893 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2895 status = cli_rpc_pipe_open_schannel_with_creds(
2896 conn->cli,
2897 &ndr_table_lsarpc,
2898 NCACN_IP_TCP,
2899 p_creds,
2900 remote_name,
2901 remote_sockaddr,
2902 &conn->lsa_pipe_tcp);
2903 if (!NT_STATUS_IS_OK(status)) {
2904 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2905 nt_errstr(status)));
2906 goto done;
2909 done:
2910 if (!NT_STATUS_IS_OK(status)) {
2911 TALLOC_FREE(conn->lsa_pipe_tcp);
2912 return status;
2915 *cli = conn->lsa_pipe_tcp;
2917 return status;
2920 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2921 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2923 struct winbindd_cm_conn *conn;
2924 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2925 struct netlogon_creds_cli_context *p_creds;
2926 struct cli_credentials *creds = NULL;
2927 bool retry = false; /* allow one retry attempt for expired session */
2928 const char *remote_name = NULL;
2929 const struct sockaddr_storage *remote_sockaddr = NULL;
2930 bool sealed_pipes = true;
2931 bool strong_key = true;
2933 retry:
2934 result = init_dc_connection_rpc(domain, false);
2935 if (!NT_STATUS_IS_OK(result))
2936 return result;
2938 conn = &domain->conn;
2940 if (rpccli_is_connected(conn->lsa_pipe)) {
2941 goto done;
2944 TALLOC_FREE(conn->lsa_pipe);
2946 if (IS_DC) {
2948 * Make sure we only use schannel as AD DC.
2950 goto schannel;
2953 result = winbindd_get_trust_credentials(domain,
2954 talloc_tos(),
2955 false, /* netlogon */
2956 true, /* ipc_fallback */
2957 &creds);
2958 if (!NT_STATUS_IS_OK(result)) {
2959 DEBUG(10, ("cm_connect_lsa: No user available for "
2960 "domain %s, trying schannel\n", domain->name));
2961 goto schannel;
2964 if (cli_credentials_is_anonymous(creds)) {
2965 goto anonymous;
2968 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2969 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2972 * We have an authenticated connection. Use a SPNEGO
2973 * authenticated LSA pipe with sign & seal.
2975 result = cli_rpc_pipe_open_with_creds
2976 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2977 DCERPC_AUTH_TYPE_SPNEGO,
2978 conn->auth_level,
2979 remote_name,
2980 remote_sockaddr,
2981 creds,
2982 &conn->lsa_pipe);
2984 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
2985 && !retry) {
2986 invalidate_cm_connection(domain);
2987 retry = true;
2988 goto retry;
2991 if (!NT_STATUS_IS_OK(result)) {
2992 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2993 "domain %s using NTLMSSP authenticated pipe: user "
2994 "%s. Error was %s. Trying schannel.\n",
2995 domain->name,
2996 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2997 nt_errstr(result)));
2998 goto schannel;
3001 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3002 "NTLMSSP authenticated pipe: user %s\n",
3003 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3005 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3006 SEC_FLAG_MAXIMUM_ALLOWED,
3007 &conn->lsa_policy);
3008 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3009 invalidate_cm_connection(domain);
3010 TALLOC_FREE(conn->lsa_pipe);
3011 retry = true;
3012 goto retry;
3015 if (NT_STATUS_IS_OK(result)) {
3016 goto done;
3019 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3020 "schannel\n"));
3022 TALLOC_FREE(conn->lsa_pipe);
3024 schannel:
3026 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3028 result = cm_get_schannel_creds(domain, &p_creds);
3029 if (!NT_STATUS_IS_OK(result)) {
3030 /* If this call fails - conn->cli can now be NULL ! */
3031 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3032 "for domain %s (error %s), trying anon\n",
3033 domain->name,
3034 nt_errstr(result) ));
3035 goto anonymous;
3038 TALLOC_FREE(creds);
3039 result = cli_rpc_pipe_open_schannel_with_creds(
3040 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3041 remote_name,
3042 remote_sockaddr,
3043 &conn->lsa_pipe);
3045 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3046 && !retry) {
3047 invalidate_cm_connection(domain);
3048 retry = true;
3049 goto retry;
3052 if (!NT_STATUS_IS_OK(result)) {
3053 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3054 "domain %s using schannel. Error was %s\n",
3055 domain->name, nt_errstr(result) ));
3056 goto anonymous;
3058 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3059 "schannel.\n", domain->name ));
3061 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3062 SEC_FLAG_MAXIMUM_ALLOWED,
3063 &conn->lsa_policy);
3065 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3066 invalidate_cm_connection(domain);
3067 TALLOC_FREE(conn->lsa_pipe);
3068 retry = true;
3069 goto retry;
3072 if (NT_STATUS_IS_OK(result)) {
3073 goto done;
3076 if (IS_DC) {
3078 * Make sure we only use schannel as AD DC.
3080 goto done;
3083 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3084 "anonymous\n"));
3086 TALLOC_FREE(conn->lsa_pipe);
3088 anonymous:
3090 if (IS_DC) {
3092 * Make sure we only use schannel as AD DC.
3094 goto done;
3097 sealed_pipes = lp_winbind_sealed_pipes();
3098 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
3099 domain->name,
3100 sealed_pipes);
3101 strong_key = lp_require_strong_key();
3102 strong_key = lp_parm_bool(-1, "require strong key",
3103 domain->name,
3104 strong_key);
3106 /* Finally fall back to anonymous. */
3107 if (sealed_pipes || strong_key) {
3108 result = NT_STATUS_DOWNGRADE_DETECTED;
3109 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3110 "without connection level security, "
3111 "must set 'winbind sealed pipes:%s = false' and "
3112 "'require strong key:%s = false' to proceed: %s\n",
3113 domain->name, domain->name, domain->name,
3114 nt_errstr(result)));
3115 goto done;
3118 result = cli_rpc_pipe_open_noauth(conn->cli,
3119 &ndr_table_lsarpc,
3120 &conn->lsa_pipe);
3122 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3123 && !retry) {
3124 invalidate_cm_connection(domain);
3125 retry = true;
3126 goto retry;
3129 if (!NT_STATUS_IS_OK(result)) {
3130 goto done;
3133 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3134 SEC_FLAG_MAXIMUM_ALLOWED,
3135 &conn->lsa_policy);
3137 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3138 invalidate_cm_connection(domain);
3139 TALLOC_FREE(conn->lsa_pipe);
3140 retry = true;
3141 goto retry;
3144 done:
3145 if (!NT_STATUS_IS_OK(result)) {
3146 invalidate_cm_connection(domain);
3147 return result;
3150 *cli = conn->lsa_pipe;
3151 *lsa_policy = conn->lsa_policy;
3152 return result;
3155 /****************************************************************************
3156 Open a LSA connection to a DC, suitable for LSA lookup calls.
3157 ****************************************************************************/
3159 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3160 TALLOC_CTX *mem_ctx,
3161 struct rpc_pipe_client **cli,
3162 struct policy_handle *lsa_policy)
3164 NTSTATUS status;
3166 if (domain->can_do_ncacn_ip_tcp) {
3167 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3168 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3169 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3170 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3171 invalidate_cm_connection(domain);
3172 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3174 if (NT_STATUS_IS_OK(status)) {
3175 return status;
3179 * we tried twice to connect via ncan_ip_tcp and schannel and
3180 * failed - maybe it is a trusted domain we can't connect to ?
3181 * do not try tcp next time - gd
3183 * This also prevents NETLOGON over TCP
3185 domain->can_do_ncacn_ip_tcp = false;
3188 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3190 return status;
3193 /****************************************************************************
3194 Open the netlogon pipe to this DC.
3195 ****************************************************************************/
3197 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3198 enum dcerpc_transport_t transport,
3199 struct rpc_pipe_client **cli)
3201 struct messaging_context *msg_ctx = global_messaging_context();
3202 struct winbindd_cm_conn *conn;
3203 NTSTATUS result;
3204 enum netr_SchannelType sec_chan_type;
3205 struct cli_credentials *creds = NULL;
3207 *cli = NULL;
3209 if (IS_DC) {
3210 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3212 * Make sure we don't even try to
3213 * connect to a foreign domain
3214 * without a direct outbound trust.
3216 return NT_STATUS_NO_TRUST_LSA_SECRET;
3220 result = init_dc_connection_rpc(domain, domain->rodc);
3221 if (!NT_STATUS_IS_OK(result)) {
3222 return result;
3225 conn = &domain->conn;
3227 if (rpccli_is_connected(conn->netlogon_pipe)) {
3228 *cli = conn->netlogon_pipe;
3229 return NT_STATUS_OK;
3232 TALLOC_FREE(conn->netlogon_pipe);
3233 TALLOC_FREE(conn->netlogon_creds_ctx);
3235 result = winbindd_get_trust_credentials(domain,
3236 talloc_tos(),
3237 true, /* netlogon */
3238 false, /* ipc_fallback */
3239 &creds);
3240 if (!NT_STATUS_IS_OK(result)) {
3241 DBG_DEBUG("No user available for domain %s when trying "
3242 "schannel\n", domain->name);
3243 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3246 if (cli_credentials_is_anonymous(creds)) {
3247 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3248 "unable to make get NETLOGON credentials\n",
3249 domain->name);
3250 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3253 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3254 if (sec_chan_type == SEC_CHAN_NULL) {
3255 const char *remote_name =
3256 smbXcli_conn_remote_name(conn->cli->conn);
3257 const struct sockaddr_storage *remote_sockaddr =
3258 smbXcli_conn_remote_sockaddr(conn->cli->conn);
3260 if (transport == NCACN_IP_TCP) {
3261 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3262 "for %s, deny NCACN_IP_TCP and let the "
3263 "caller fallback to NCACN_NP.\n",
3264 domain->name);
3265 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3268 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3269 "fallback to noauth on NCACN_NP.\n",
3270 domain->name);
3272 result = cli_rpc_pipe_open_noauth_transport(
3273 conn->cli,
3274 transport,
3275 &ndr_table_netlogon,
3276 remote_name,
3277 remote_sockaddr,
3278 &conn->netlogon_pipe);
3279 if (!NT_STATUS_IS_OK(result)) {
3280 invalidate_cm_connection(domain);
3281 return result;
3284 *cli = conn->netlogon_pipe;
3285 return NT_STATUS_OK;
3288 result = rpccli_create_netlogon_creds_ctx(creds,
3289 domain->dcname,
3290 msg_ctx,
3291 domain,
3292 &conn->netlogon_creds_ctx);
3293 if (!NT_STATUS_IS_OK(result)) {
3294 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3295 "unable to create NETLOGON credentials: %s\n",
3296 domain->name, nt_errstr(result)));
3297 return result;
3300 result = rpccli_connect_netlogon(
3301 conn->cli, transport,
3302 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3303 &conn->netlogon_pipe);
3304 conn->netlogon_force_reauth = false;
3305 if (!NT_STATUS_IS_OK(result)) {
3306 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3307 nt_errstr(result));
3308 return result;
3311 *cli = conn->netlogon_pipe;
3312 return NT_STATUS_OK;
3315 /****************************************************************************
3316 Open a NETLOGON connection to a DC, suitable for SamLogon calls.
3317 ****************************************************************************/
3319 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3320 struct rpc_pipe_client **cli)
3322 NTSTATUS status;
3324 status = init_dc_connection_rpc(domain, domain->rodc);
3325 if (!NT_STATUS_IS_OK(status)) {
3326 return status;
3329 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3330 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3331 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3332 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3333 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3334 invalidate_cm_connection(domain);
3335 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3337 if (NT_STATUS_IS_OK(status)) {
3338 return status;
3342 * we tried twice to connect via ncan_ip_tcp and schannel and
3343 * failed - maybe it is a trusted domain we can't connect to ?
3344 * do not try tcp next time - gd
3346 * This also prevents LSA over TCP
3348 domain->can_do_ncacn_ip_tcp = false;
3351 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3352 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3354 * SMB2 session expired, needs reauthentication. Drop
3355 * connection and retry.
3357 invalidate_cm_connection(domain);
3358 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3361 return status;
3364 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3365 struct rpc_pipe_client **cli,
3366 struct netlogon_creds_cli_context **ppdc)
3368 NTSTATUS status;
3370 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3371 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3374 status = cm_connect_netlogon(domain, cli);
3375 if (!NT_STATUS_IS_OK(status)) {
3376 return status;
3379 if (domain->conn.netlogon_creds_ctx == NULL) {
3380 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3383 *ppdc = domain->conn.netlogon_creds_ctx;
3384 return NT_STATUS_OK;
3387 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3388 void *private_data,
3389 uint32_t msg_type,
3390 struct server_id server_id,
3391 DATA_BLOB *data)
3393 struct winbindd_domain *domain;
3394 char *freeit = NULL;
3395 char *addr;
3397 if ((data == NULL)
3398 || (data->data == NULL)
3399 || (data->length == 0)
3400 || (data->data[data->length-1] != '\0')) {
3401 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3402 "string\n"));
3403 return;
3406 addr = (char *)data->data;
3407 DEBUG(10, ("IP %s dropped\n", addr));
3409 if (!is_ipaddress(addr)) {
3410 char *slash;
3412 * Some code sends us ip addresses with the /netmask
3413 * suffix
3415 slash = strchr(addr, '/');
3416 if (slash == NULL) {
3417 DEBUG(1, ("invalid msg_ip_dropped message: %s\n",
3418 addr));
3419 return;
3421 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3422 if (freeit == NULL) {
3423 DEBUG(1, ("talloc failed\n"));
3424 return;
3426 addr = freeit;
3427 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3430 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3431 char sockaddr[INET6_ADDRSTRLEN];
3433 if (!cli_state_is_connected(domain->conn.cli)) {
3434 continue;
3437 print_sockaddr(sockaddr, sizeof(sockaddr),
3438 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3440 if (strequal(sockaddr, addr)) {
3441 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3444 TALLOC_FREE(freeit);
3447 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3448 void *private_data,
3449 uint32_t msg_type,
3450 struct server_id server_id,
3451 DATA_BLOB *data)
3453 struct winbindd_domain *domain;
3455 for (domain = domain_list(); domain; domain = domain->next) {
3456 if (domain->internal) {
3457 continue;
3459 invalidate_cm_connection(domain);