s3: smbd: Remove unused and commented out check_path_syntax_smb2_msdfs().
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob264fc1368d64519ce6e1acc71c6c84d0a49300c3
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 DEBUG(0, ("talloc_strdup failed\n"));
544 talloc_destroy(mem_ctx);
545 return false;
547 if (domain->alt_name == NULL) {
548 domain->alt_name = talloc_strdup(domain,
549 domain_info->domain_name);
550 if (domain->alt_name == NULL) {
551 DEBUG(0, ("talloc_strdup failed\n"));
552 talloc_destroy(mem_ctx);
553 return false;
556 if (domain->forest_name == NULL) {
557 domain->forest_name = talloc_strdup(domain,
558 domain_info->forest_name);
559 if (domain->forest_name == NULL) {
560 DEBUG(0, ("talloc_strdup failed\n"));
561 talloc_destroy(mem_ctx);
562 return false;
566 } else {
567 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
568 our_domain->dcname,
569 domain->name,
570 &tmp,
571 &werr);
574 /* And restore our original timeout. */
575 rpccli_set_timeout(netlogon_pipe, orig_timeout);
577 if (!NT_STATUS_IS_OK(result)) {
578 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
579 nt_errstr(result)));
580 talloc_destroy(mem_ctx);
581 return false;
584 if (!W_ERROR_IS_OK(werr)) {
585 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
586 win_errstr(werr)));
587 talloc_destroy(mem_ctx);
588 return false;
591 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
592 p = strip_hostname(tmp);
594 fstrcpy(dcname, p);
596 talloc_destroy(mem_ctx);
598 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
600 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
601 return False;
604 return True;
608 * Helper function to assemble trust password and account name
610 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
611 TALLOC_CTX *mem_ctx,
612 bool netlogon,
613 struct cli_credentials **_creds)
615 const struct winbindd_domain *creds_domain = NULL;
616 struct cli_credentials *creds;
617 NTSTATUS status;
618 bool force_machine_account = false;
620 /* If we are a DC and this is not our own domain */
622 if (!domain->active_directory) {
623 if (!netlogon) {
625 * For non active directory domains
626 * we can only use NTLMSSP for SMB.
628 * But the trust account is not allowed
629 * to use SMB with NTLMSSP.
631 force_machine_account = true;
635 if (IS_DC && !force_machine_account) {
636 creds_domain = domain;
637 } else {
638 creds_domain = find_our_domain();
639 if (creds_domain == NULL) {
640 return NT_STATUS_INVALID_SERVER_STATE;
644 status = pdb_get_trust_credentials(creds_domain->name,
645 creds_domain->alt_name,
646 mem_ctx,
647 &creds);
648 if (!NT_STATUS_IS_OK(status)) {
649 goto ipc_fallback;
652 if (creds_domain != domain) {
654 * We can only use schannel against a direct trust
656 cli_credentials_set_secure_channel_type(creds,
657 SEC_CHAN_NULL);
660 *_creds = creds;
661 return NT_STATUS_OK;
663 ipc_fallback:
664 if (netlogon) {
665 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
668 status = cm_get_ipc_credentials(mem_ctx, &creds);
669 if (!NT_STATUS_IS_OK(status)) {
670 return status;
673 *_creds = creds;
674 return NT_STATUS_OK;
677 /************************************************************************
678 Given a fd with a just-connected TCP connection to a DC, open a connection
679 to the pipe.
680 ************************************************************************/
682 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
683 const int sockfd,
684 const char *controller,
685 struct cli_state **cli,
686 bool *retry)
688 bool try_ipc_auth = false;
689 const char *machine_principal = NULL;
690 const char *machine_realm = NULL;
691 const char *machine_account = NULL;
692 const char *machine_domain = NULL;
693 int flags = 0;
694 struct cli_credentials *creds = NULL;
696 struct named_mutex *mutex;
698 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
699 NTSTATUS tmp_status;
700 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
702 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
704 if (IS_AD_DC) {
705 if (domain->secure_channel_type == SEC_CHAN_NULL) {
707 * Make sure we don't even try to
708 * connect to a foreign domain
709 * without a direct outbound trust.
711 return NT_STATUS_NO_TRUST_LSA_SECRET;
715 * As AD DC we only use netlogon and lsa
716 * using schannel over an anonymous transport
717 * (ncacn_ip_tcp or ncacn_np).
719 * Currently we always establish the SMB connection,
720 * even if we don't use it, because we later use ncacn_ip_tcp.
722 * As we won't use the SMB connection there's no
723 * need to try kerberos. And NT4 domains expect
724 * an anonymous IPC$ connection anyway.
726 smb_sign_client_connections = SMB_SIGNING_OFF;
729 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
731 * If we are connecting to our own AD domain, require
732 * smb signing to disrupt MITM attacks
734 if (domain->primary && lp_security() == SEC_ADS) {
735 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
737 * If we are in or are an AD domain and connecting to another
738 * AD domain in our forest
739 * then require smb signing to disrupt MITM attacks
741 } else if ((lp_security() == SEC_ADS)
742 && domain->active_directory
743 && (domain->domain_trust_attribs
744 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
745 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
749 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
750 controller, domain->name ));
752 *retry = True;
754 mutex = grab_named_mutex(talloc_tos(), controller,
755 WINBIND_SERVER_MUTEX_WAIT_TIME);
756 if (mutex == NULL) {
757 close(sockfd);
758 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
759 controller));
760 result = NT_STATUS_POSSIBLE_DEADLOCK;
761 goto done;
764 *cli = cli_state_create(NULL, sockfd, controller,
765 smb_sign_client_connections, flags);
766 if (*cli == NULL) {
767 close(sockfd);
768 DEBUG(1, ("Could not cli_initialize\n"));
769 result = NT_STATUS_NO_MEMORY;
770 goto done;
773 cli_set_timeout(*cli, 10000); /* 10 seconds */
775 set_socket_options(sockfd, lp_socket_options());
777 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
778 lp_client_ipc_min_protocol(),
779 lp_client_ipc_max_protocol());
781 if (!NT_STATUS_IS_OK(result)) {
782 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
783 goto done;
786 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
787 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
788 try_ipc_auth = true;
789 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
790 try_ipc_auth = true;
791 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
793 * If we are forcing on SMB signing, then we must
794 * require authentication unless this is a one-way
795 * trust, and we have no stored user/password
797 try_ipc_auth = true;
800 if (IS_AD_DC) {
802 * As AD DC we only use netlogon and lsa
803 * using schannel over an anonymous transport
804 * (ncacn_ip_tcp or ncacn_np).
806 * Currently we always establish the SMB connection,
807 * even if we don't use it, because we later use ncacn_ip_tcp.
809 * As we won't use the SMB connection there's no
810 * need to try kerberos. And NT4 domains expect
811 * an anonymous IPC$ connection anyway.
813 try_ipc_auth = false;
816 if (try_ipc_auth) {
817 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
818 if (!NT_STATUS_IS_OK(result)) {
819 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
820 domain->name, nt_errstr(result)));
821 goto done;
823 } else {
825 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
826 * would try and authentication with our machine
827 * account password and fail. This is very rare in
828 * the modern world however
830 creds = cli_credentials_init_anon(talloc_tos());
831 if (creds == NULL) {
832 result = NT_STATUS_NO_MEMORY;
833 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
834 domain->name, nt_errstr(result)));
835 goto done;
839 machine_principal = cli_credentials_get_principal(creds,
840 talloc_tos());
841 machine_realm = cli_credentials_get_realm(creds);
842 machine_account = cli_credentials_get_username(creds);
843 machine_domain = cli_credentials_get_domain(creds);
845 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
846 "[%s] and realm [%s]\n",
847 controller, domain->name, domain->alt_name,
848 machine_domain, machine_account,
849 machine_principal, machine_realm));
851 if (cli_credentials_is_anonymous(creds)) {
852 goto anon_fallback;
855 winbindd_set_locator_kdc_envs(domain);
857 result = cli_session_setup_creds(*cli, creds);
858 if (NT_STATUS_IS_OK(result)) {
859 goto session_setup_done;
862 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
863 controller,
864 cli_credentials_get_unparsed_name(creds, talloc_tos()),
865 nt_errstr(result)));
868 * If we are not going to validate the connection
869 * with SMB signing, then allow us to fall back to
870 * anonymous
872 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
873 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
874 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
875 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
876 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
877 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
878 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
880 if (!cm_is_ipc_credentials(creds)) {
881 goto ipc_fallback;
884 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
885 goto done;
888 goto anon_fallback;
891 goto done;
893 ipc_fallback:
894 TALLOC_FREE(creds);
895 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
896 if (!NT_STATUS_IS_OK(tmp_status)) {
897 result = tmp_status;
898 goto done;
901 if (cli_credentials_is_anonymous(creds)) {
902 goto anon_fallback;
905 machine_account = cli_credentials_get_username(creds);
906 machine_domain = cli_credentials_get_domain(creds);
908 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
909 "[%s]\\[%s]\n", controller, lp_netbios_name(),
910 machine_domain, machine_account));
912 result = cli_session_setup_creds(*cli, creds);
913 if (NT_STATUS_IS_OK(result)) {
914 goto session_setup_done;
917 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
918 controller,
919 cli_credentials_get_unparsed_name(creds, talloc_tos()),
920 nt_errstr(result)));
923 * If we are not going to validate the connection
924 * with SMB signing, then allow us to fall back to
925 * anonymous
927 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
928 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
929 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
930 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
931 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
932 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
933 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
935 goto anon_fallback;
938 goto done;
940 anon_fallback:
941 TALLOC_FREE(creds);
943 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
944 goto done;
947 /* Fall back to anonymous connection, this might fail later */
948 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
949 "connection for DC %s\n",
950 controller ));
952 result = cli_session_setup_anon(*cli);
953 if (NT_STATUS_IS_OK(result)) {
954 DEBUG(5, ("Connected anonymously\n"));
955 goto session_setup_done;
958 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
959 controller, nt_errstr(result)));
961 /* We can't session setup */
962 goto done;
964 session_setup_done:
965 TALLOC_FREE(creds);
968 * This should be a short term hack until
969 * dynamic re-authentication is implemented.
971 * See Bug 9175 - winbindd doesn't recover from
972 * NT_STATUS_NETWORK_SESSION_EXPIRED
974 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
975 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
978 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
979 if (!NT_STATUS_IS_OK(result)) {
980 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
981 goto done;
983 tcon_status = result;
985 /* cache the server name for later connections */
987 saf_store(domain->name, controller);
988 if (domain->alt_name) {
989 saf_store(domain->alt_name, controller);
992 winbindd_set_locator_kdc_envs(domain);
994 TALLOC_FREE(mutex);
995 *retry = False;
997 result = NT_STATUS_OK;
999 done:
1000 TALLOC_FREE(mutex);
1001 TALLOC_FREE(creds);
1003 if (NT_STATUS_IS_OK(result)) {
1004 result = tcon_status;
1007 if (!NT_STATUS_IS_OK(result)) {
1008 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1009 controller, nt_errstr(result)));
1010 winbind_add_failed_connection_entry(domain, controller, result);
1011 if ((*cli) != NULL) {
1012 cli_shutdown(*cli);
1013 *cli = NULL;
1017 return result;
1020 /*******************************************************************
1021 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1022 array.
1024 Keeps the list unique by not adding duplicate entries.
1026 @param[in] mem_ctx talloc memory context to allocate from
1027 @param[in] domain_name domain of the DC
1028 @param[in] dcname name of the DC to add to the list
1029 @param[in] pss Internet address and port pair to add to the list
1030 @param[in,out] dcs array of dc_name_ip structures to add to
1031 @param[in,out] num_dcs number of dcs returned in the dcs array
1032 @return true if the list was added to, false otherwise
1033 *******************************************************************/
1035 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1036 const char *dcname, struct sockaddr_storage *pss,
1037 struct dc_name_ip **dcs, int *num)
1039 int i = 0;
1041 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1042 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1043 return False;
1046 /* Make sure there's no duplicates in the list */
1047 for (i=0; i<*num; i++)
1048 if (sockaddr_equal(
1049 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1050 (struct sockaddr *)(void *)pss))
1051 return False;
1053 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1055 if (*dcs == NULL)
1056 return False;
1058 fstrcpy((*dcs)[*num].name, dcname);
1059 (*dcs)[*num].ss = *pss;
1060 *num += 1;
1061 return True;
1064 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1065 struct sockaddr_storage *pss, uint16_t port,
1066 struct sockaddr_storage **addrs, int *num)
1068 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1070 if (*addrs == NULL) {
1071 *num = 0;
1072 return False;
1075 (*addrs)[*num] = *pss;
1076 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1078 *num += 1;
1079 return True;
1082 #ifdef HAVE_ADS
1083 static bool dcip_check_name_ads(const struct winbindd_domain *domain,
1084 struct samba_sockaddr *sa,
1085 uint32_t request_flags,
1086 TALLOC_CTX *mem_ctx,
1087 char **namep)
1089 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1090 char *name = NULL;
1091 ADS_STRUCT *ads = NULL;
1092 ADS_STATUS ads_status;
1093 char addr[INET6_ADDRSTRLEN];
1095 print_sockaddr(addr, sizeof(addr), &sa->u.ss);
1097 ads = ads_init(tmp_ctx,
1098 domain->alt_name,
1099 domain->name,
1100 addr,
1101 ADS_SASL_PLAIN);
1102 if (ads == NULL) {
1103 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1104 goto out;
1106 ads->auth.flags |= ADS_AUTH_NO_BIND;
1107 ads->config.flags |= request_flags;
1108 ads->server.no_fallback = true;
1110 ads_status = ads_connect(ads);
1111 if (!ADS_ERR_OK(ads_status)) {
1112 goto out;
1115 /* We got a cldap packet. */
1116 name = talloc_strdup(tmp_ctx, ads->config.ldap_server_name);
1117 if (name == NULL) {
1118 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1119 goto out;
1121 namecache_store(name, 0x20, 1, sa);
1123 DBG_DEBUG("CLDAP flags = 0x%"PRIx32"\n", ads->config.flags);
1125 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1126 if (ads_closest_dc(ads)) {
1127 char *sitename = sitename_fetch(tmp_ctx,
1128 ads->config.realm);
1130 /* We're going to use this KDC for this realm/domain.
1131 If we are using sites, then force the krb5 libs
1132 to use this KDC. */
1134 create_local_private_krb5_conf_for_domain(domain->alt_name,
1135 domain->name,
1136 sitename,
1137 &sa->u.ss);
1139 TALLOC_FREE(sitename);
1140 } else {
1141 /* use an off site KDC */
1142 create_local_private_krb5_conf_for_domain(domain->alt_name,
1143 domain->name,
1144 NULL,
1145 &sa->u.ss);
1147 winbindd_set_locator_kdc_envs(domain);
1149 /* Ensure we contact this DC also. */
1150 saf_store(domain->name, name);
1151 saf_store(domain->alt_name, name);
1154 *namep = talloc_move(mem_ctx, &name);
1156 out:
1157 TALLOC_FREE(tmp_ctx);
1159 return ADS_ERR_OK(ads_status) ? true : false;
1161 #endif
1163 /*******************************************************************
1164 convert an ip to a name
1165 For an AD Domain, it checks the requirements of the request flags.
1166 *******************************************************************/
1168 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1169 const struct winbindd_domain *domain,
1170 struct sockaddr_storage *pss,
1171 char **name, uint32_t request_flags)
1173 struct samba_sockaddr sa = {0};
1174 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1175 NTSTATUS status;
1176 const char *dc_name;
1177 fstring nbtname;
1178 #ifdef HAVE_ADS
1179 bool is_ad_domain = false;
1180 #endif
1181 bool ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
1182 if (!ok) {
1183 return false;
1186 #ifdef HAVE_ADS
1187 /* For active directory servers, try to get the ldap server name.
1188 None of these failures should be considered critical for now */
1190 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1191 is_ad_domain = true;
1192 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1193 is_ad_domain = domain->active_directory;
1196 if (is_ad_domain) {
1197 return dcip_check_name_ads(domain,
1198 &sa,
1199 request_flags,
1200 mem_ctx,
1201 name);
1203 #endif
1206 size_t len = strlen(lp_netbios_name());
1207 char my_acct_name[len+2];
1209 snprintf(my_acct_name,
1210 sizeof(my_acct_name),
1211 "%s$",
1212 lp_netbios_name());
1214 status = nbt_getdc(global_messaging_context(), 10, &sa.u.ss,
1215 domain->name, &domain->sid,
1216 my_acct_name, ACB_WSTRUST,
1217 nt_version, mem_ctx, &nt_version,
1218 &dc_name, NULL);
1220 if (NT_STATUS_IS_OK(status)) {
1221 *name = talloc_strdup(mem_ctx, dc_name);
1222 if (*name == NULL) {
1223 return false;
1225 namecache_store(*name, 0x20, 1, &sa);
1226 return True;
1229 /* try node status request */
1231 if (name_status_find(domain->name, 0x1c, 0x20, &sa.u.ss, nbtname) ) {
1232 namecache_store(nbtname, 0x20, 1, &sa);
1234 if (name != NULL) {
1235 *name = talloc_strdup(mem_ctx, nbtname);
1236 if (*name == NULL) {
1237 return false;
1241 return true;
1243 return False;
1246 /*******************************************************************
1247 Retrieve a list of IP addresses for domain controllers.
1249 The array is sorted in the preferred connection order.
1251 @param[in] mem_ctx talloc memory context to allocate from
1252 @param[in] domain domain to retrieve DCs for
1253 @param[out] dcs array of dcs that will be returned
1254 @param[out] num_dcs number of dcs returned in the dcs array
1255 @return always true
1256 *******************************************************************/
1258 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1259 struct dc_name_ip **dcs, int *num_dcs,
1260 uint32_t request_flags)
1262 fstring dcname;
1263 struct sockaddr_storage ss;
1264 struct samba_sockaddr *sa_list = NULL;
1265 size_t salist_size = 0;
1266 size_t i;
1267 bool is_our_domain;
1268 enum security_types sec = (enum security_types)lp_security();
1270 is_our_domain = strequal(domain->name, lp_workgroup());
1272 /* If not our domain, get the preferred DC, by asking our primary DC */
1273 if ( !is_our_domain
1274 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1275 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1276 num_dcs) )
1278 char addr[INET6_ADDRSTRLEN];
1279 print_sockaddr(addr, sizeof(addr), &ss);
1280 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1281 dcname, addr));
1282 return True;
1285 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1286 char *sitename = NULL;
1288 /* We need to make sure we know the local site before
1289 doing any DNS queries, as this will restrict the
1290 get_sorted_dc_list() call below to only fetching
1291 DNS records for the correct site. */
1293 /* Find any DC to get the site record.
1294 We deliberately don't care about the
1295 return here. */
1297 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1299 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1300 if (sitename) {
1302 /* Do the site-specific AD dns lookup first. */
1303 (void)get_sorted_dc_list(mem_ctx,
1304 domain->alt_name,
1305 sitename,
1306 &sa_list,
1307 &salist_size,
1308 true);
1310 /* Add ips to the DC array. We don't look up the name
1311 of the DC in this function, but we fill in the char*
1312 of the ip now to make the failed connection cache
1313 work */
1314 for ( i=0; i<salist_size; i++ ) {
1315 char addr[INET6_ADDRSTRLEN];
1316 print_sockaddr(addr, sizeof(addr),
1317 &sa_list[i].u.ss);
1318 add_one_dc_unique(mem_ctx,
1319 domain->name,
1320 addr,
1321 &sa_list[i].u.ss,
1322 dcs,
1323 num_dcs);
1326 TALLOC_FREE(sa_list);
1327 TALLOC_FREE(sitename);
1328 salist_size = 0;
1331 /* Now we add DCs from the main AD DNS lookup. */
1332 (void)get_sorted_dc_list(mem_ctx,
1333 domain->alt_name,
1334 NULL,
1335 &sa_list,
1336 &salist_size,
1337 true);
1339 for ( i=0; i<salist_size; i++ ) {
1340 char addr[INET6_ADDRSTRLEN];
1341 print_sockaddr(addr, sizeof(addr),
1342 &sa_list[i].u.ss);
1343 add_one_dc_unique(mem_ctx,
1344 domain->name,
1345 addr,
1346 &sa_list[i].u.ss,
1347 dcs,
1348 num_dcs);
1351 TALLOC_FREE(sa_list);
1352 salist_size = 0;
1355 /* Try standard netbios queries if no ADS and fall back to DNS queries
1356 * if alt_name is available */
1357 if (*num_dcs == 0) {
1358 (void)get_sorted_dc_list(mem_ctx,
1359 domain->name,
1360 NULL,
1361 &sa_list,
1362 &salist_size,
1363 false);
1364 if (salist_size == 0) {
1365 if (domain->alt_name != NULL) {
1366 (void)get_sorted_dc_list(mem_ctx,
1367 domain->alt_name,
1368 NULL,
1369 &sa_list,
1370 &salist_size,
1371 true);
1375 for ( i=0; i<salist_size; i++ ) {
1376 char addr[INET6_ADDRSTRLEN];
1377 print_sockaddr(addr, sizeof(addr),
1378 &sa_list[i].u.ss);
1379 add_one_dc_unique(mem_ctx,
1380 domain->name,
1381 addr,
1382 &sa_list[i].u.ss,
1383 dcs,
1384 num_dcs);
1387 TALLOC_FREE(sa_list);
1388 salist_size = 0;
1391 return True;
1394 static bool connect_preferred_dc(TALLOC_CTX *mem_ctx,
1395 struct winbindd_domain *domain,
1396 uint32_t request_flags,
1397 int *fd)
1399 char *saf_servername = NULL;
1400 NTSTATUS status;
1401 bool ok;
1404 * We have to check the server affinity cache here since later we select
1405 * a DC based on response time and not preference.
1407 if (domain->force_dc) {
1408 saf_servername = domain->dcname;
1409 } else {
1410 saf_servername = saf_fetch(mem_ctx, domain->name);
1414 * Check the negative connection cache before talking to it. It going
1415 * down may have triggered the reconnection.
1417 status = check_negative_conn_cache(domain->name, saf_servername);
1418 if (!NT_STATUS_IS_OK(status)) {
1419 saf_servername = NULL;
1422 if (saf_servername != NULL) {
1423 DBG_DEBUG("saf_servername is '%s' for domain %s\n",
1424 saf_servername, domain->name);
1426 /* convert an ip address to a name */
1427 if (is_ipaddress(saf_servername)) {
1428 ok = interpret_string_addr(&domain->dcaddr,
1429 saf_servername,
1430 AI_NUMERICHOST);
1431 if (!ok) {
1432 return false;
1434 } else {
1435 ok = resolve_name(saf_servername,
1436 &domain->dcaddr,
1437 0x20,
1438 true);
1439 if (!ok) {
1440 goto fail;
1444 TALLOC_FREE(domain->dcname);
1445 ok = dcip_check_name(domain,
1446 domain,
1447 &domain->dcaddr,
1448 &domain->dcname,
1449 request_flags);
1450 if (!ok) {
1451 goto fail;
1455 if (domain->dcname == NULL) {
1456 return false;
1459 status = check_negative_conn_cache(domain->name, domain->dcname);
1460 if (!NT_STATUS_IS_OK(status)) {
1461 return false;
1464 status = smbsock_connect(&domain->dcaddr, 0,
1465 NULL, -1, NULL, -1,
1466 fd, NULL, 10);
1467 if (!NT_STATUS_IS_OK(status)) {
1468 goto fail;
1470 return true;
1472 fail:
1473 winbind_add_failed_connection_entry(domain,
1474 saf_servername,
1475 NT_STATUS_UNSUCCESSFUL);
1476 return false;
1480 /*******************************************************************
1481 Find and make a connection to a DC in the given domain.
1483 @param[in] mem_ctx talloc memory context to allocate from
1484 @param[in] domain domain to find a dc in
1485 @param[out] fd fd of the open socket connected to the newly found dc
1486 @return true when a DC connection is made, false otherwise
1487 *******************************************************************/
1489 static bool find_dc(TALLOC_CTX *mem_ctx,
1490 struct winbindd_domain *domain,
1491 uint32_t request_flags,
1492 int *fd)
1494 struct dc_name_ip *dcs = NULL;
1495 int num_dcs = 0;
1497 const char **dcnames = NULL;
1498 size_t num_dcnames = 0;
1500 struct sockaddr_storage *addrs = NULL;
1501 int num_addrs = 0;
1503 int i;
1504 size_t fd_index;
1506 NTSTATUS status;
1507 bool ok;
1509 *fd = -1;
1511 ok = connect_preferred_dc(mem_ctx, domain, request_flags, fd);
1512 if (ok) {
1513 return true;
1516 if (domain->force_dc) {
1517 return false;
1520 again:
1521 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1522 return False;
1524 for (i=0; i<num_dcs; i++) {
1526 if (!add_string_to_array(mem_ctx, dcs[i].name,
1527 &dcnames, &num_dcnames)) {
1528 return False;
1530 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1531 &addrs, &num_addrs)) {
1532 return False;
1536 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1537 return False;
1539 if ((addrs == NULL) || (dcnames == NULL))
1540 return False;
1542 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1543 num_addrs, 0, 10, fd, &fd_index, NULL);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 for (i=0; i<num_dcs; i++) {
1546 char ab[INET6_ADDRSTRLEN];
1547 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1548 DBG_DEBUG("smbsock_any_connect failed for "
1549 "domain %s address %s. Error was %s\n",
1550 domain->name, ab, nt_errstr(status));
1551 winbind_add_failed_connection_entry(domain,
1552 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1554 return False;
1557 domain->dcaddr = addrs[fd_index];
1559 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1560 /* Ok, we've got a name for the DC */
1561 TALLOC_FREE(domain->dcname);
1562 domain->dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1563 if (domain->dcname == NULL) {
1564 return false;
1566 return true;
1569 /* Try to figure out the name */
1570 TALLOC_FREE(domain->dcname);
1571 ok = dcip_check_name(domain,
1572 domain,
1573 &domain->dcaddr,
1574 &domain->dcname,
1575 request_flags);
1576 if (ok) {
1577 return true;
1580 /* We can not continue without the DC's name */
1581 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1582 NT_STATUS_UNSUCCESSFUL);
1584 /* Throw away all arrays as we're doing this again. */
1585 TALLOC_FREE(dcs);
1586 num_dcs = 0;
1588 TALLOC_FREE(dcnames);
1589 num_dcnames = 0;
1591 TALLOC_FREE(addrs);
1592 num_addrs = 0;
1594 if (*fd != -1) {
1595 close(*fd);
1596 *fd = -1;
1599 goto again;
1602 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1604 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1605 domain_name);
1608 static void store_current_dc_in_gencache(const char *domain_name,
1609 const char *dc_name,
1610 struct cli_state *cli)
1612 char addr[INET6_ADDRSTRLEN];
1613 char *key = NULL;
1614 char *value = NULL;
1616 if (!cli_state_is_connected(cli)) {
1617 return;
1620 print_sockaddr(addr, sizeof(addr),
1621 smbXcli_conn_remote_sockaddr(cli->conn));
1623 key = current_dc_key(talloc_tos(), domain_name);
1624 if (key == NULL) {
1625 goto done;
1628 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1629 if (value == NULL) {
1630 goto done;
1633 gencache_set(key, value, 0x7fffffff);
1634 done:
1635 TALLOC_FREE(value);
1636 TALLOC_FREE(key);
1639 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1640 const char *domain_name,
1641 char **p_dc_name, char **p_dc_ip)
1643 char *key, *p;
1644 char *value = NULL;
1645 bool ret = false;
1646 char *dc_name = NULL;
1647 char *dc_ip = NULL;
1649 key = current_dc_key(talloc_tos(), domain_name);
1650 if (key == NULL) {
1651 goto done;
1653 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1654 goto done;
1656 p = strchr(value, ' ');
1657 if (p == NULL) {
1658 goto done;
1660 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1661 if (dc_ip == NULL) {
1662 goto done;
1664 dc_name = talloc_strdup(mem_ctx, p+1);
1665 if (dc_name == NULL) {
1666 goto done;
1669 if (p_dc_ip != NULL) {
1670 *p_dc_ip = dc_ip;
1671 dc_ip = NULL;
1673 if (p_dc_name != NULL) {
1674 *p_dc_name = dc_name;
1675 dc_name = NULL;
1677 ret = true;
1678 done:
1679 TALLOC_FREE(dc_name);
1680 TALLOC_FREE(dc_ip);
1681 TALLOC_FREE(key);
1682 TALLOC_FREE(value);
1683 return ret;
1686 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1687 const struct ndr_interface_table *table,
1688 struct rpc_pipe_client **ret_pipe)
1690 struct rpc_pipe_client *cli = NULL;
1691 const struct auth_session_info *session_info = NULL;
1692 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1695 session_info = get_session_info_system();
1696 SMB_ASSERT(session_info != NULL);
1698 status = rpc_pipe_open_local_np(
1699 mem_ctx, table, NULL, NULL, NULL, NULL, session_info, &cli);
1700 if (!NT_STATUS_IS_OK(status)) {
1701 return status;
1704 if (ret_pipe) {
1705 *ret_pipe = cli;
1708 return NT_STATUS_OK;
1711 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1712 struct winbindd_cm_conn *new_conn,
1713 bool need_rw_dc)
1715 TALLOC_CTX *mem_ctx;
1716 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1717 int retries;
1718 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1719 int fd = -1;
1720 bool retry = false;
1721 bool seal_pipes = true;
1723 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1724 set_domain_offline(domain);
1725 return NT_STATUS_NO_MEMORY;
1728 for (retries = 0; retries < 3; retries++) {
1729 bool found_dc;
1731 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1732 domain->dcname ? domain->dcname : "", domain->name));
1734 found_dc = find_dc(mem_ctx, domain, request_flags, &fd);
1735 if (!found_dc) {
1736 /* This is the one place where we will
1737 set the global winbindd offline state
1738 to true, if a "WINBINDD_OFFLINE" entry
1739 is found in the winbindd cache. */
1740 set_global_winbindd_state_offline();
1741 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1742 break;
1745 new_conn->cli = NULL;
1747 result = cm_prepare_connection(domain, fd, domain->dcname,
1748 &new_conn->cli, &retry);
1749 if (NT_STATUS_IS_OK(result)) {
1750 break;
1752 close(fd);
1753 fd = -1;
1754 if (!retry) {
1755 break;
1759 if (!NT_STATUS_IS_OK(result)) {
1760 /* Ensure we setup the retry handler. */
1761 set_domain_offline(domain);
1762 goto out;
1765 winbindd_set_locator_kdc_envs(domain);
1767 if (domain->online == False) {
1768 /* We're changing state from offline to online. */
1769 set_global_winbindd_state_online();
1771 set_domain_online(domain);
1774 * Much as I hate global state, this seems to be the point
1775 * where we can be certain that we have a proper connection to
1776 * a DC. wbinfo --dc-info needs that information, store it in
1777 * gencache with a looong timeout. This will need revisiting
1778 * once we start to connect to multiple DCs, wbcDcInfo is
1779 * already prepared for that.
1781 store_current_dc_in_gencache(domain->name, domain->dcname,
1782 new_conn->cli);
1784 seal_pipes = lp_winbind_sealed_pipes();
1785 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1786 domain->name,
1787 seal_pipes);
1789 if (seal_pipes) {
1790 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1791 } else {
1792 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1795 out:
1796 talloc_destroy(mem_ctx);
1797 return result;
1800 /* Close down all open pipes on a connection. */
1802 void invalidate_cm_connection(struct winbindd_domain *domain)
1804 NTSTATUS result;
1805 struct winbindd_cm_conn *conn = &domain->conn;
1807 domain->sequence_number = DOM_SEQUENCE_NONE;
1808 domain->last_seq_check = 0;
1809 domain->last_status = NT_STATUS_SERVER_DISABLED;
1811 /* We're closing down a possibly dead
1812 connection. Don't have impossibly long (10s) timeouts. */
1814 if (conn->cli) {
1815 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1818 if (conn->samr_pipe != NULL) {
1819 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1820 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1821 talloc_tos(),
1822 &conn->sam_connect_handle,
1823 &result);
1825 TALLOC_FREE(conn->samr_pipe);
1826 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1827 if (conn->cli) {
1828 cli_set_timeout(conn->cli, 500);
1832 if (conn->lsa_pipe != NULL) {
1833 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1834 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1835 talloc_tos(),
1836 &conn->lsa_policy,
1837 &result);
1839 TALLOC_FREE(conn->lsa_pipe);
1840 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1841 if (conn->cli) {
1842 cli_set_timeout(conn->cli, 500);
1846 if (conn->lsa_pipe_tcp != NULL) {
1847 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1848 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1849 talloc_tos(),
1850 &conn->lsa_policy,
1851 &result);
1853 TALLOC_FREE(conn->lsa_pipe_tcp);
1854 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1855 if (conn->cli) {
1856 cli_set_timeout(conn->cli, 500);
1860 if (conn->netlogon_pipe != NULL) {
1861 TALLOC_FREE(conn->netlogon_pipe);
1862 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1863 if (conn->cli) {
1864 cli_set_timeout(conn->cli, 500);
1868 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1869 TALLOC_FREE(conn->netlogon_creds_ctx);
1871 if (conn->cli) {
1872 cli_shutdown(conn->cli);
1875 conn->cli = NULL;
1878 void close_conns_after_fork(void)
1880 struct winbindd_domain *domain;
1881 struct winbindd_cli_state *cli_state;
1883 for (domain = domain_list(); domain; domain = domain->next) {
1885 * first close the low level SMB TCP connection
1886 * so that we don't generate any SMBclose
1887 * requests in invalidate_cm_connection()
1889 if (cli_state_is_connected(domain->conn.cli)) {
1890 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1893 invalidate_cm_connection(domain);
1896 for (cli_state = winbindd_client_list();
1897 cli_state != NULL;
1898 cli_state = cli_state->next) {
1899 if (cli_state->sock >= 0) {
1900 close(cli_state->sock);
1901 cli_state->sock = -1;
1906 static bool connection_ok(struct winbindd_domain *domain)
1908 bool ok;
1910 ok = cli_state_is_connected(domain->conn.cli);
1911 if (!ok) {
1912 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1913 domain->dcname, domain->name));
1914 return False;
1917 if (!domain->online) {
1918 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1919 return False;
1922 return True;
1925 /* Initialize a new connection up to the RPC BIND.
1926 Bypass online status check so always does network calls. */
1928 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
1930 NTSTATUS result;
1931 bool skip_connection = domain->internal;
1932 if (need_rw_dc && domain->rodc) {
1933 skip_connection = false;
1936 /* Internal connections never use the network. */
1937 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
1938 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1941 /* Still ask the internal LSA and SAMR server about the local domain */
1942 if (skip_connection || connection_ok(domain)) {
1943 if (!domain->initialized) {
1944 set_dc_type_and_flags(domain);
1946 return NT_STATUS_OK;
1949 invalidate_cm_connection(domain);
1951 if (!domain->primary && !domain->initialized) {
1953 * Before we connect to a trust, work out if it is an
1954 * AD domain by asking our own domain.
1956 set_dc_type_and_flags_trustinfo(domain);
1959 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
1961 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1962 set_dc_type_and_flags(domain);
1965 return result;
1968 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
1970 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
1971 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1974 SMB_ASSERT(wb_child_domain() || idmap_child());
1976 return init_dc_connection_network(domain, need_rw_dc);
1979 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
1981 NTSTATUS status;
1983 status = init_dc_connection(domain, need_rw_dc);
1984 if (!NT_STATUS_IS_OK(status)) {
1985 return status;
1988 if (!domain->internal && domain->conn.cli == NULL) {
1989 /* happens for trusted domains without inbound trust */
1990 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1993 return NT_STATUS_OK;
1996 /******************************************************************************
1997 Set the trust flags (direction and forest location) for a domain
1998 ******************************************************************************/
2000 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2002 struct winbindd_domain *our_domain;
2003 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2004 WERROR werr;
2005 struct netr_DomainTrustList trusts;
2006 int i;
2007 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2008 NETR_TRUST_FLAG_OUTBOUND |
2009 NETR_TRUST_FLAG_INBOUND);
2010 struct rpc_pipe_client *cli;
2011 TALLOC_CTX *mem_ctx = NULL;
2012 struct dcerpc_binding_handle *b;
2014 if (IS_DC) {
2016 * On a DC we loaded all trusts
2017 * from configuration and never learn
2018 * new domains.
2020 return true;
2023 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2025 /* Our primary domain doesn't need to worry about trust flags.
2026 Force it to go through the network setup */
2027 if ( domain->primary ) {
2028 return False;
2031 mem_ctx = talloc_stackframe();
2032 our_domain = find_our_domain();
2033 if (our_domain->internal) {
2034 result = init_dc_connection(our_domain, false);
2035 if (!NT_STATUS_IS_OK(result)) {
2036 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2037 "Not able to make a connection to our domain: %s\n",
2038 nt_errstr(result)));
2039 TALLOC_FREE(mem_ctx);
2040 return false;
2044 /* This won't work unless our domain is AD */
2045 if ( !our_domain->active_directory ) {
2046 TALLOC_FREE(mem_ctx);
2047 return False;
2050 if (our_domain->internal) {
2051 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2052 } else if (!connection_ok(our_domain)) {
2053 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2054 "No connection to our domain!\n"));
2055 TALLOC_FREE(mem_ctx);
2056 return False;
2057 } else {
2058 result = cm_connect_netlogon(our_domain, &cli);
2061 if (!NT_STATUS_IS_OK(result)) {
2062 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2063 "a connection to %s for PIPE_NETLOGON (%s)\n",
2064 domain->name, nt_errstr(result)));
2065 TALLOC_FREE(mem_ctx);
2066 return False;
2068 b = cli->binding_handle;
2070 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2071 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2072 cli->desthost,
2073 flags,
2074 &trusts,
2075 &werr);
2076 if (!NT_STATUS_IS_OK(result)) {
2077 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2078 "failed to query trusted domain list: %s\n",
2079 nt_errstr(result)));
2080 TALLOC_FREE(mem_ctx);
2081 return false;
2083 if (!W_ERROR_IS_OK(werr)) {
2084 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2085 "failed to query trusted domain list: %s\n",
2086 win_errstr(werr)));
2087 TALLOC_FREE(mem_ctx);
2088 return false;
2091 /* Now find the domain name and get the flags */
2093 for ( i=0; i<trusts.count; i++ ) {
2094 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2095 domain->domain_flags = trusts.array[i].trust_flags;
2096 domain->domain_type = trusts.array[i].trust_type;
2097 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2099 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2100 domain->active_directory = True;
2102 /* This flag is only set if the domain is *our*
2103 primary domain and the primary domain is in
2104 native mode */
2106 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2108 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2109 "native mode.\n", domain->name,
2110 domain->native_mode ? "" : "NOT "));
2112 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2113 "running active directory.\n", domain->name,
2114 domain->active_directory ? "" : "NOT "));
2116 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2118 domain->initialized = True;
2120 break;
2124 TALLOC_FREE(mem_ctx);
2126 return domain->initialized;
2129 /******************************************************************************
2130 We can 'sense' certain things about the DC by it's replies to certain
2131 questions.
2133 This tells us if this particular remote server is Active Directory, and if it
2134 is native mode.
2135 ******************************************************************************/
2137 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2139 NTSTATUS status, result;
2140 WERROR werr;
2141 TALLOC_CTX *mem_ctx = NULL;
2142 struct rpc_pipe_client *cli = NULL;
2143 struct policy_handle pol;
2144 union dssetup_DsRoleInfo info;
2145 union lsa_PolicyInformation *lsa_info = NULL;
2147 if (!domain->internal && !connection_ok(domain)) {
2148 return;
2151 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2152 domain->name);
2153 if (!mem_ctx) {
2154 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2155 return;
2158 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2160 if (domain->internal) {
2161 status = wb_open_internal_pipe(mem_ctx,
2162 &ndr_table_dssetup,
2163 &cli);
2164 } else {
2165 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2166 &ndr_table_dssetup,
2167 &cli);
2170 if (!NT_STATUS_IS_OK(status)) {
2171 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2172 "PI_DSSETUP on domain %s: (%s)\n",
2173 domain->name, nt_errstr(status)));
2175 /* if this is just a non-AD domain we need to continue
2176 * identifying so that we can in the end return with
2177 * domain->initialized = True - gd */
2179 goto no_dssetup;
2182 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2183 DS_ROLE_BASIC_INFORMATION,
2184 &info,
2185 &werr);
2186 TALLOC_FREE(cli);
2188 if (NT_STATUS_IS_OK(status)) {
2189 result = werror_to_ntstatus(werr);
2191 if (!NT_STATUS_IS_OK(status)) {
2192 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2193 "on domain %s failed: (%s)\n",
2194 domain->name, nt_errstr(status)));
2196 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2197 * every opcode on the DSSETUP pipe, continue with
2198 * no_dssetup mode here as well to get domain->initialized
2199 * set - gd */
2201 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2202 goto no_dssetup;
2205 TALLOC_FREE(mem_ctx);
2206 return;
2209 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2210 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2211 domain->native_mode = True;
2212 } else {
2213 domain->native_mode = False;
2216 no_dssetup:
2217 if (domain->internal) {
2218 status = wb_open_internal_pipe(mem_ctx,
2219 &ndr_table_lsarpc,
2220 &cli);
2221 } else {
2222 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2223 &ndr_table_lsarpc, &cli);
2225 if (!NT_STATUS_IS_OK(status)) {
2226 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2227 "PI_LSARPC on domain %s: (%s)\n",
2228 domain->name, nt_errstr(status)));
2229 TALLOC_FREE(cli);
2230 TALLOC_FREE(mem_ctx);
2231 return;
2234 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2235 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2237 if (NT_STATUS_IS_OK(status)) {
2238 /* This particular query is exactly what Win2k clients use
2239 to determine that the DC is active directory */
2240 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2241 &pol,
2242 LSA_POLICY_INFO_DNS,
2243 &lsa_info,
2244 &result);
2247 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2248 domain->active_directory = True;
2250 if (lsa_info->dns.name.string) {
2251 if (!strequal(domain->name, lsa_info->dns.name.string))
2253 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2254 "for domain %s claimed it was a DC "
2255 "for domain %s, refusing to "
2256 "initialize\n",
2257 domain->name,
2258 lsa_info->dns.name.string));
2259 TALLOC_FREE(cli);
2260 TALLOC_FREE(mem_ctx);
2261 return;
2263 talloc_free(domain->name);
2264 domain->name = talloc_strdup(domain,
2265 lsa_info->dns.name.string);
2266 if (domain->name == NULL) {
2267 goto done;
2271 if (lsa_info->dns.dns_domain.string) {
2272 if (domain->alt_name != NULL &&
2273 !strequal(domain->alt_name,
2274 lsa_info->dns.dns_domain.string))
2276 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2277 "for domain %s (%s) claimed it was "
2278 "a DC for domain %s, refusing to "
2279 "initialize\n",
2280 domain->alt_name, domain->name,
2281 lsa_info->dns.dns_domain.string));
2282 TALLOC_FREE(cli);
2283 TALLOC_FREE(mem_ctx);
2284 return;
2286 talloc_free(domain->alt_name);
2287 domain->alt_name =
2288 talloc_strdup(domain,
2289 lsa_info->dns.dns_domain.string);
2290 if (domain->alt_name == NULL) {
2291 goto done;
2295 /* See if we can set some domain trust flags about
2296 ourself */
2298 if (lsa_info->dns.dns_forest.string) {
2299 talloc_free(domain->forest_name);
2300 domain->forest_name =
2301 talloc_strdup(domain,
2302 lsa_info->dns.dns_forest.string);
2303 if (domain->forest_name == NULL) {
2304 goto done;
2307 if (strequal(domain->forest_name, domain->alt_name)) {
2308 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2312 if (lsa_info->dns.sid) {
2313 if (!is_null_sid(&domain->sid) &&
2314 !dom_sid_equal(&domain->sid,
2315 lsa_info->dns.sid))
2317 struct dom_sid_buf buf1, buf2;
2318 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2319 "for domain %s (%s) claimed it was "
2320 "a DC for domain %s, refusing to "
2321 "initialize\n",
2322 dom_sid_str_buf(&domain->sid, &buf1),
2323 domain->name,
2324 dom_sid_str_buf(lsa_info->dns.sid,
2325 &buf2)));
2326 TALLOC_FREE(cli);
2327 TALLOC_FREE(mem_ctx);
2328 return;
2330 sid_copy(&domain->sid, lsa_info->dns.sid);
2332 } else {
2333 domain->active_directory = False;
2335 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2336 SEC_FLAG_MAXIMUM_ALLOWED,
2337 &pol);
2339 if (!NT_STATUS_IS_OK(status)) {
2340 goto done;
2343 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2344 &pol,
2345 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2346 &lsa_info,
2347 &result);
2348 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2350 if (lsa_info->account_domain.name.string) {
2351 if (!strequal(domain->name,
2352 lsa_info->account_domain.name.string))
2354 DEBUG(1,
2355 ("set_dc_type_and_flags_connect: "
2356 "DC for domain %s claimed it was"
2357 " a DC for domain %s, refusing "
2358 "to initialize\n", domain->name,
2359 lsa_info->
2360 account_domain.name.string));
2361 TALLOC_FREE(cli);
2362 TALLOC_FREE(mem_ctx);
2363 return;
2365 talloc_free(domain->name);
2366 domain->name =
2367 talloc_strdup(domain,
2368 lsa_info->account_domain.name.string);
2371 if (lsa_info->account_domain.sid) {
2372 if (!is_null_sid(&domain->sid) &&
2373 !dom_sid_equal(&domain->sid,
2374 lsa_info->account_domain.sid))
2376 struct dom_sid_buf buf1, buf2;
2377 DEBUG(1,
2378 ("set_dc_type_and_flags_connect: "
2379 "DC for domain %s (%s) claimed "
2380 "it was a DC for domain %s, "
2381 "refusing to initialize\n",
2382 dom_sid_str_buf(
2383 &domain->sid, &buf1),
2384 domain->name,
2385 dom_sid_str_buf(
2386 lsa_info->account_domain.sid,
2387 &buf2)));
2388 TALLOC_FREE(cli);
2389 TALLOC_FREE(mem_ctx);
2390 return;
2392 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2396 done:
2398 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2399 domain->name, domain->native_mode ? "" : "NOT "));
2401 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2402 domain->name, domain->active_directory ? "" : "NOT "));
2404 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2406 TALLOC_FREE(cli);
2408 TALLOC_FREE(mem_ctx);
2410 domain->initialized = True;
2413 /**********************************************************************
2414 Set the domain_flags (trust attributes, domain operating modes, etc...
2415 ***********************************************************************/
2417 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2419 if (IS_DC) {
2421 * On a DC we loaded all trusts
2422 * from configuration and never learn
2423 * new domains.
2425 return;
2428 /* we always have to contact our primary domain */
2430 if ( domain->primary || domain->internal) {
2431 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2432 "primary or internal domain\n"));
2433 set_dc_type_and_flags_connect( domain );
2434 return;
2437 /* Use our DC to get the information if possible */
2439 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2440 /* Otherwise, fallback to contacting the
2441 domain directly */
2442 set_dc_type_and_flags_connect( domain );
2445 return;
2450 /**********************************************************************
2451 ***********************************************************************/
2453 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2454 struct netlogon_creds_cli_context **ppdc)
2456 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2457 struct rpc_pipe_client *netlogon_pipe;
2459 *ppdc = NULL;
2461 if ((!IS_DC) && (!domain->primary)) {
2462 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2465 if (domain->conn.netlogon_creds_ctx != NULL) {
2466 *ppdc = domain->conn.netlogon_creds_ctx;
2467 return NT_STATUS_OK;
2470 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2471 if (!NT_STATUS_IS_OK(result)) {
2472 return result;
2475 return NT_STATUS_OK;
2478 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2479 bool need_rw_dc,
2480 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2482 struct winbindd_cm_conn *conn;
2483 NTSTATUS status, result;
2484 struct netlogon_creds_cli_context *p_creds;
2485 struct cli_credentials *creds = NULL;
2486 bool retry = false; /* allow one retry attempt for expired session */
2487 const char *remote_name = NULL;
2488 const struct sockaddr_storage *remote_sockaddr = NULL;
2489 bool sealed_pipes = true;
2490 bool strong_key = true;
2492 if (sid_check_is_our_sam(&domain->sid)) {
2493 if (domain->rodc == false || need_rw_dc == false) {
2494 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2498 if (IS_AD_DC) {
2500 * In theory we should not use SAMR within
2501 * winbindd at all, but that's a larger task to
2502 * remove this and avoid breaking existing
2503 * setups.
2505 * At least as AD DC we have the restriction
2506 * to avoid SAMR against trusted domains,
2507 * as there're no existing setups.
2509 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2512 retry:
2513 status = init_dc_connection_rpc(domain, need_rw_dc);
2514 if (!NT_STATUS_IS_OK(status)) {
2515 return status;
2518 conn = &domain->conn;
2520 if (rpccli_is_connected(conn->samr_pipe)) {
2521 goto done;
2524 TALLOC_FREE(conn->samr_pipe);
2527 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2528 * sign and sealed pipe using the machine account password by
2529 * preference. If we can't - try schannel, if that fails, try
2530 * anonymous.
2533 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2534 if (!NT_STATUS_IS_OK(result)) {
2535 DEBUG(10, ("cm_connect_sam: No user available for "
2536 "domain %s, trying schannel\n", domain->name));
2537 goto schannel;
2540 if (cli_credentials_is_anonymous(creds)) {
2541 goto anonymous;
2544 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2545 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2548 * We have an authenticated connection. Use a SPNEGO
2549 * authenticated SAMR pipe with sign & seal.
2551 status = cli_rpc_pipe_open_with_creds(conn->cli,
2552 &ndr_table_samr,
2553 NCACN_NP,
2554 DCERPC_AUTH_TYPE_SPNEGO,
2555 conn->auth_level,
2556 remote_name,
2557 remote_sockaddr,
2558 creds,
2559 &conn->samr_pipe);
2561 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2562 && !retry) {
2563 invalidate_cm_connection(domain);
2564 retry = true;
2565 goto retry;
2568 if (!NT_STATUS_IS_OK(status)) {
2569 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2570 "pipe for domain %s using NTLMSSP "
2571 "authenticated pipe: user %s. Error was "
2572 "%s\n", domain->name,
2573 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2574 nt_errstr(status)));
2575 goto schannel;
2578 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2579 "domain %s using NTLMSSP authenticated "
2580 "pipe: user %s\n", domain->name,
2581 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2583 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2584 conn->samr_pipe->desthost,
2585 SEC_FLAG_MAXIMUM_ALLOWED,
2586 &conn->sam_connect_handle,
2587 &result);
2589 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2590 invalidate_cm_connection(domain);
2591 TALLOC_FREE(conn->samr_pipe);
2592 retry = true;
2593 goto retry;
2596 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2597 goto open_domain;
2599 if (NT_STATUS_IS_OK(status)) {
2600 status = result;
2603 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2604 "failed for domain %s, error was %s. Trying schannel\n",
2605 domain->name, nt_errstr(status) ));
2606 TALLOC_FREE(conn->samr_pipe);
2608 schannel:
2610 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2612 status = cm_get_schannel_creds(domain, &p_creds);
2613 if (!NT_STATUS_IS_OK(status)) {
2614 /* If this call fails - conn->cli can now be NULL ! */
2615 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2616 "for domain %s (error %s), trying anon\n",
2617 domain->name,
2618 nt_errstr(status) ));
2619 goto anonymous;
2621 TALLOC_FREE(creds);
2622 status = cli_rpc_pipe_open_schannel_with_creds(
2623 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2624 remote_name,
2625 remote_sockaddr,
2626 &conn->samr_pipe);
2628 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2629 && !retry) {
2630 invalidate_cm_connection(domain);
2631 retry = true;
2632 goto retry;
2635 if (!NT_STATUS_IS_OK(status)) {
2636 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2637 "domain %s using schannel. Error was %s\n",
2638 domain->name, nt_errstr(status) ));
2639 goto anonymous;
2641 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2642 "schannel.\n", domain->name ));
2644 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2645 conn->samr_pipe->desthost,
2646 SEC_FLAG_MAXIMUM_ALLOWED,
2647 &conn->sam_connect_handle,
2648 &result);
2650 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2651 invalidate_cm_connection(domain);
2652 TALLOC_FREE(conn->samr_pipe);
2653 retry = true;
2654 goto retry;
2657 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2658 goto open_domain;
2660 if (NT_STATUS_IS_OK(status)) {
2661 status = result;
2663 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2664 "for domain %s, error was %s. Trying anonymous\n",
2665 domain->name, nt_errstr(status) ));
2666 TALLOC_FREE(conn->samr_pipe);
2668 anonymous:
2670 sealed_pipes = lp_winbind_sealed_pipes();
2671 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2672 domain->name,
2673 sealed_pipes);
2674 strong_key = lp_require_strong_key();
2675 strong_key = lp_parm_bool(-1, "require strong key",
2676 domain->name,
2677 strong_key);
2679 /* Finally fall back to anonymous. */
2680 if (sealed_pipes || strong_key) {
2681 status = NT_STATUS_DOWNGRADE_DETECTED;
2682 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2683 "without connection level security, "
2684 "must set 'winbind sealed pipes:%s = false' and "
2685 "'require strong key:%s = false' to proceed: %s\n",
2686 domain->name, domain->name, domain->name,
2687 nt_errstr(status)));
2688 goto done;
2690 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2691 &conn->samr_pipe);
2693 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2694 && !retry) {
2695 invalidate_cm_connection(domain);
2696 retry = true;
2697 goto retry;
2700 if (!NT_STATUS_IS_OK(status)) {
2701 goto done;
2704 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2705 conn->samr_pipe->desthost,
2706 SEC_FLAG_MAXIMUM_ALLOWED,
2707 &conn->sam_connect_handle,
2708 &result);
2710 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2711 invalidate_cm_connection(domain);
2712 TALLOC_FREE(conn->samr_pipe);
2713 retry = true;
2714 goto retry;
2717 if (!NT_STATUS_IS_OK(status)) {
2718 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2719 "for domain %s Error was %s\n",
2720 domain->name, nt_errstr(status) ));
2721 goto done;
2723 if (!NT_STATUS_IS_OK(result)) {
2724 status = result;
2725 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2726 "for domain %s Error was %s\n",
2727 domain->name, nt_errstr(result)));
2728 goto done;
2731 open_domain:
2732 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2733 mem_ctx,
2734 &conn->sam_connect_handle,
2735 SEC_FLAG_MAXIMUM_ALLOWED,
2736 &domain->sid,
2737 &conn->sam_domain_handle,
2738 &result);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 goto done;
2743 status = result;
2744 done:
2746 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2748 * if we got access denied, we might just have no access rights
2749 * to talk to the remote samr server server (e.g. when we are a
2750 * PDC and we are connecting a w2k8 pdc via an interdomain
2751 * trust). In that case do not invalidate the whole connection
2752 * stack
2754 TALLOC_FREE(conn->samr_pipe);
2755 ZERO_STRUCT(conn->sam_domain_handle);
2756 return status;
2757 } else if (!NT_STATUS_IS_OK(status)) {
2758 invalidate_cm_connection(domain);
2759 return status;
2762 *cli = conn->samr_pipe;
2763 *sam_handle = conn->sam_domain_handle;
2764 return status;
2767 /**********************************************************************
2768 open an schanneld ncacn_ip_tcp connection to LSA
2769 ***********************************************************************/
2771 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2772 TALLOC_CTX *mem_ctx,
2773 struct rpc_pipe_client **cli)
2775 struct winbindd_cm_conn *conn;
2776 struct netlogon_creds_cli_context *p_creds = NULL;
2777 NTSTATUS status;
2778 const char *remote_name = NULL;
2779 const struct sockaddr_storage *remote_sockaddr = NULL;
2781 DEBUG(10,("cm_connect_lsa_tcp\n"));
2783 status = init_dc_connection_rpc(domain, false);
2784 if (!NT_STATUS_IS_OK(status)) {
2785 return status;
2788 conn = &domain->conn;
2791 * rpccli_is_connected handles more error cases
2793 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2794 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2795 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2796 goto done;
2799 TALLOC_FREE(conn->lsa_pipe_tcp);
2801 status = cm_get_schannel_creds(domain, &p_creds);
2802 if (!NT_STATUS_IS_OK(status)) {
2803 goto done;
2806 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2807 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2809 status = cli_rpc_pipe_open_schannel_with_creds(
2810 conn->cli,
2811 &ndr_table_lsarpc,
2812 NCACN_IP_TCP,
2813 p_creds,
2814 remote_name,
2815 remote_sockaddr,
2816 &conn->lsa_pipe_tcp);
2817 if (!NT_STATUS_IS_OK(status)) {
2818 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2819 nt_errstr(status)));
2820 goto done;
2823 done:
2824 if (!NT_STATUS_IS_OK(status)) {
2825 TALLOC_FREE(conn->lsa_pipe_tcp);
2826 return status;
2829 *cli = conn->lsa_pipe_tcp;
2831 return status;
2834 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2835 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2837 struct winbindd_cm_conn *conn;
2838 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2839 struct netlogon_creds_cli_context *p_creds;
2840 struct cli_credentials *creds = NULL;
2841 bool retry = false; /* allow one retry attempt for expired session */
2842 const char *remote_name = NULL;
2843 const struct sockaddr_storage *remote_sockaddr = NULL;
2844 bool sealed_pipes = true;
2845 bool strong_key = true;
2847 retry:
2848 result = init_dc_connection_rpc(domain, false);
2849 if (!NT_STATUS_IS_OK(result))
2850 return result;
2852 conn = &domain->conn;
2854 if (rpccli_is_connected(conn->lsa_pipe)) {
2855 goto done;
2858 TALLOC_FREE(conn->lsa_pipe);
2860 if (IS_AD_DC) {
2862 * Make sure we only use schannel as AD DC.
2864 goto schannel;
2867 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2868 if (!NT_STATUS_IS_OK(result)) {
2869 DEBUG(10, ("cm_connect_lsa: No user available for "
2870 "domain %s, trying schannel\n", domain->name));
2871 goto schannel;
2874 if (cli_credentials_is_anonymous(creds)) {
2875 goto anonymous;
2878 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2879 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2882 * We have an authenticated connection. Use a SPNEGO
2883 * authenticated LSA pipe with sign & seal.
2885 result = cli_rpc_pipe_open_with_creds
2886 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2887 DCERPC_AUTH_TYPE_SPNEGO,
2888 conn->auth_level,
2889 remote_name,
2890 remote_sockaddr,
2891 creds,
2892 &conn->lsa_pipe);
2894 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
2895 && !retry) {
2896 invalidate_cm_connection(domain);
2897 retry = true;
2898 goto retry;
2901 if (!NT_STATUS_IS_OK(result)) {
2902 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2903 "domain %s using NTLMSSP authenticated pipe: user "
2904 "%s. Error was %s. Trying schannel.\n",
2905 domain->name,
2906 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2907 nt_errstr(result)));
2908 goto schannel;
2911 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2912 "NTLMSSP authenticated pipe: user %s\n",
2913 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
2915 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2916 SEC_FLAG_MAXIMUM_ALLOWED,
2917 &conn->lsa_policy);
2918 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2919 invalidate_cm_connection(domain);
2920 TALLOC_FREE(conn->lsa_pipe);
2921 retry = true;
2922 goto retry;
2925 if (NT_STATUS_IS_OK(result)) {
2926 goto done;
2929 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2930 "schannel\n"));
2932 TALLOC_FREE(conn->lsa_pipe);
2934 schannel:
2936 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2938 result = cm_get_schannel_creds(domain, &p_creds);
2939 if (!NT_STATUS_IS_OK(result)) {
2940 /* If this call fails - conn->cli can now be NULL ! */
2941 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2942 "for domain %s (error %s), trying anon\n",
2943 domain->name,
2944 nt_errstr(result) ));
2945 goto anonymous;
2948 TALLOC_FREE(creds);
2949 result = cli_rpc_pipe_open_schannel_with_creds(
2950 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
2951 remote_name,
2952 remote_sockaddr,
2953 &conn->lsa_pipe);
2955 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
2956 && !retry) {
2957 invalidate_cm_connection(domain);
2958 retry = true;
2959 goto retry;
2962 if (!NT_STATUS_IS_OK(result)) {
2963 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2964 "domain %s using schannel. Error was %s\n",
2965 domain->name, nt_errstr(result) ));
2966 goto anonymous;
2968 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2969 "schannel.\n", domain->name ));
2971 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2972 SEC_FLAG_MAXIMUM_ALLOWED,
2973 &conn->lsa_policy);
2975 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2976 invalidate_cm_connection(domain);
2977 TALLOC_FREE(conn->lsa_pipe);
2978 retry = true;
2979 goto retry;
2982 if (NT_STATUS_IS_OK(result)) {
2983 goto done;
2986 if (IS_AD_DC) {
2988 * Make sure we only use schannel as AD DC.
2990 goto done;
2993 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2994 "anonymous\n"));
2996 TALLOC_FREE(conn->lsa_pipe);
2998 anonymous:
3000 if (IS_AD_DC) {
3002 * Make sure we only use schannel as AD DC.
3004 goto done;
3007 sealed_pipes = lp_winbind_sealed_pipes();
3008 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
3009 domain->name,
3010 sealed_pipes);
3011 strong_key = lp_require_strong_key();
3012 strong_key = lp_parm_bool(-1, "require strong key",
3013 domain->name,
3014 strong_key);
3016 /* Finally fall back to anonymous. */
3017 if (sealed_pipes || strong_key) {
3018 result = NT_STATUS_DOWNGRADE_DETECTED;
3019 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3020 "without connection level security, "
3021 "must set 'winbind sealed pipes:%s = false' and "
3022 "'require strong key:%s = false' to proceed: %s\n",
3023 domain->name, domain->name, domain->name,
3024 nt_errstr(result)));
3025 goto done;
3028 result = cli_rpc_pipe_open_noauth(conn->cli,
3029 &ndr_table_lsarpc,
3030 &conn->lsa_pipe);
3032 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3033 && !retry) {
3034 invalidate_cm_connection(domain);
3035 retry = true;
3036 goto retry;
3039 if (!NT_STATUS_IS_OK(result)) {
3040 goto done;
3043 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3044 SEC_FLAG_MAXIMUM_ALLOWED,
3045 &conn->lsa_policy);
3047 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3048 invalidate_cm_connection(domain);
3049 TALLOC_FREE(conn->lsa_pipe);
3050 retry = true;
3051 goto retry;
3054 done:
3055 if (!NT_STATUS_IS_OK(result)) {
3056 invalidate_cm_connection(domain);
3057 return result;
3060 *cli = conn->lsa_pipe;
3061 *lsa_policy = conn->lsa_policy;
3062 return result;
3065 /****************************************************************************
3066 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3067 ****************************************************************************/
3069 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3070 TALLOC_CTX *mem_ctx,
3071 struct rpc_pipe_client **cli,
3072 struct policy_handle *lsa_policy)
3074 NTSTATUS status;
3076 if (domain->can_do_ncacn_ip_tcp) {
3077 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3078 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3079 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3080 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3081 invalidate_cm_connection(domain);
3082 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3084 if (NT_STATUS_IS_OK(status)) {
3085 return status;
3089 * we tried twice to connect via ncan_ip_tcp and schannel and
3090 * failed - maybe it is a trusted domain we can't connect to ?
3091 * do not try tcp next time - gd
3093 * This also prevents NETLOGON over TCP
3095 domain->can_do_ncacn_ip_tcp = false;
3098 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3100 return status;
3103 /****************************************************************************
3104 Open the netlogon pipe to this DC.
3105 ****************************************************************************/
3107 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3108 enum dcerpc_transport_t transport,
3109 struct rpc_pipe_client **cli)
3111 struct messaging_context *msg_ctx = global_messaging_context();
3112 struct winbindd_cm_conn *conn;
3113 NTSTATUS result;
3114 enum netr_SchannelType sec_chan_type;
3115 struct cli_credentials *creds = NULL;
3117 *cli = NULL;
3119 if (IS_AD_DC) {
3120 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3122 * Make sure we don't even try to
3123 * connect to a foreign domain
3124 * without a direct outbound trust.
3126 return NT_STATUS_NO_TRUST_LSA_SECRET;
3130 result = init_dc_connection_rpc(domain, domain->rodc);
3131 if (!NT_STATUS_IS_OK(result)) {
3132 return result;
3135 conn = &domain->conn;
3137 if (rpccli_is_connected(conn->netlogon_pipe)) {
3138 *cli = conn->netlogon_pipe;
3139 return NT_STATUS_OK;
3142 TALLOC_FREE(conn->netlogon_pipe);
3143 TALLOC_FREE(conn->netlogon_creds_ctx);
3145 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3146 if (!NT_STATUS_IS_OK(result)) {
3147 DBG_DEBUG("No user available for domain %s when trying "
3148 "schannel\n", domain->name);
3149 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3152 if (cli_credentials_is_anonymous(creds)) {
3153 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3154 "unable to make get NETLOGON credentials\n",
3155 domain->name);
3156 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3159 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3160 if (sec_chan_type == SEC_CHAN_NULL) {
3161 const char *remote_name =
3162 smbXcli_conn_remote_name(conn->cli->conn);
3163 const struct sockaddr_storage *remote_sockaddr =
3164 smbXcli_conn_remote_sockaddr(conn->cli->conn);
3166 if (transport == NCACN_IP_TCP) {
3167 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3168 "for %s, deny NCACN_IP_TCP and let the "
3169 "caller fallback to NCACN_NP.\n",
3170 domain->name);
3171 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3174 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3175 "fallback to noauth on NCACN_NP.\n",
3176 domain->name);
3178 result = cli_rpc_pipe_open_noauth_transport(
3179 conn->cli,
3180 transport,
3181 &ndr_table_netlogon,
3182 remote_name,
3183 remote_sockaddr,
3184 &conn->netlogon_pipe);
3185 if (!NT_STATUS_IS_OK(result)) {
3186 invalidate_cm_connection(domain);
3187 return result;
3190 *cli = conn->netlogon_pipe;
3191 return NT_STATUS_OK;
3194 result = rpccli_create_netlogon_creds_ctx(creds,
3195 domain->dcname,
3196 msg_ctx,
3197 domain,
3198 &conn->netlogon_creds_ctx);
3199 if (!NT_STATUS_IS_OK(result)) {
3200 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3201 "unable to create NETLOGON credentials: %s\n",
3202 domain->name, nt_errstr(result)));
3203 return result;
3206 result = rpccli_connect_netlogon(
3207 conn->cli, transport,
3208 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3209 &conn->netlogon_pipe);
3210 conn->netlogon_force_reauth = false;
3211 if (!NT_STATUS_IS_OK(result)) {
3212 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3213 nt_errstr(result));
3214 return result;
3217 *cli = conn->netlogon_pipe;
3218 return NT_STATUS_OK;
3221 /****************************************************************************
3222 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3223 ****************************************************************************/
3225 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3226 struct rpc_pipe_client **cli)
3228 NTSTATUS status;
3230 status = init_dc_connection_rpc(domain, domain->rodc);
3231 if (!NT_STATUS_IS_OK(status)) {
3232 return status;
3235 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3236 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3237 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3238 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3239 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3240 invalidate_cm_connection(domain);
3241 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3243 if (NT_STATUS_IS_OK(status)) {
3244 return status;
3248 * we tried twice to connect via ncan_ip_tcp and schannel and
3249 * failed - maybe it is a trusted domain we can't connect to ?
3250 * do not try tcp next time - gd
3252 * This also prevents LSA over TCP
3254 domain->can_do_ncacn_ip_tcp = false;
3257 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3258 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3260 * SMB2 session expired, needs reauthentication. Drop
3261 * connection and retry.
3263 invalidate_cm_connection(domain);
3264 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3267 return status;
3270 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3271 struct rpc_pipe_client **cli,
3272 struct netlogon_creds_cli_context **ppdc)
3274 NTSTATUS status;
3276 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3277 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3280 status = cm_connect_netlogon(domain, cli);
3281 if (!NT_STATUS_IS_OK(status)) {
3282 return status;
3285 if (domain->conn.netlogon_creds_ctx == NULL) {
3286 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3289 *ppdc = domain->conn.netlogon_creds_ctx;
3290 return NT_STATUS_OK;
3293 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3294 void *private_data,
3295 uint32_t msg_type,
3296 struct server_id server_id,
3297 DATA_BLOB *data)
3299 struct winbindd_domain *domain;
3300 char *freeit = NULL;
3301 char *addr;
3303 if ((data == NULL)
3304 || (data->data == NULL)
3305 || (data->length == 0)
3306 || (data->data[data->length-1] != '\0')) {
3307 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3308 "string\n"));
3309 return;
3312 addr = (char *)data->data;
3313 DEBUG(10, ("IP %s dropped\n", addr));
3315 if (!is_ipaddress(addr)) {
3316 char *slash;
3318 * Some code sends us ip addresses with the /netmask
3319 * suffix
3321 slash = strchr(addr, '/');
3322 if (slash == NULL) {
3323 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3324 addr));
3325 return;
3327 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3328 if (freeit == NULL) {
3329 DEBUG(1, ("talloc failed\n"));
3330 return;
3332 addr = freeit;
3333 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3336 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3337 char sockaddr[INET6_ADDRSTRLEN];
3339 if (!cli_state_is_connected(domain->conn.cli)) {
3340 continue;
3343 print_sockaddr(sockaddr, sizeof(sockaddr),
3344 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3346 if (strequal(sockaddr, addr)) {
3347 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3350 TALLOC_FREE(freeit);
3353 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3354 void *private_data,
3355 uint32_t msg_type,
3356 struct server_id server_id,
3357 DATA_BLOB *data)
3359 struct winbindd_domain *domain;
3361 for (domain = domain_list(); domain; domain = domain->next) {
3362 if (domain->internal) {
3363 continue;
3365 invalidate_cm_connection(domain);