util:datablob: data_blob_pad checks its alignment assumption
[samba.git] / source3 / winbindd / winbindd_cm.c
blob2a2eb3da72b02a07df001875dc34d14d71c156c7
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 struct samba_sockaddr ss1 = { .u = { .ss = (*dcs)[i].ss, }};
1077 struct samba_sockaddr ss2 = { .u = { .ss = *pss, }};
1079 if (sockaddr_equal(&ss1.u.sa, &ss2.u.sa)) {
1080 return False;
1084 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1086 if (*dcs == NULL)
1087 return False;
1089 fstrcpy((*dcs)[*num].name, dcname);
1090 (*dcs)[*num].ss = *pss;
1091 *num += 1;
1092 return True;
1095 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1096 struct sockaddr_storage *pss, uint16_t port,
1097 struct sockaddr_storage **addrs, int *num)
1099 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1101 if (*addrs == NULL) {
1102 *num = 0;
1103 return False;
1106 (*addrs)[*num] = *pss;
1107 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1109 *num += 1;
1110 return True;
1113 #ifdef HAVE_ADS
1114 static bool dcip_check_name_ads(const struct winbindd_domain *domain,
1115 struct samba_sockaddr *sa,
1116 uint32_t request_flags,
1117 TALLOC_CTX *mem_ctx,
1118 char **namep)
1120 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1121 char *name = NULL;
1122 ADS_STRUCT *ads = NULL;
1123 ADS_STATUS ads_status;
1124 char addr[INET6_ADDRSTRLEN];
1126 print_sockaddr(addr, sizeof(addr), &sa->u.ss);
1127 D_DEBUG("Trying to figure out the DC name for domain '%s' at IP '%s'.\n",
1128 domain->name,
1129 addr);
1131 ads = ads_init(tmp_ctx,
1132 domain->alt_name,
1133 domain->name,
1134 addr,
1135 ADS_SASL_PLAIN);
1136 if (ads == NULL) {
1137 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1138 goto out;
1140 ads->config.flags |= request_flags;
1141 ads->server.no_fallback = true;
1143 ads_status = ads_connect_cldap_only(ads);
1144 if (!ADS_ERR_OK(ads_status)) {
1145 goto out;
1148 /* We got a cldap packet. */
1149 name = talloc_strdup(tmp_ctx, ads->config.ldap_server_name);
1150 if (name == NULL) {
1151 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1152 goto out;
1154 namecache_store(name, 0x20, 1, sa);
1156 DBG_DEBUG("CLDAP flags = 0x%"PRIx32"\n", ads->config.flags);
1158 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1159 if (ads_closest_dc(ads)) {
1160 char *sitename = sitename_fetch(tmp_ctx,
1161 ads->config.realm);
1163 /* We're going to use this KDC for this realm/domain.
1164 If we are using sites, then force the krb5 libs
1165 to use this KDC. */
1167 create_local_private_krb5_conf_for_domain(domain->alt_name,
1168 domain->name,
1169 sitename,
1170 &sa->u.ss);
1172 TALLOC_FREE(sitename);
1173 } else {
1174 /* use an off site KDC */
1175 create_local_private_krb5_conf_for_domain(domain->alt_name,
1176 domain->name,
1177 NULL,
1178 &sa->u.ss);
1180 winbindd_set_locator_kdc_envs(domain);
1182 /* Ensure we contact this DC also. */
1183 saf_store(domain->name, name);
1184 saf_store(domain->alt_name, name);
1187 D_DEBUG("DC name for domain '%s' at IP '%s' is '%s'\n",
1188 domain->name,
1189 addr,
1190 name);
1191 *namep = talloc_move(mem_ctx, &name);
1193 out:
1194 TALLOC_FREE(tmp_ctx);
1196 return ADS_ERR_OK(ads_status) ? true : false;
1198 #endif
1200 /*******************************************************************
1201 convert an ip to a name
1202 For an AD Domain, it checks the requirements of the request flags.
1203 *******************************************************************/
1205 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1206 const struct winbindd_domain *domain,
1207 const struct sockaddr_storage *pss,
1208 char **name, uint32_t request_flags)
1210 struct samba_sockaddr sa = {0};
1211 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1212 NTSTATUS status;
1213 const char *dc_name;
1214 fstring nbtname;
1215 #ifdef HAVE_ADS
1216 bool is_ad_domain = false;
1217 #endif
1218 bool ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
1219 if (!ok) {
1220 return false;
1223 #ifdef HAVE_ADS
1224 /* For active directory servers, try to get the ldap server name.
1225 None of these failures should be considered critical for now */
1227 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1228 is_ad_domain = true;
1229 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1230 is_ad_domain = domain->active_directory;
1233 if (is_ad_domain) {
1234 return dcip_check_name_ads(domain,
1235 &sa,
1236 request_flags,
1237 mem_ctx,
1238 name);
1240 #endif
1243 size_t len = strlen(lp_netbios_name());
1244 char my_acct_name[len+2];
1246 snprintf(my_acct_name,
1247 sizeof(my_acct_name),
1248 "%s$",
1249 lp_netbios_name());
1251 status = nbt_getdc(global_messaging_context(), 10, &sa.u.ss,
1252 domain->name, &domain->sid,
1253 my_acct_name, ACB_WSTRUST,
1254 nt_version, mem_ctx, &nt_version,
1255 &dc_name, NULL);
1257 if (NT_STATUS_IS_OK(status)) {
1258 *name = talloc_strdup(mem_ctx, dc_name);
1259 if (*name == NULL) {
1260 return false;
1262 namecache_store(*name, 0x20, 1, &sa);
1263 return True;
1266 /* try node status request */
1268 if (name_status_find(domain->name, 0x1c, 0x20, &sa.u.ss, nbtname) ) {
1269 namecache_store(nbtname, 0x20, 1, &sa);
1271 if (name != NULL) {
1272 *name = talloc_strdup(mem_ctx, nbtname);
1273 if (*name == NULL) {
1274 return false;
1278 return true;
1280 return False;
1283 /*******************************************************************
1284 Retrieve a list of IP addresses for domain controllers.
1286 The array is sorted in the preferred connection order.
1288 @param[in] mem_ctx talloc memory context to allocate from
1289 @param[in] domain domain to retrieve DCs for
1290 @param[out] dcs array of dcs that will be returned
1291 @param[out] num_dcs number of dcs returned in the dcs array
1292 @return always true
1293 *******************************************************************/
1295 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1296 struct dc_name_ip **dcs, int *num_dcs,
1297 uint32_t request_flags)
1299 fstring dcname;
1300 struct sockaddr_storage ss;
1301 struct samba_sockaddr *sa_list = NULL;
1302 size_t salist_size = 0;
1303 size_t i;
1304 bool is_our_domain;
1305 enum security_types sec = (enum security_types)lp_security();
1307 is_our_domain = strequal(domain->name, lp_workgroup());
1309 /* If not our domain, get the preferred DC, by asking our primary DC */
1310 if ( !is_our_domain
1311 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1312 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1313 num_dcs) )
1315 char addr[INET6_ADDRSTRLEN];
1316 print_sockaddr(addr, sizeof(addr), &ss);
1317 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1318 dcname, addr));
1319 return True;
1322 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1323 char *sitename = NULL;
1325 /* We need to make sure we know the local site before
1326 doing any DNS queries, as this will restrict the
1327 get_sorted_dc_list() call below to only fetching
1328 DNS records for the correct site. */
1330 /* Find any DC to get the site record.
1331 We deliberately don't care about the
1332 return here. */
1334 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1336 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1337 if (sitename) {
1339 /* Do the site-specific AD dns lookup first. */
1340 (void)get_sorted_dc_list(mem_ctx,
1341 domain->alt_name,
1342 sitename,
1343 &sa_list,
1344 &salist_size,
1345 true);
1347 /* Add ips to the DC array. We don't look up the name
1348 of the DC in this function, but we fill in the char*
1349 of the ip now to make the failed connection cache
1350 work */
1351 for ( i=0; i<salist_size; i++ ) {
1352 char addr[INET6_ADDRSTRLEN];
1353 print_sockaddr(addr, sizeof(addr),
1354 &sa_list[i].u.ss);
1355 add_one_dc_unique(mem_ctx,
1356 domain->name,
1357 addr,
1358 &sa_list[i].u.ss,
1359 dcs,
1360 num_dcs);
1363 TALLOC_FREE(sa_list);
1364 TALLOC_FREE(sitename);
1365 salist_size = 0;
1368 /* Now we add DCs from the main AD DNS lookup. */
1369 (void)get_sorted_dc_list(mem_ctx,
1370 domain->alt_name,
1371 NULL,
1372 &sa_list,
1373 &salist_size,
1374 true);
1376 for ( i=0; i<salist_size; i++ ) {
1377 char addr[INET6_ADDRSTRLEN];
1378 print_sockaddr(addr, sizeof(addr),
1379 &sa_list[i].u.ss);
1380 add_one_dc_unique(mem_ctx,
1381 domain->name,
1382 addr,
1383 &sa_list[i].u.ss,
1384 dcs,
1385 num_dcs);
1388 TALLOC_FREE(sa_list);
1389 salist_size = 0;
1392 /* Try standard netbios queries if no ADS and fall back to DNS queries
1393 * if alt_name is available */
1394 if (*num_dcs == 0) {
1395 (void)get_sorted_dc_list(mem_ctx,
1396 domain->name,
1397 NULL,
1398 &sa_list,
1399 &salist_size,
1400 false);
1401 if (salist_size == 0) {
1402 if (domain->alt_name != NULL) {
1403 (void)get_sorted_dc_list(mem_ctx,
1404 domain->alt_name,
1405 NULL,
1406 &sa_list,
1407 &salist_size,
1408 true);
1412 for ( i=0; i<salist_size; i++ ) {
1413 char addr[INET6_ADDRSTRLEN];
1414 print_sockaddr(addr, sizeof(addr),
1415 &sa_list[i].u.ss);
1416 add_one_dc_unique(mem_ctx,
1417 domain->name,
1418 addr,
1419 &sa_list[i].u.ss,
1420 dcs,
1421 num_dcs);
1424 TALLOC_FREE(sa_list);
1425 salist_size = 0;
1428 return True;
1431 static bool connect_preferred_dc(TALLOC_CTX *mem_ctx,
1432 struct winbindd_domain *domain,
1433 uint32_t request_flags,
1434 int *fd)
1436 char *saf_servername = NULL;
1437 NTSTATUS status;
1438 bool ok;
1441 * We have to check the server affinity cache here since later we select
1442 * a DC based on response time and not preference.
1444 if (domain->force_dc) {
1445 saf_servername = domain->dcname;
1446 } else {
1447 saf_servername = saf_fetch(mem_ctx, domain->name);
1451 * Check the negative connection cache before talking to it. It going
1452 * down may have triggered the reconnection.
1454 if (saf_servername != NULL) {
1455 status = check_negative_conn_cache(domain->name,
1456 saf_servername);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 saf_servername = NULL;
1462 if (saf_servername != NULL) {
1463 DBG_DEBUG("saf_servername is '%s' for domain %s\n",
1464 saf_servername, domain->name);
1466 /* convert an ip address to a name */
1467 if (is_ipaddress(saf_servername)) {
1468 ok = interpret_string_addr(&domain->dcaddr,
1469 saf_servername,
1470 AI_NUMERICHOST);
1471 if (!ok) {
1472 return false;
1474 } else {
1475 ok = resolve_name(saf_servername,
1476 &domain->dcaddr,
1477 0x20,
1478 true);
1479 if (!ok) {
1480 goto fail;
1484 TALLOC_FREE(domain->dcname);
1485 ok = dcip_check_name(domain,
1486 domain,
1487 &domain->dcaddr,
1488 &domain->dcname,
1489 request_flags);
1490 if (!ok) {
1491 goto fail;
1495 if (domain->dcname == NULL) {
1496 return false;
1499 status = check_negative_conn_cache(domain->name, domain->dcname);
1500 if (!NT_STATUS_IS_OK(status)) {
1501 return false;
1504 status = smbsock_connect(&domain->dcaddr, 0,
1505 domain->dcname, -1, NULL, -1,
1506 fd, NULL, 10);
1507 if (!NT_STATUS_IS_OK(status)) {
1508 winbind_add_failed_connection_entry(domain,
1509 domain->dcname,
1510 NT_STATUS_UNSUCCESSFUL);
1511 return false;
1513 return true;
1515 fail:
1516 winbind_add_failed_connection_entry(domain,
1517 saf_servername,
1518 NT_STATUS_UNSUCCESSFUL);
1519 return false;
1523 /*******************************************************************
1524 Find and make a connection to a DC in the given domain.
1526 @param[in] mem_ctx talloc memory context to allocate from
1527 @param[in] domain domain to find a dc in
1528 @param[out] fd fd of the open socket connected to the newly found dc
1529 @return true when a DC connection is made, false otherwise
1530 *******************************************************************/
1532 static bool find_dc(TALLOC_CTX *mem_ctx,
1533 struct winbindd_domain *domain,
1534 uint32_t request_flags,
1535 int *fd)
1537 struct dc_name_ip *dcs = NULL;
1538 int num_dcs = 0;
1540 const char **dcnames = NULL;
1541 size_t num_dcnames = 0;
1543 struct sockaddr_storage *addrs = NULL;
1544 int num_addrs = 0;
1546 int i;
1547 size_t fd_index;
1549 NTSTATUS status;
1550 bool ok;
1552 *fd = -1;
1554 D_NOTICE("First try to connect to the closest DC (using server "
1555 "affinity cache). If this fails, try to lookup the DC using "
1556 "DNS afterwards.\n");
1557 ok = connect_preferred_dc(mem_ctx, domain, request_flags, fd);
1558 if (ok) {
1559 return true;
1562 if (domain->force_dc) {
1563 return false;
1566 again:
1567 D_DEBUG("Retrieving a list of IP addresses for DCs.\n");
1568 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1569 return False;
1571 D_DEBUG("Retrieved IP addresses for %d DCs.\n", num_dcs);
1572 for (i=0; i<num_dcs; i++) {
1574 if (!add_string_to_array(mem_ctx, dcs[i].name,
1575 &dcnames, &num_dcnames)) {
1576 return False;
1578 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1579 &addrs, &num_addrs)) {
1580 return False;
1584 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1585 return False;
1587 if ((addrs == NULL) || (dcnames == NULL))
1588 return False;
1590 D_DEBUG("Trying to establish a connection to one of the %d DCs "
1591 "(timeout of 10 sec for each DC).\n",
1592 num_dcs);
1593 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1594 num_addrs, 0, 10, fd, &fd_index, NULL);
1595 if (!NT_STATUS_IS_OK(status)) {
1596 for (i=0; i<num_dcs; i++) {
1597 char ab[INET6_ADDRSTRLEN];
1598 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1599 DBG_DEBUG("smbsock_any_connect failed for "
1600 "domain %s address %s. Error was %s\n",
1601 domain->name, ab, nt_errstr(status));
1602 winbind_add_failed_connection_entry(domain,
1603 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1605 return False;
1607 D_NOTICE("Successfully connected to DC '%s'.\n", dcs[fd_index].name);
1609 domain->dcaddr = addrs[fd_index];
1611 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1612 /* Ok, we've got a name for the DC */
1613 TALLOC_FREE(domain->dcname);
1614 domain->dcname = talloc_strdup(domain, dcnames[fd_index]);
1615 if (domain->dcname == NULL) {
1616 return false;
1618 return true;
1621 /* Try to figure out the name */
1622 TALLOC_FREE(domain->dcname);
1623 ok = dcip_check_name(domain,
1624 domain,
1625 &domain->dcaddr,
1626 &domain->dcname,
1627 request_flags);
1628 if (ok) {
1629 return true;
1632 /* We can not continue without the DC's name */
1633 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1634 NT_STATUS_UNSUCCESSFUL);
1636 /* Throw away all arrays as we're doing this again. */
1637 TALLOC_FREE(dcs);
1638 num_dcs = 0;
1640 TALLOC_FREE(dcnames);
1641 num_dcnames = 0;
1643 TALLOC_FREE(addrs);
1644 num_addrs = 0;
1646 if (*fd != -1) {
1647 close(*fd);
1648 *fd = -1;
1652 * This should not be an infinite loop, since get_dcs() will not return
1653 * the DC added to the negative connection cache in the above
1654 * winbind_add_failed_connection_entry() call.
1656 goto again;
1659 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1661 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1662 domain_name);
1665 static void store_current_dc_in_gencache(const char *domain_name,
1666 const char *dc_name,
1667 const struct sockaddr_storage *dc_addr)
1669 char addr[INET6_ADDRSTRLEN];
1670 char *key = NULL;
1671 char *value = NULL;
1673 print_sockaddr(addr, sizeof(addr), dc_addr);
1675 key = current_dc_key(talloc_tos(), domain_name);
1676 if (key == NULL) {
1677 goto done;
1680 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1681 if (value == NULL) {
1682 goto done;
1685 gencache_set(key, value, 0x7fffffff);
1686 done:
1687 TALLOC_FREE(value);
1688 TALLOC_FREE(key);
1691 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1692 const char *domain_name,
1693 char **p_dc_name, char **p_dc_ip)
1695 char *key, *p;
1696 char *value = NULL;
1697 bool ret = false;
1698 char *dc_name = NULL;
1699 char *dc_ip = NULL;
1701 key = current_dc_key(talloc_tos(), domain_name);
1702 if (key == NULL) {
1703 goto done;
1705 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1706 goto done;
1708 p = strchr(value, ' ');
1709 if (p == NULL) {
1710 goto done;
1712 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1713 if (dc_ip == NULL) {
1714 goto done;
1716 dc_name = talloc_strdup(mem_ctx, p+1);
1717 if (dc_name == NULL) {
1718 goto done;
1721 if (p_dc_ip != NULL) {
1722 *p_dc_ip = dc_ip;
1723 dc_ip = NULL;
1725 if (p_dc_name != NULL) {
1726 *p_dc_name = dc_name;
1727 dc_name = NULL;
1729 ret = true;
1730 done:
1731 TALLOC_FREE(dc_name);
1732 TALLOC_FREE(dc_ip);
1733 TALLOC_FREE(key);
1734 TALLOC_FREE(value);
1735 return ret;
1738 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1739 const struct ndr_interface_table *table,
1740 struct rpc_pipe_client **ret_pipe)
1742 struct rpc_pipe_client *cli = NULL;
1743 const struct auth_session_info *session_info = NULL;
1744 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1747 session_info = get_session_info_system();
1748 SMB_ASSERT(session_info != NULL);
1750 status = rpc_pipe_open_local_np(
1751 mem_ctx, table, NULL, NULL, NULL, NULL, session_info, &cli);
1752 if (!NT_STATUS_IS_OK(status)) {
1753 return status;
1756 if (ret_pipe) {
1757 *ret_pipe = cli;
1760 return NT_STATUS_OK;
1763 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1764 struct winbindd_cm_conn *new_conn,
1765 bool need_rw_dc)
1767 TALLOC_CTX *mem_ctx;
1768 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1769 int retries;
1770 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1771 int fd = -1;
1772 bool retry = false;
1773 bool seal_pipes = true;
1775 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1776 set_domain_offline(domain);
1777 return NT_STATUS_NO_MEMORY;
1780 D_NOTICE("Creating connection to domain controller. This is a start of "
1781 "a new connection or a DC failover. The failover only happens "
1782 "if the domain has more than one DC. We will try to connect 3 "
1783 "times at most.\n");
1784 for (retries = 0; retries < 3; retries++) {
1785 bool found_dc;
1787 D_DEBUG("Attempt %d/3: DC '%s' of domain '%s'.\n",
1788 retries,
1789 domain->dcname ? domain->dcname : "",
1790 domain->name);
1792 found_dc = find_dc(mem_ctx, domain, request_flags, &fd);
1793 if (!found_dc) {
1794 /* This is the one place where we will
1795 set the global winbindd offline state
1796 to true, if a "WINBINDD_OFFLINE" entry
1797 is found in the winbindd cache. */
1798 set_global_winbindd_state_offline();
1799 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1800 break;
1803 new_conn->cli = NULL;
1805 result = cm_prepare_connection(domain, fd, domain->dcname,
1806 &new_conn->cli, &retry);
1807 if (NT_STATUS_IS_OK(result)) {
1808 break;
1810 if (!retry) {
1811 break;
1815 if (!NT_STATUS_IS_OK(result)) {
1816 /* Ensure we setup the retry handler. */
1817 set_domain_offline(domain);
1818 goto out;
1821 winbindd_set_locator_kdc_envs(domain);
1823 if (domain->online == False) {
1824 /* We're changing state from offline to online. */
1825 set_global_winbindd_state_online();
1827 set_domain_online(domain);
1830 * Much as I hate global state, this seems to be the point
1831 * where we can be certain that we have a proper connection to
1832 * a DC. wbinfo --dc-info needs that information, store it in
1833 * gencache with a looong timeout. This will need revisiting
1834 * once we start to connect to multiple DCs, wbcDcInfo is
1835 * already prepared for that.
1837 store_current_dc_in_gencache(domain->name,
1838 domain->dcname,
1839 &domain->dcaddr);
1841 seal_pipes = lp_winbind_sealed_pipes();
1842 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1843 domain->name,
1844 seal_pipes);
1846 if (seal_pipes) {
1847 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1848 } else {
1849 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1852 out:
1853 talloc_destroy(mem_ctx);
1854 return result;
1857 /* Close down all open pipes on a connection. */
1859 void invalidate_cm_connection(struct winbindd_domain *domain)
1861 NTSTATUS result;
1862 struct winbindd_cm_conn *conn = &domain->conn;
1864 domain->sequence_number = DOM_SEQUENCE_NONE;
1865 domain->last_seq_check = 0;
1866 domain->last_status = NT_STATUS_SERVER_DISABLED;
1868 /* We're closing down a possibly dead
1869 connection. Don't have impossibly long (10s) timeouts. */
1871 if (conn->cli) {
1872 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1875 if (conn->samr_pipe != NULL) {
1876 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1877 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1878 talloc_tos(),
1879 &conn->sam_connect_handle,
1880 &result);
1882 TALLOC_FREE(conn->samr_pipe);
1883 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1884 if (conn->cli) {
1885 cli_set_timeout(conn->cli, 500);
1889 if (conn->lsa_pipe != NULL) {
1890 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1891 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1892 talloc_tos(),
1893 &conn->lsa_policy,
1894 &result);
1896 TALLOC_FREE(conn->lsa_pipe);
1897 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1898 if (conn->cli) {
1899 cli_set_timeout(conn->cli, 500);
1903 if (conn->lsa_pipe_tcp != NULL) {
1904 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1905 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1906 talloc_tos(),
1907 &conn->lsa_policy,
1908 &result);
1910 TALLOC_FREE(conn->lsa_pipe_tcp);
1911 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1912 if (conn->cli) {
1913 cli_set_timeout(conn->cli, 500);
1917 if (conn->netlogon_pipe != NULL) {
1918 TALLOC_FREE(conn->netlogon_pipe);
1919 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1920 if (conn->cli) {
1921 cli_set_timeout(conn->cli, 500);
1925 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1926 TALLOC_FREE(conn->netlogon_creds_ctx);
1928 if (conn->cli) {
1929 cli_shutdown(conn->cli);
1932 conn->cli = NULL;
1935 void close_conns_after_fork(void)
1937 struct winbindd_domain *domain;
1938 struct winbindd_cli_state *cli_state;
1940 for (domain = domain_list(); domain; domain = domain->next) {
1942 * first close the low level SMB TCP connection
1943 * so that we don't generate any SMBclose
1944 * requests in invalidate_cm_connection()
1946 if (cli_state_is_connected(domain->conn.cli)) {
1947 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1950 invalidate_cm_connection(domain);
1953 for (cli_state = winbindd_client_list();
1954 cli_state != NULL;
1955 cli_state = cli_state->next) {
1956 if (cli_state->sock >= 0) {
1957 close(cli_state->sock);
1958 cli_state->sock = -1;
1963 static bool connection_ok(struct winbindd_domain *domain)
1965 bool ok;
1967 ok = cli_state_is_connected(domain->conn.cli);
1968 if (!ok) {
1969 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1970 domain->dcname, domain->name));
1971 return False;
1974 if (!domain->online) {
1975 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1976 return False;
1979 return True;
1982 /* Initialize a new connection up to the RPC BIND.
1983 Bypass online status check so always does network calls. */
1985 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
1987 NTSTATUS result;
1988 bool skip_connection = domain->internal;
1989 if (need_rw_dc && domain->rodc) {
1990 skip_connection = false;
1993 /* Internal connections never use the network. */
1994 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
1995 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1998 /* Still ask the internal LSA and SAMR server about the local domain */
1999 if (skip_connection || connection_ok(domain)) {
2000 if (!domain->initialized) {
2001 set_dc_type_and_flags(domain);
2003 return NT_STATUS_OK;
2006 invalidate_cm_connection(domain);
2008 if (!domain->primary && !domain->initialized) {
2010 * Before we connect to a trust, work out if it is an
2011 * AD domain by asking our own domain.
2013 set_dc_type_and_flags_trustinfo(domain);
2016 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2018 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2019 set_dc_type_and_flags(domain);
2022 return result;
2025 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2027 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2028 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2031 SMB_ASSERT(wb_child_domain() || idmap_child());
2033 return init_dc_connection_network(domain, need_rw_dc);
2036 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2038 NTSTATUS status;
2040 status = init_dc_connection(domain, need_rw_dc);
2041 if (!NT_STATUS_IS_OK(status)) {
2042 return status;
2045 if (!domain->internal && domain->conn.cli == NULL) {
2046 /* happens for trusted domains without inbound trust */
2047 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2050 return NT_STATUS_OK;
2053 /******************************************************************************
2054 Set the trust flags (direction and forest location) for a domain
2055 ******************************************************************************/
2057 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2059 struct winbindd_domain *our_domain;
2060 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2061 WERROR werr;
2062 struct netr_DomainTrustList trusts;
2063 int i;
2064 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2065 NETR_TRUST_FLAG_OUTBOUND |
2066 NETR_TRUST_FLAG_INBOUND);
2067 struct rpc_pipe_client *cli;
2068 TALLOC_CTX *mem_ctx = NULL;
2069 struct dcerpc_binding_handle *b;
2071 if (IS_DC) {
2073 * On a DC we loaded all trusts
2074 * from configuration and never learn
2075 * new domains.
2077 return true;
2080 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2082 /* Our primary domain doesn't need to worry about trust flags.
2083 Force it to go through the network setup */
2084 if ( domain->primary ) {
2085 return False;
2088 mem_ctx = talloc_stackframe();
2089 our_domain = find_our_domain();
2090 if (our_domain->internal) {
2091 result = init_dc_connection(our_domain, false);
2092 if (!NT_STATUS_IS_OK(result)) {
2093 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2094 "Not able to make a connection to our domain: %s\n",
2095 nt_errstr(result)));
2096 TALLOC_FREE(mem_ctx);
2097 return false;
2101 /* This won't work unless our domain is AD */
2102 if ( !our_domain->active_directory ) {
2103 TALLOC_FREE(mem_ctx);
2104 return False;
2107 if (our_domain->internal) {
2108 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2109 } else if (!connection_ok(our_domain)) {
2110 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2111 "No connection to our domain!\n"));
2112 TALLOC_FREE(mem_ctx);
2113 return False;
2114 } else {
2115 result = cm_connect_netlogon(our_domain, &cli);
2118 if (!NT_STATUS_IS_OK(result)) {
2119 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2120 "a connection to %s for PIPE_NETLOGON (%s)\n",
2121 domain->name, nt_errstr(result)));
2122 TALLOC_FREE(mem_ctx);
2123 return False;
2125 b = cli->binding_handle;
2127 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2128 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2129 cli->desthost,
2130 flags,
2131 &trusts,
2132 &werr);
2133 if (!NT_STATUS_IS_OK(result)) {
2134 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2135 "failed to query trusted domain list: %s\n",
2136 nt_errstr(result)));
2137 TALLOC_FREE(mem_ctx);
2138 return false;
2140 if (!W_ERROR_IS_OK(werr)) {
2141 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2142 "failed to query trusted domain list: %s\n",
2143 win_errstr(werr)));
2144 TALLOC_FREE(mem_ctx);
2145 return false;
2148 /* Now find the domain name and get the flags */
2150 for ( i=0; i<trusts.count; i++ ) {
2151 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2152 domain->domain_flags = trusts.array[i].trust_flags;
2153 domain->domain_type = trusts.array[i].trust_type;
2154 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2156 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2157 domain->active_directory = True;
2159 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2160 "running active directory.\n", domain->name,
2161 domain->active_directory ? "" : "NOT "));
2163 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2165 domain->initialized = True;
2167 break;
2171 TALLOC_FREE(mem_ctx);
2173 return domain->initialized;
2176 /******************************************************************************
2177 We can 'sense' certain things about the DC by it's replies to certain
2178 questions.
2180 This tells us if this particular remote server is Active Directory, and if it
2181 is native mode.
2182 ******************************************************************************/
2184 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2186 NTSTATUS status, result;
2187 NTSTATUS close_status = NT_STATUS_UNSUCCESSFUL;
2188 TALLOC_CTX *mem_ctx = NULL;
2189 struct rpc_pipe_client *cli = NULL;
2190 struct policy_handle pol = { .handle_type = 0 };
2191 union lsa_PolicyInformation *lsa_info = NULL;
2192 union lsa_revision_info out_revision_info = {
2193 .info1 = {
2194 .revision = 0,
2197 uint32_t out_version = 0;
2199 if (!domain->internal && !connection_ok(domain)) {
2200 return;
2203 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2204 domain->name);
2205 if (!mem_ctx) {
2206 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2207 return;
2210 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2212 if (domain->internal) {
2213 status = wb_open_internal_pipe(mem_ctx,
2214 &ndr_table_lsarpc,
2215 &cli);
2216 } else {
2217 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2218 &ndr_table_lsarpc, &cli);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2222 "PI_LSARPC on domain %s: (%s)\n",
2223 domain->name, nt_errstr(status)));
2224 TALLOC_FREE(cli);
2225 TALLOC_FREE(mem_ctx);
2226 return;
2229 status = dcerpc_lsa_open_policy_fallback(cli->binding_handle,
2230 mem_ctx,
2231 cli->srv_name_slash,
2232 true,
2233 SEC_FLAG_MAXIMUM_ALLOWED,
2234 &out_version,
2235 &out_revision_info,
2236 &pol,
2237 &result);
2239 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2240 /* This particular query is exactly what Win2k clients use
2241 to determine that the DC is active directory */
2242 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2243 &pol,
2244 LSA_POLICY_INFO_DNS,
2245 &lsa_info,
2246 &result);
2250 * If the status and result will not be OK we will fallback to
2251 * OpenPolicy.
2253 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2254 domain->active_directory = True;
2256 if (lsa_info->dns.name.string) {
2257 if (!strequal(domain->name, lsa_info->dns.name.string))
2259 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2260 "for domain %s claimed it was a DC "
2261 "for domain %s, refusing to "
2262 "initialize\n",
2263 domain->name,
2264 lsa_info->dns.name.string));
2265 TALLOC_FREE(cli);
2266 TALLOC_FREE(mem_ctx);
2267 return;
2269 talloc_free(domain->name);
2270 domain->name = talloc_strdup(domain,
2271 lsa_info->dns.name.string);
2272 if (domain->name == NULL) {
2273 goto done;
2277 if (lsa_info->dns.dns_domain.string) {
2278 if (domain->alt_name != NULL &&
2279 !strequal(domain->alt_name,
2280 lsa_info->dns.dns_domain.string))
2282 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2283 "for domain %s (%s) claimed it was "
2284 "a DC for domain %s, refusing to "
2285 "initialize\n",
2286 domain->alt_name, domain->name,
2287 lsa_info->dns.dns_domain.string));
2288 TALLOC_FREE(cli);
2289 TALLOC_FREE(mem_ctx);
2290 return;
2292 talloc_free(domain->alt_name);
2293 domain->alt_name =
2294 talloc_strdup(domain,
2295 lsa_info->dns.dns_domain.string);
2296 if (domain->alt_name == NULL) {
2297 goto done;
2301 /* See if we can set some domain trust flags about
2302 ourself */
2304 if (lsa_info->dns.dns_forest.string) {
2305 talloc_free(domain->forest_name);
2306 domain->forest_name =
2307 talloc_strdup(domain,
2308 lsa_info->dns.dns_forest.string);
2309 if (domain->forest_name == NULL) {
2310 goto done;
2313 if (strequal(domain->forest_name, domain->alt_name)) {
2314 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2318 if (lsa_info->dns.sid) {
2319 if (!is_null_sid(&domain->sid) &&
2320 !dom_sid_equal(&domain->sid,
2321 lsa_info->dns.sid))
2323 struct dom_sid_buf buf1, buf2;
2324 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2325 "for domain %s (%s) claimed it was "
2326 "a DC for domain %s, refusing to "
2327 "initialize\n",
2328 dom_sid_str_buf(&domain->sid, &buf1),
2329 domain->name,
2330 dom_sid_str_buf(lsa_info->dns.sid,
2331 &buf2)));
2332 TALLOC_FREE(cli);
2333 TALLOC_FREE(mem_ctx);
2334 return;
2336 sid_copy(&domain->sid, lsa_info->dns.sid);
2338 } else {
2339 domain->active_directory = False;
2341 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2342 SEC_FLAG_MAXIMUM_ALLOWED,
2343 &pol);
2345 if (!NT_STATUS_IS_OK(status)) {
2346 goto done;
2349 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2350 &pol,
2351 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2352 &lsa_info,
2353 &result);
2354 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2356 if (lsa_info->account_domain.name.string) {
2357 if (!strequal(domain->name,
2358 lsa_info->account_domain.name.string))
2360 DEBUG(1,
2361 ("set_dc_type_and_flags_connect: "
2362 "DC for domain %s claimed it was"
2363 " a DC for domain %s, refusing "
2364 "to initialize\n", domain->name,
2365 lsa_info->
2366 account_domain.name.string));
2367 TALLOC_FREE(cli);
2368 TALLOC_FREE(mem_ctx);
2369 return;
2371 talloc_free(domain->name);
2372 domain->name =
2373 talloc_strdup(domain,
2374 lsa_info->account_domain.name.string);
2377 if (lsa_info->account_domain.sid) {
2378 if (!is_null_sid(&domain->sid) &&
2379 !dom_sid_equal(&domain->sid,
2380 lsa_info->account_domain.sid))
2382 struct dom_sid_buf buf1, buf2;
2383 DEBUG(1,
2384 ("set_dc_type_and_flags_connect: "
2385 "DC for domain %s (%s) claimed "
2386 "it was a DC for domain %s, "
2387 "refusing to initialize\n",
2388 dom_sid_str_buf(
2389 &domain->sid, &buf1),
2390 domain->name,
2391 dom_sid_str_buf(
2392 lsa_info->account_domain.sid,
2393 &buf2)));
2394 TALLOC_FREE(cli);
2395 TALLOC_FREE(mem_ctx);
2396 return;
2398 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2402 done:
2403 if (is_valid_policy_hnd(&pol)) {
2404 dcerpc_lsa_Close(cli->binding_handle,
2405 mem_ctx,
2406 &pol,
2407 &close_status);
2410 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2411 domain->name, domain->active_directory ? "" : "NOT "));
2413 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2415 TALLOC_FREE(cli);
2417 TALLOC_FREE(mem_ctx);
2419 domain->initialized = True;
2422 /**********************************************************************
2423 Set the domain_flags (trust attributes, domain operating modes, etc...
2424 ***********************************************************************/
2426 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2428 if (IS_DC) {
2430 * On a DC we loaded all trusts
2431 * from configuration and never learn
2432 * new domains.
2434 return;
2437 /* we always have to contact our primary domain */
2438 if (domain->primary || domain->internal) {
2440 * primary and internal domains are
2441 * are already completely
2442 * setup via init_domain_list()
2443 * calling add_trusted_domain()
2445 * There's no need to ask the
2446 * server again, if it hosts an AD
2447 * domain...
2449 domain->initialized = true;
2450 return;
2453 /* Use our DC to get the information if possible */
2455 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2456 /* Otherwise, fallback to contacting the
2457 domain directly */
2458 set_dc_type_and_flags_connect( domain );
2461 return;
2466 /**********************************************************************
2467 ***********************************************************************/
2469 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2470 struct netlogon_creds_cli_context **ppdc)
2472 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2473 struct rpc_pipe_client *netlogon_pipe;
2475 *ppdc = NULL;
2477 if ((!IS_DC) && (!domain->primary)) {
2478 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2481 if (domain->conn.netlogon_creds_ctx != NULL) {
2482 *ppdc = domain->conn.netlogon_creds_ctx;
2483 return NT_STATUS_OK;
2486 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2487 if (!NT_STATUS_IS_OK(result)) {
2488 return result;
2491 return NT_STATUS_OK;
2494 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2495 bool need_rw_dc,
2496 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2498 struct winbindd_cm_conn *conn;
2499 NTSTATUS status, result;
2500 struct netlogon_creds_cli_context *p_creds;
2501 struct cli_credentials *creds = NULL;
2502 bool retry = false; /* allow one retry attempt for expired session */
2503 const char *remote_name = NULL;
2504 const struct sockaddr_storage *remote_sockaddr = NULL;
2505 bool sealed_pipes = true;
2506 bool strong_key = true;
2508 if (sid_check_is_our_sam(&domain->sid)) {
2509 if (domain->rodc == false || need_rw_dc == false) {
2510 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2514 if (IS_AD_DC) {
2516 * In theory we should not use SAMR within
2517 * winbindd at all, but that's a larger task to
2518 * remove this and avoid breaking existing
2519 * setups.
2521 * At least as AD DC we have the restriction
2522 * to avoid SAMR against trusted domains,
2523 * as there're no existing setups.
2525 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2528 retry:
2529 status = init_dc_connection_rpc(domain, need_rw_dc);
2530 if (!NT_STATUS_IS_OK(status)) {
2531 return status;
2534 conn = &domain->conn;
2536 if (rpccli_is_connected(conn->samr_pipe)) {
2537 goto done;
2540 TALLOC_FREE(conn->samr_pipe);
2543 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2544 * sign and sealed pipe using the machine account password by
2545 * preference. If we can't - try schannel, if that fails, try
2546 * anonymous.
2549 result = winbindd_get_trust_credentials(domain,
2550 talloc_tos(),
2551 false, /* netlogon */
2552 true, /* ipc_fallback */
2553 &creds);
2554 if (!NT_STATUS_IS_OK(result)) {
2555 DEBUG(10, ("cm_connect_sam: No user available for "
2556 "domain %s, trying schannel\n", domain->name));
2557 goto schannel;
2560 if (cli_credentials_is_anonymous(creds)) {
2561 goto anonymous;
2564 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2565 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2568 * We have an authenticated connection. Use a SPNEGO
2569 * authenticated SAMR pipe with sign & seal.
2571 status = cli_rpc_pipe_open_with_creds(conn->cli,
2572 &ndr_table_samr,
2573 NCACN_NP,
2574 DCERPC_AUTH_TYPE_SPNEGO,
2575 conn->auth_level,
2576 NULL, /* target_service */
2577 remote_name,
2578 remote_sockaddr,
2579 creds,
2580 &conn->samr_pipe);
2582 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2583 && !retry) {
2584 invalidate_cm_connection(domain);
2585 retry = true;
2586 goto retry;
2589 if (!NT_STATUS_IS_OK(status)) {
2590 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2591 "pipe for domain %s using NTLMSSP "
2592 "authenticated pipe: user %s. Error was "
2593 "%s\n", domain->name,
2594 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2595 nt_errstr(status)));
2596 goto schannel;
2599 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2600 "domain %s using NTLMSSP authenticated "
2601 "pipe: user %s\n", domain->name,
2602 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2604 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2605 conn->samr_pipe->desthost,
2606 SEC_FLAG_MAXIMUM_ALLOWED,
2607 &conn->sam_connect_handle,
2608 &result);
2610 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2611 invalidate_cm_connection(domain);
2612 TALLOC_FREE(conn->samr_pipe);
2613 retry = true;
2614 goto retry;
2617 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2618 goto open_domain;
2620 if (NT_STATUS_IS_OK(status)) {
2621 status = result;
2624 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2625 "failed for domain %s, error was %s. Trying schannel\n",
2626 domain->name, nt_errstr(status) ));
2627 TALLOC_FREE(conn->samr_pipe);
2629 schannel:
2631 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2633 status = cm_get_schannel_creds(domain, &p_creds);
2634 if (!NT_STATUS_IS_OK(status)) {
2635 /* If this call fails - conn->cli can now be NULL ! */
2636 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2637 "for domain %s (error %s), trying anon\n",
2638 domain->name,
2639 nt_errstr(status) ));
2640 goto anonymous;
2642 TALLOC_FREE(creds);
2643 status = cli_rpc_pipe_open_schannel_with_creds(
2644 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2645 remote_name,
2646 remote_sockaddr,
2647 &conn->samr_pipe);
2649 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2650 && !retry) {
2651 invalidate_cm_connection(domain);
2652 retry = true;
2653 goto retry;
2656 if (!NT_STATUS_IS_OK(status)) {
2657 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2658 "domain %s using schannel. Error was %s\n",
2659 domain->name, nt_errstr(status) ));
2660 goto anonymous;
2662 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2663 "schannel.\n", domain->name ));
2665 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2666 conn->samr_pipe->desthost,
2667 SEC_FLAG_MAXIMUM_ALLOWED,
2668 &conn->sam_connect_handle,
2669 &result);
2671 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2672 invalidate_cm_connection(domain);
2673 TALLOC_FREE(conn->samr_pipe);
2674 retry = true;
2675 goto retry;
2678 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2679 goto open_domain;
2681 if (NT_STATUS_IS_OK(status)) {
2682 status = result;
2684 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2685 "for domain %s, error was %s. Trying anonymous\n",
2686 domain->name, nt_errstr(status) ));
2687 TALLOC_FREE(conn->samr_pipe);
2689 anonymous:
2691 sealed_pipes = lp_winbind_sealed_pipes();
2692 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2693 domain->name,
2694 sealed_pipes);
2695 strong_key = lp_require_strong_key();
2696 strong_key = lp_parm_bool(-1, "require strong key",
2697 domain->name,
2698 strong_key);
2700 /* Finally fall back to anonymous. */
2701 if (sealed_pipes || strong_key) {
2702 status = NT_STATUS_DOWNGRADE_DETECTED;
2703 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2704 "without connection level security, "
2705 "must set 'winbind sealed pipes:%s = false' and "
2706 "'require strong key:%s = false' to proceed: %s\n",
2707 domain->name, domain->name, domain->name,
2708 nt_errstr(status)));
2709 goto done;
2711 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
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 goto done;
2725 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2726 conn->samr_pipe->desthost,
2727 SEC_FLAG_MAXIMUM_ALLOWED,
2728 &conn->sam_connect_handle,
2729 &result);
2731 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2732 invalidate_cm_connection(domain);
2733 TALLOC_FREE(conn->samr_pipe);
2734 retry = true;
2735 goto retry;
2738 if (!NT_STATUS_IS_OK(status)) {
2739 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2740 "for domain %s Error was %s\n",
2741 domain->name, nt_errstr(status) ));
2742 goto done;
2744 if (!NT_STATUS_IS_OK(result)) {
2745 status = result;
2746 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2747 "for domain %s Error was %s\n",
2748 domain->name, nt_errstr(result)));
2749 goto done;
2752 open_domain:
2753 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2754 mem_ctx,
2755 &conn->sam_connect_handle,
2756 SEC_FLAG_MAXIMUM_ALLOWED,
2757 &domain->sid,
2758 &conn->sam_domain_handle,
2759 &result);
2760 if (!NT_STATUS_IS_OK(status)) {
2761 goto done;
2764 status = result;
2765 done:
2767 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2769 * if we got access denied, we might just have no access rights
2770 * to talk to the remote samr server server (e.g. when we are a
2771 * PDC and we are connecting a w2k8 pdc via an interdomain
2772 * trust). In that case do not invalidate the whole connection
2773 * stack
2775 TALLOC_FREE(conn->samr_pipe);
2776 ZERO_STRUCT(conn->sam_domain_handle);
2777 return status;
2778 } else if (!NT_STATUS_IS_OK(status)) {
2779 invalidate_cm_connection(domain);
2780 return status;
2783 *cli = conn->samr_pipe;
2784 *sam_handle = conn->sam_domain_handle;
2785 return status;
2788 /**********************************************************************
2789 open an schanneld ncacn_ip_tcp connection to LSA
2790 ***********************************************************************/
2792 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2793 TALLOC_CTX *mem_ctx,
2794 struct rpc_pipe_client **cli)
2796 struct winbindd_cm_conn *conn;
2797 struct netlogon_creds_cli_context *p_creds = NULL;
2798 NTSTATUS status;
2799 const char *remote_name = NULL;
2800 const struct sockaddr_storage *remote_sockaddr = NULL;
2802 DEBUG(10,("cm_connect_lsa_tcp\n"));
2804 status = init_dc_connection_rpc(domain, false);
2805 if (!NT_STATUS_IS_OK(status)) {
2806 return status;
2809 conn = &domain->conn;
2812 * rpccli_is_connected handles more error cases
2814 if (rpccli_is_connected(conn->lsa_pipe_tcp)) {
2815 goto done;
2818 TALLOC_FREE(conn->lsa_pipe_tcp);
2820 status = cm_get_schannel_creds(domain, &p_creds);
2821 if (!NT_STATUS_IS_OK(status)) {
2822 goto done;
2825 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2826 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2828 status = cli_rpc_pipe_open_schannel_with_creds(
2829 conn->cli,
2830 &ndr_table_lsarpc,
2831 NCACN_IP_TCP,
2832 p_creds,
2833 remote_name,
2834 remote_sockaddr,
2835 &conn->lsa_pipe_tcp);
2836 if (!NT_STATUS_IS_OK(status)) {
2837 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2838 nt_errstr(status)));
2839 goto done;
2842 done:
2843 if (!NT_STATUS_IS_OK(status)) {
2844 TALLOC_FREE(conn->lsa_pipe_tcp);
2845 return status;
2848 *cli = conn->lsa_pipe_tcp;
2850 return status;
2853 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2854 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2856 struct winbindd_cm_conn *conn;
2857 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2858 struct netlogon_creds_cli_context *p_creds;
2859 struct cli_credentials *creds = NULL;
2860 bool retry = false; /* allow one retry attempt for expired session */
2861 const char *remote_name = NULL;
2862 const struct sockaddr_storage *remote_sockaddr = NULL;
2863 bool sealed_pipes = true;
2864 bool strong_key = true;
2865 bool require_schannel = false;
2867 retry:
2868 result = init_dc_connection_rpc(domain, false);
2869 if (!NT_STATUS_IS_OK(result))
2870 return result;
2872 conn = &domain->conn;
2874 if (rpccli_is_connected(conn->lsa_pipe)) {
2875 goto done;
2878 TALLOC_FREE(conn->lsa_pipe);
2880 if (IS_DC ||
2881 domain->secure_channel_type != SEC_CHAN_NULL)
2884 * Make sure we only use schannel as DC
2885 * or with a direct trust
2887 require_schannel = true;
2888 goto schannel;
2891 result = winbindd_get_trust_credentials(domain,
2892 talloc_tos(),
2893 false, /* netlogon */
2894 true, /* ipc_fallback */
2895 &creds);
2896 if (!NT_STATUS_IS_OK(result)) {
2897 DEBUG(10, ("cm_connect_lsa: No user available for "
2898 "domain %s, trying schannel\n", domain->name));
2899 goto schannel;
2902 if (cli_credentials_is_anonymous(creds)) {
2903 goto anonymous;
2906 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2907 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2910 * We have an authenticated connection. Use a SPNEGO
2911 * authenticated LSA pipe with sign & seal.
2913 result = cli_rpc_pipe_open_with_creds
2914 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2915 DCERPC_AUTH_TYPE_SPNEGO,
2916 conn->auth_level,
2917 NULL, /* target_service */
2918 remote_name,
2919 remote_sockaddr,
2920 creds,
2921 &conn->lsa_pipe);
2923 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
2924 && !retry) {
2925 invalidate_cm_connection(domain);
2926 retry = true;
2927 goto retry;
2930 if (!NT_STATUS_IS_OK(result)) {
2931 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2932 "domain %s using NTLMSSP authenticated pipe: user "
2933 "%s. Error was %s. Trying schannel.\n",
2934 domain->name,
2935 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2936 nt_errstr(result)));
2937 goto schannel;
2940 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2941 "NTLMSSP authenticated pipe: user %s\n",
2942 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
2944 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2945 SEC_FLAG_MAXIMUM_ALLOWED,
2946 &conn->lsa_policy);
2947 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2948 invalidate_cm_connection(domain);
2949 TALLOC_FREE(conn->lsa_pipe);
2950 retry = true;
2951 goto retry;
2954 if (NT_STATUS_IS_OK(result)) {
2955 goto done;
2958 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2959 "schannel\n"));
2961 TALLOC_FREE(conn->lsa_pipe);
2963 schannel:
2965 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2967 result = cm_get_schannel_creds(domain, &p_creds);
2968 if (!NT_STATUS_IS_OK(result)) {
2969 /* If this call fails - conn->cli can now be NULL ! */
2970 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2971 "for domain %s (error %s), trying anon\n",
2972 domain->name,
2973 nt_errstr(result) ));
2974 goto anonymous;
2977 TALLOC_FREE(creds);
2978 result = cli_rpc_pipe_open_schannel_with_creds(
2979 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
2980 remote_name,
2981 remote_sockaddr,
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 schannel. Error was %s\n",
2994 domain->name, nt_errstr(result) ));
2995 goto anonymous;
2997 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2998 "schannel.\n", domain->name ));
3000 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3001 SEC_FLAG_MAXIMUM_ALLOWED,
3002 &conn->lsa_policy);
3004 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3005 invalidate_cm_connection(domain);
3006 TALLOC_FREE(conn->lsa_pipe);
3007 retry = true;
3008 goto retry;
3011 if (NT_STATUS_IS_OK(result)) {
3012 goto done;
3015 if (require_schannel) {
3017 * Make sure we only use schannel as DC
3018 * or with a direct trust
3020 goto done;
3023 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3024 "anonymous\n"));
3026 TALLOC_FREE(conn->lsa_pipe);
3028 anonymous:
3030 if (require_schannel) {
3032 * Make sure we only use schannel as DC
3033 * or with a direct trust
3035 goto done;
3038 sealed_pipes = lp_winbind_sealed_pipes();
3039 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
3040 domain->name,
3041 sealed_pipes);
3042 strong_key = lp_require_strong_key();
3043 strong_key = lp_parm_bool(-1, "require strong key",
3044 domain->name,
3045 strong_key);
3047 /* Finally fall back to anonymous. */
3048 if (sealed_pipes || strong_key) {
3049 result = NT_STATUS_DOWNGRADE_DETECTED;
3050 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3051 "without connection level security, "
3052 "must set 'winbind sealed pipes:%s = false' and "
3053 "'require strong key:%s = false' to proceed: %s\n",
3054 domain->name, domain->name, domain->name,
3055 nt_errstr(result)));
3056 goto done;
3059 result = cli_rpc_pipe_open_noauth(conn->cli,
3060 &ndr_table_lsarpc,
3061 &conn->lsa_pipe);
3063 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3064 && !retry) {
3065 invalidate_cm_connection(domain);
3066 retry = true;
3067 goto retry;
3070 if (!NT_STATUS_IS_OK(result)) {
3071 goto done;
3074 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3075 SEC_FLAG_MAXIMUM_ALLOWED,
3076 &conn->lsa_policy);
3078 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3079 invalidate_cm_connection(domain);
3080 TALLOC_FREE(conn->lsa_pipe);
3081 retry = true;
3082 goto retry;
3085 done:
3086 if (!NT_STATUS_IS_OK(result)) {
3087 invalidate_cm_connection(domain);
3088 return result;
3091 *cli = conn->lsa_pipe;
3092 *lsa_policy = conn->lsa_policy;
3093 return result;
3096 /****************************************************************************
3097 Open a LSA connection to a DC, suitable for LSA lookup calls.
3098 ****************************************************************************/
3100 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3101 TALLOC_CTX *mem_ctx,
3102 struct rpc_pipe_client **cli,
3103 struct policy_handle *lsa_policy)
3105 NTSTATUS status;
3107 if (domain->can_do_ncacn_ip_tcp) {
3108 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3109 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3110 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3111 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3112 invalidate_cm_connection(domain);
3113 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3115 if (NT_STATUS_IS_OK(status)) {
3116 return status;
3120 * we tried twice to connect via ncan_ip_tcp and schannel and
3121 * failed - maybe it is a trusted domain we can't connect to ?
3122 * do not try tcp next time - gd
3124 * This also prevents NETLOGON over TCP
3126 domain->can_do_ncacn_ip_tcp = false;
3129 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3131 return status;
3134 /****************************************************************************
3135 Open the netlogon pipe to this DC.
3136 ****************************************************************************/
3138 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3139 enum dcerpc_transport_t transport,
3140 struct rpc_pipe_client **cli)
3142 struct messaging_context *msg_ctx = global_messaging_context();
3143 struct winbindd_cm_conn *conn;
3144 NTSTATUS result;
3145 enum netr_SchannelType sec_chan_type;
3146 struct cli_credentials *creds = NULL;
3147 const char *remote_name = NULL;
3148 const struct sockaddr_storage *remote_sockaddr = NULL;
3150 *cli = NULL;
3152 if (IS_DC) {
3153 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3155 * Make sure we don't even try to
3156 * connect to a foreign domain
3157 * without a direct outbound trust.
3159 return NT_STATUS_NO_TRUST_LSA_SECRET;
3163 result = init_dc_connection_rpc(domain, domain->rodc);
3164 if (!NT_STATUS_IS_OK(result)) {
3165 return result;
3168 conn = &domain->conn;
3170 if (rpccli_is_connected(conn->netlogon_pipe)) {
3171 *cli = conn->netlogon_pipe;
3172 return NT_STATUS_OK;
3175 TALLOC_FREE(conn->netlogon_pipe);
3176 TALLOC_FREE(conn->netlogon_creds_ctx);
3178 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
3179 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
3181 result = winbindd_get_trust_credentials(domain,
3182 talloc_tos(),
3183 true, /* netlogon */
3184 false, /* ipc_fallback */
3185 &creds);
3186 if (!NT_STATUS_IS_OK(result)) {
3187 DBG_DEBUG("No user available for domain %s when trying "
3188 "schannel\n", domain->name);
3189 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3192 if (cli_credentials_is_anonymous(creds)) {
3193 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3194 "unable to make get NETLOGON credentials\n",
3195 domain->name);
3196 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3199 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3200 if (sec_chan_type == SEC_CHAN_NULL) {
3201 if (transport == NCACN_IP_TCP) {
3202 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3203 "for %s, deny NCACN_IP_TCP and let the "
3204 "caller fallback to NCACN_NP.\n",
3205 domain->name);
3206 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3209 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3210 "fallback to noauth on NCACN_NP.\n",
3211 domain->name);
3213 result = cli_rpc_pipe_open_noauth_transport(
3214 conn->cli,
3215 transport,
3216 &ndr_table_netlogon,
3217 remote_name,
3218 remote_sockaddr,
3219 &conn->netlogon_pipe);
3220 if (!NT_STATUS_IS_OK(result)) {
3221 invalidate_cm_connection(domain);
3222 return result;
3225 *cli = conn->netlogon_pipe;
3226 return NT_STATUS_OK;
3229 result = rpccli_create_netlogon_creds_ctx(creds,
3230 domain->dcname,
3231 msg_ctx,
3232 domain,
3233 &conn->netlogon_creds_ctx);
3234 if (!NT_STATUS_IS_OK(result)) {
3235 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3236 "unable to create NETLOGON credentials: %s\n",
3237 domain->name, nt_errstr(result)));
3238 return result;
3241 result = rpccli_connect_netlogon(conn->cli,
3242 transport,
3243 remote_name,
3244 remote_sockaddr,
3245 conn->netlogon_creds_ctx,
3246 conn->netlogon_force_reauth, creds,
3247 &conn->netlogon_pipe);
3248 conn->netlogon_force_reauth = false;
3249 if (!NT_STATUS_IS_OK(result)) {
3250 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3251 nt_errstr(result));
3252 return result;
3255 *cli = conn->netlogon_pipe;
3256 return NT_STATUS_OK;
3259 /****************************************************************************
3260 Open a NETLOGON connection to a DC, suitable for SamLogon calls.
3261 ****************************************************************************/
3263 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3264 struct rpc_pipe_client **cli)
3266 NTSTATUS status;
3268 status = init_dc_connection_rpc(domain, domain->rodc);
3269 if (!NT_STATUS_IS_OK(status)) {
3270 return status;
3273 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3274 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3275 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3276 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3277 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3278 invalidate_cm_connection(domain);
3279 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3281 if (NT_STATUS_IS_OK(status)) {
3282 return status;
3286 * we tried twice to connect via ncan_ip_tcp and schannel and
3287 * failed - maybe it is a trusted domain we can't connect to ?
3288 * do not try tcp next time - gd
3290 * This also prevents LSA over TCP
3292 domain->can_do_ncacn_ip_tcp = false;
3295 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3296 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3298 * SMB2 session expired, needs reauthentication. Drop
3299 * connection and retry.
3301 invalidate_cm_connection(domain);
3302 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3305 return status;
3308 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3309 struct rpc_pipe_client **cli,
3310 struct netlogon_creds_cli_context **ppdc)
3312 NTSTATUS status;
3314 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3315 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3318 status = cm_connect_netlogon(domain, cli);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 return status;
3323 if (domain->conn.netlogon_creds_ctx == NULL) {
3324 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3327 *ppdc = domain->conn.netlogon_creds_ctx;
3328 return NT_STATUS_OK;
3331 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3332 void *private_data,
3333 uint32_t msg_type,
3334 struct server_id server_id,
3335 DATA_BLOB *data)
3337 struct winbindd_domain *domain;
3338 char *freeit = NULL;
3339 char *addr;
3341 if ((data == NULL)
3342 || (data->data == NULL)
3343 || (data->length == 0)
3344 || (data->data[data->length-1] != '\0')) {
3345 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3346 "string\n"));
3347 return;
3350 addr = (char *)data->data;
3351 DEBUG(10, ("IP %s dropped\n", addr));
3353 if (!is_ipaddress(addr)) {
3354 char *slash;
3356 * Some code sends us ip addresses with the /netmask
3357 * suffix
3359 slash = strchr(addr, '/');
3360 if (slash == NULL) {
3361 DEBUG(1, ("invalid msg_ip_dropped message: %s\n",
3362 addr));
3363 return;
3365 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3366 if (freeit == NULL) {
3367 DEBUG(1, ("talloc failed\n"));
3368 return;
3370 addr = freeit;
3371 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3374 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3375 char sockaddr[INET6_ADDRSTRLEN];
3377 if (!cli_state_is_connected(domain->conn.cli)) {
3378 continue;
3381 print_sockaddr(sockaddr, sizeof(sockaddr),
3382 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3384 if (strequal(sockaddr, addr)) {
3385 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3388 TALLOC_FREE(freeit);
3391 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3392 void *private_data,
3393 uint32_t msg_type,
3394 struct server_id server_id,
3395 DATA_BLOB *data)
3397 struct winbindd_domain *domain;
3399 for (domain = domain_list(); domain; domain = domain->next) {
3400 if (domain->internal) {
3401 continue;
3403 invalidate_cm_connection(domain);