winbindd: also apply schannel logic as an NT4 DC
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob1685edbabaa2aa29d66d0e846f6199370ec1e853
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_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 close(sockfd);
712 return NT_STATUS_NO_TRUST_LSA_SECRET;
716 * As AD DC we only use netlogon and lsa
717 * using schannel over an anonymous transport
718 * (ncacn_ip_tcp or ncacn_np).
720 * Currently we always establish the SMB connection,
721 * even if we don't use it, because we later use ncacn_ip_tcp.
723 * As we won't use the SMB connection there's no
724 * need to try kerberos. And NT4 domains expect
725 * an anonymous IPC$ connection anyway.
727 smb_sign_client_connections = SMB_SIGNING_OFF;
730 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
732 * If we are connecting to our own AD domain, require
733 * smb signing to disrupt MITM attacks
735 if (domain->primary && lp_security() == SEC_ADS) {
736 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
738 * If we are in or are an AD domain and connecting to another
739 * AD domain in our forest
740 * then require smb signing to disrupt MITM attacks
742 } else if ((lp_security() == SEC_ADS)
743 && domain->active_directory
744 && (domain->domain_trust_attribs
745 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
746 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
750 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
751 controller, domain->name ));
753 *retry = True;
755 mutex = grab_named_mutex(talloc_tos(), controller,
756 WINBIND_SERVER_MUTEX_WAIT_TIME);
757 if (mutex == NULL) {
758 close(sockfd);
759 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
760 controller));
761 result = NT_STATUS_POSSIBLE_DEADLOCK;
762 goto done;
766 * cm_prepare_connection() is responsible that sockfd does not leak.
767 * Once cli_state_create() returns with success, the
768 * smbXcli_conn_destructor() makes sure that close(sockfd) is finally
769 * called. Till that, close(sockfd) must be called on every unsuccessful
770 * return.
772 *cli = cli_state_create(NULL, sockfd, controller,
773 smb_sign_client_connections, flags);
774 if (*cli == NULL) {
775 close(sockfd);
776 DEBUG(1, ("Could not cli_initialize\n"));
777 result = NT_STATUS_NO_MEMORY;
778 goto done;
781 cli_set_timeout(*cli, 10000); /* 10 seconds */
783 set_socket_options(sockfd, lp_socket_options());
785 result = smbXcli_negprot((*cli)->conn,
786 (*cli)->timeout,
787 lp_client_ipc_min_protocol(),
788 lp_client_ipc_max_protocol(),
789 NULL,
790 NULL,
791 NULL);
793 if (!NT_STATUS_IS_OK(result)) {
794 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
795 goto done;
798 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
799 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
800 try_ipc_auth = true;
801 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
802 try_ipc_auth = true;
803 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
805 * If we are forcing on SMB signing, then we must
806 * require authentication unless this is a one-way
807 * trust, and we have no stored user/password
809 try_ipc_auth = true;
812 if (IS_DC) {
814 * As AD DC we only use netlogon and lsa
815 * using schannel over an anonymous transport
816 * (ncacn_ip_tcp or ncacn_np).
818 * Currently we always establish the SMB connection,
819 * even if we don't use it, because we later use ncacn_ip_tcp.
821 * As we won't use the SMB connection there's no
822 * need to try kerberos. And NT4 domains expect
823 * an anonymous IPC$ connection anyway.
825 try_ipc_auth = false;
828 if (try_ipc_auth) {
829 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
830 if (!NT_STATUS_IS_OK(result)) {
831 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
832 domain->name, nt_errstr(result)));
833 goto done;
835 } else {
837 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
838 * would try and authentication with our machine
839 * account password and fail. This is very rare in
840 * the modern world however
842 creds = cli_credentials_init_anon(talloc_tos());
843 if (creds == NULL) {
844 result = NT_STATUS_NO_MEMORY;
845 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
846 domain->name, nt_errstr(result)));
847 goto done;
851 machine_principal = cli_credentials_get_principal(creds,
852 talloc_tos());
853 machine_realm = cli_credentials_get_realm(creds);
854 machine_account = cli_credentials_get_username(creds);
855 machine_domain = cli_credentials_get_domain(creds);
857 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
858 "[%s] and realm [%s]\n",
859 controller, domain->name, domain->alt_name,
860 machine_domain, machine_account,
861 machine_principal, machine_realm));
863 if (cli_credentials_is_anonymous(creds)) {
864 goto anon_fallback;
867 winbindd_set_locator_kdc_envs(domain);
869 result = cli_session_setup_creds(*cli, creds);
870 if (NT_STATUS_IS_OK(result)) {
871 goto session_setup_done;
874 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
875 controller,
876 cli_credentials_get_unparsed_name(creds, talloc_tos()),
877 nt_errstr(result)));
880 * If we are not going to validate the connection
881 * with SMB signing, then allow us to fall back to
882 * anonymous
884 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
885 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
886 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
887 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
888 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
889 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
890 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
892 if (!cm_is_ipc_credentials(creds)) {
893 goto ipc_fallback;
896 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
897 goto done;
900 goto anon_fallback;
903 goto done;
905 ipc_fallback:
906 TALLOC_FREE(creds);
907 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
908 if (!NT_STATUS_IS_OK(tmp_status)) {
909 result = tmp_status;
910 goto done;
913 if (cli_credentials_is_anonymous(creds)) {
914 goto anon_fallback;
917 machine_account = cli_credentials_get_username(creds);
918 machine_domain = cli_credentials_get_domain(creds);
920 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
921 "[%s]\\[%s]\n", controller, lp_netbios_name(),
922 machine_domain, machine_account));
924 result = cli_session_setup_creds(*cli, creds);
925 if (NT_STATUS_IS_OK(result)) {
926 goto session_setup_done;
929 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
930 controller,
931 cli_credentials_get_unparsed_name(creds, talloc_tos()),
932 nt_errstr(result)));
935 * If we are not going to validate the connection
936 * with SMB signing, then allow us to fall back to
937 * anonymous
939 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
940 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
941 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
942 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
943 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
944 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
945 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
947 goto anon_fallback;
950 goto done;
952 anon_fallback:
953 TALLOC_FREE(creds);
955 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
956 goto done;
959 /* Fall back to anonymous connection, this might fail later */
960 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
961 "connection for DC %s\n",
962 controller ));
964 result = cli_session_setup_anon(*cli);
965 if (NT_STATUS_IS_OK(result)) {
966 DEBUG(5, ("Connected anonymously\n"));
967 goto session_setup_done;
970 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
971 controller, nt_errstr(result)));
973 /* We can't session setup */
974 goto done;
976 session_setup_done:
977 TALLOC_FREE(creds);
980 * This should be a short term hack until
981 * dynamic re-authentication is implemented.
983 * See Bug 9175 - winbindd doesn't recover from
984 * NT_STATUS_NETWORK_SESSION_EXPIRED
986 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
987 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
990 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
991 if (!NT_STATUS_IS_OK(result)) {
992 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
993 goto done;
995 tcon_status = result;
997 /* cache the server name for later connections */
999 saf_store(domain->name, controller);
1000 if (domain->alt_name) {
1001 saf_store(domain->alt_name, controller);
1004 winbindd_set_locator_kdc_envs(domain);
1006 TALLOC_FREE(mutex);
1007 *retry = False;
1009 result = NT_STATUS_OK;
1011 done:
1012 TALLOC_FREE(mutex);
1013 TALLOC_FREE(creds);
1015 if (NT_STATUS_IS_OK(result)) {
1016 result = tcon_status;
1019 if (!NT_STATUS_IS_OK(result)) {
1020 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1021 controller, nt_errstr(result)));
1022 winbind_add_failed_connection_entry(domain, controller, result);
1023 if ((*cli) != NULL) {
1024 cli_shutdown(*cli);
1025 *cli = NULL;
1029 return result;
1032 /*******************************************************************
1033 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1034 array.
1036 Keeps the list unique by not adding duplicate entries.
1038 @param[in] mem_ctx talloc memory context to allocate from
1039 @param[in] domain_name domain of the DC
1040 @param[in] dcname name of the DC to add to the list
1041 @param[in] pss Internet address and port pair to add to the list
1042 @param[in,out] dcs array of dc_name_ip structures to add to
1043 @param[in,out] num_dcs number of dcs returned in the dcs array
1044 @return true if the list was added to, false otherwise
1045 *******************************************************************/
1047 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1048 const char *dcname, struct sockaddr_storage *pss,
1049 struct dc_name_ip **dcs, int *num)
1051 int i = 0;
1053 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1054 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1055 return False;
1058 /* Make sure there's no duplicates in the list */
1059 for (i=0; i<*num; i++)
1060 if (sockaddr_equal(
1061 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1062 (struct sockaddr *)(void *)pss))
1063 return False;
1065 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1067 if (*dcs == NULL)
1068 return False;
1070 fstrcpy((*dcs)[*num].name, dcname);
1071 (*dcs)[*num].ss = *pss;
1072 *num += 1;
1073 return True;
1076 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1077 struct sockaddr_storage *pss, uint16_t port,
1078 struct sockaddr_storage **addrs, int *num)
1080 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1082 if (*addrs == NULL) {
1083 *num = 0;
1084 return False;
1087 (*addrs)[*num] = *pss;
1088 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1090 *num += 1;
1091 return True;
1094 #ifdef HAVE_ADS
1095 static bool dcip_check_name_ads(const struct winbindd_domain *domain,
1096 struct samba_sockaddr *sa,
1097 uint32_t request_flags,
1098 TALLOC_CTX *mem_ctx,
1099 char **namep)
1101 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1102 char *name = NULL;
1103 ADS_STRUCT *ads = NULL;
1104 ADS_STATUS ads_status;
1105 char addr[INET6_ADDRSTRLEN];
1107 print_sockaddr(addr, sizeof(addr), &sa->u.ss);
1108 D_DEBUG("Trying to figure out the DC name for domain '%s' at IP '%s'.\n",
1109 domain->name,
1110 addr);
1112 ads = ads_init(tmp_ctx,
1113 domain->alt_name,
1114 domain->name,
1115 addr,
1116 ADS_SASL_PLAIN);
1117 if (ads == NULL) {
1118 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1119 goto out;
1121 ads->auth.flags |= ADS_AUTH_NO_BIND;
1122 ads->config.flags |= request_flags;
1123 ads->server.no_fallback = true;
1125 ads_status = ads_connect(ads);
1126 if (!ADS_ERR_OK(ads_status)) {
1127 goto out;
1130 /* We got a cldap packet. */
1131 name = talloc_strdup(tmp_ctx, ads->config.ldap_server_name);
1132 if (name == NULL) {
1133 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1134 goto out;
1136 namecache_store(name, 0x20, 1, sa);
1138 DBG_DEBUG("CLDAP flags = 0x%"PRIx32"\n", ads->config.flags);
1140 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1141 if (ads_closest_dc(ads)) {
1142 char *sitename = sitename_fetch(tmp_ctx,
1143 ads->config.realm);
1145 /* We're going to use this KDC for this realm/domain.
1146 If we are using sites, then force the krb5 libs
1147 to use this KDC. */
1149 create_local_private_krb5_conf_for_domain(domain->alt_name,
1150 domain->name,
1151 sitename,
1152 &sa->u.ss);
1154 TALLOC_FREE(sitename);
1155 } else {
1156 /* use an off site KDC */
1157 create_local_private_krb5_conf_for_domain(domain->alt_name,
1158 domain->name,
1159 NULL,
1160 &sa->u.ss);
1162 winbindd_set_locator_kdc_envs(domain);
1164 /* Ensure we contact this DC also. */
1165 saf_store(domain->name, name);
1166 saf_store(domain->alt_name, name);
1169 D_DEBUG("DC name for domain '%s' at IP '%s' is '%s'\n",
1170 domain->name,
1171 addr,
1172 name);
1173 *namep = talloc_move(mem_ctx, &name);
1175 out:
1176 TALLOC_FREE(tmp_ctx);
1178 return ADS_ERR_OK(ads_status) ? true : false;
1180 #endif
1182 /*******************************************************************
1183 convert an ip to a name
1184 For an AD Domain, it checks the requirements of the request flags.
1185 *******************************************************************/
1187 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1188 const struct winbindd_domain *domain,
1189 struct sockaddr_storage *pss,
1190 char **name, uint32_t request_flags)
1192 struct samba_sockaddr sa = {0};
1193 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1194 NTSTATUS status;
1195 const char *dc_name;
1196 fstring nbtname;
1197 #ifdef HAVE_ADS
1198 bool is_ad_domain = false;
1199 #endif
1200 bool ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
1201 if (!ok) {
1202 return false;
1205 #ifdef HAVE_ADS
1206 /* For active directory servers, try to get the ldap server name.
1207 None of these failures should be considered critical for now */
1209 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1210 is_ad_domain = true;
1211 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1212 is_ad_domain = domain->active_directory;
1215 if (is_ad_domain) {
1216 return dcip_check_name_ads(domain,
1217 &sa,
1218 request_flags,
1219 mem_ctx,
1220 name);
1222 #endif
1225 size_t len = strlen(lp_netbios_name());
1226 char my_acct_name[len+2];
1228 snprintf(my_acct_name,
1229 sizeof(my_acct_name),
1230 "%s$",
1231 lp_netbios_name());
1233 status = nbt_getdc(global_messaging_context(), 10, &sa.u.ss,
1234 domain->name, &domain->sid,
1235 my_acct_name, ACB_WSTRUST,
1236 nt_version, mem_ctx, &nt_version,
1237 &dc_name, NULL);
1239 if (NT_STATUS_IS_OK(status)) {
1240 *name = talloc_strdup(mem_ctx, dc_name);
1241 if (*name == NULL) {
1242 return false;
1244 namecache_store(*name, 0x20, 1, &sa);
1245 return True;
1248 /* try node status request */
1250 if (name_status_find(domain->name, 0x1c, 0x20, &sa.u.ss, nbtname) ) {
1251 namecache_store(nbtname, 0x20, 1, &sa);
1253 if (name != NULL) {
1254 *name = talloc_strdup(mem_ctx, nbtname);
1255 if (*name == NULL) {
1256 return false;
1260 return true;
1262 return False;
1265 /*******************************************************************
1266 Retrieve a list of IP addresses for domain controllers.
1268 The array is sorted in the preferred connection order.
1270 @param[in] mem_ctx talloc memory context to allocate from
1271 @param[in] domain domain to retrieve DCs for
1272 @param[out] dcs array of dcs that will be returned
1273 @param[out] num_dcs number of dcs returned in the dcs array
1274 @return always true
1275 *******************************************************************/
1277 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1278 struct dc_name_ip **dcs, int *num_dcs,
1279 uint32_t request_flags)
1281 fstring dcname;
1282 struct sockaddr_storage ss;
1283 struct samba_sockaddr *sa_list = NULL;
1284 size_t salist_size = 0;
1285 size_t i;
1286 bool is_our_domain;
1287 enum security_types sec = (enum security_types)lp_security();
1289 is_our_domain = strequal(domain->name, lp_workgroup());
1291 /* If not our domain, get the preferred DC, by asking our primary DC */
1292 if ( !is_our_domain
1293 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1294 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1295 num_dcs) )
1297 char addr[INET6_ADDRSTRLEN];
1298 print_sockaddr(addr, sizeof(addr), &ss);
1299 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1300 dcname, addr));
1301 return True;
1304 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1305 char *sitename = NULL;
1307 /* We need to make sure we know the local site before
1308 doing any DNS queries, as this will restrict the
1309 get_sorted_dc_list() call below to only fetching
1310 DNS records for the correct site. */
1312 /* Find any DC to get the site record.
1313 We deliberately don't care about the
1314 return here. */
1316 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1318 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1319 if (sitename) {
1321 /* Do the site-specific AD dns lookup first. */
1322 (void)get_sorted_dc_list(mem_ctx,
1323 domain->alt_name,
1324 sitename,
1325 &sa_list,
1326 &salist_size,
1327 true);
1329 /* Add ips to the DC array. We don't look up the name
1330 of the DC in this function, but we fill in the char*
1331 of the ip now to make the failed connection cache
1332 work */
1333 for ( i=0; i<salist_size; i++ ) {
1334 char addr[INET6_ADDRSTRLEN];
1335 print_sockaddr(addr, sizeof(addr),
1336 &sa_list[i].u.ss);
1337 add_one_dc_unique(mem_ctx,
1338 domain->name,
1339 addr,
1340 &sa_list[i].u.ss,
1341 dcs,
1342 num_dcs);
1345 TALLOC_FREE(sa_list);
1346 TALLOC_FREE(sitename);
1347 salist_size = 0;
1350 /* Now we add DCs from the main AD DNS lookup. */
1351 (void)get_sorted_dc_list(mem_ctx,
1352 domain->alt_name,
1353 NULL,
1354 &sa_list,
1355 &salist_size,
1356 true);
1358 for ( i=0; i<salist_size; i++ ) {
1359 char addr[INET6_ADDRSTRLEN];
1360 print_sockaddr(addr, sizeof(addr),
1361 &sa_list[i].u.ss);
1362 add_one_dc_unique(mem_ctx,
1363 domain->name,
1364 addr,
1365 &sa_list[i].u.ss,
1366 dcs,
1367 num_dcs);
1370 TALLOC_FREE(sa_list);
1371 salist_size = 0;
1374 /* Try standard netbios queries if no ADS and fall back to DNS queries
1375 * if alt_name is available */
1376 if (*num_dcs == 0) {
1377 (void)get_sorted_dc_list(mem_ctx,
1378 domain->name,
1379 NULL,
1380 &sa_list,
1381 &salist_size,
1382 false);
1383 if (salist_size == 0) {
1384 if (domain->alt_name != NULL) {
1385 (void)get_sorted_dc_list(mem_ctx,
1386 domain->alt_name,
1387 NULL,
1388 &sa_list,
1389 &salist_size,
1390 true);
1394 for ( i=0; i<salist_size; i++ ) {
1395 char addr[INET6_ADDRSTRLEN];
1396 print_sockaddr(addr, sizeof(addr),
1397 &sa_list[i].u.ss);
1398 add_one_dc_unique(mem_ctx,
1399 domain->name,
1400 addr,
1401 &sa_list[i].u.ss,
1402 dcs,
1403 num_dcs);
1406 TALLOC_FREE(sa_list);
1407 salist_size = 0;
1410 return True;
1413 static bool connect_preferred_dc(TALLOC_CTX *mem_ctx,
1414 struct winbindd_domain *domain,
1415 uint32_t request_flags,
1416 int *fd)
1418 char *saf_servername = NULL;
1419 NTSTATUS status;
1420 bool ok;
1423 * We have to check the server affinity cache here since later we select
1424 * a DC based on response time and not preference.
1426 if (domain->force_dc) {
1427 saf_servername = domain->dcname;
1428 } else {
1429 saf_servername = saf_fetch(mem_ctx, domain->name);
1433 * Check the negative connection cache before talking to it. It going
1434 * down may have triggered the reconnection.
1436 if (saf_servername != NULL) {
1437 status = check_negative_conn_cache(domain->name,
1438 saf_servername);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 saf_servername = NULL;
1444 if (saf_servername != NULL) {
1445 DBG_DEBUG("saf_servername is '%s' for domain %s\n",
1446 saf_servername, domain->name);
1448 /* convert an ip address to a name */
1449 if (is_ipaddress(saf_servername)) {
1450 ok = interpret_string_addr(&domain->dcaddr,
1451 saf_servername,
1452 AI_NUMERICHOST);
1453 if (!ok) {
1454 return false;
1456 } else {
1457 ok = resolve_name(saf_servername,
1458 &domain->dcaddr,
1459 0x20,
1460 true);
1461 if (!ok) {
1462 goto fail;
1466 TALLOC_FREE(domain->dcname);
1467 ok = dcip_check_name(domain,
1468 domain,
1469 &domain->dcaddr,
1470 &domain->dcname,
1471 request_flags);
1472 if (!ok) {
1473 goto fail;
1477 if (domain->dcname == NULL) {
1478 return false;
1481 status = check_negative_conn_cache(domain->name, domain->dcname);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 return false;
1486 status = smbsock_connect(&domain->dcaddr, 0,
1487 NULL, -1, NULL, -1,
1488 fd, NULL, 10);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 winbind_add_failed_connection_entry(domain,
1491 domain->dcname,
1492 NT_STATUS_UNSUCCESSFUL);
1493 return false;
1495 return true;
1497 fail:
1498 winbind_add_failed_connection_entry(domain,
1499 saf_servername,
1500 NT_STATUS_UNSUCCESSFUL);
1501 return false;
1505 /*******************************************************************
1506 Find and make a connection to a DC in the given domain.
1508 @param[in] mem_ctx talloc memory context to allocate from
1509 @param[in] domain domain to find a dc in
1510 @param[out] fd fd of the open socket connected to the newly found dc
1511 @return true when a DC connection is made, false otherwise
1512 *******************************************************************/
1514 static bool find_dc(TALLOC_CTX *mem_ctx,
1515 struct winbindd_domain *domain,
1516 uint32_t request_flags,
1517 int *fd)
1519 struct dc_name_ip *dcs = NULL;
1520 int num_dcs = 0;
1522 const char **dcnames = NULL;
1523 size_t num_dcnames = 0;
1525 struct sockaddr_storage *addrs = NULL;
1526 int num_addrs = 0;
1528 int i;
1529 size_t fd_index;
1531 NTSTATUS status;
1532 bool ok;
1534 *fd = -1;
1536 D_NOTICE("First try to connect to the closest DC (using server "
1537 "affinity cache). If this fails, try to lookup the DC using "
1538 "DNS afterwards.\n");
1539 ok = connect_preferred_dc(mem_ctx, domain, request_flags, fd);
1540 if (ok) {
1541 return true;
1544 if (domain->force_dc) {
1545 return false;
1548 again:
1549 D_DEBUG("Retrieving a list of IP addresses for DCs.\n");
1550 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1551 return False;
1553 D_DEBUG("Retrieved IP addresses for %d DCs.\n", num_dcs);
1554 for (i=0; i<num_dcs; i++) {
1556 if (!add_string_to_array(mem_ctx, dcs[i].name,
1557 &dcnames, &num_dcnames)) {
1558 return False;
1560 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1561 &addrs, &num_addrs)) {
1562 return False;
1566 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1567 return False;
1569 if ((addrs == NULL) || (dcnames == NULL))
1570 return False;
1572 D_DEBUG("Trying to establish a connection to one of the %d DCs "
1573 "(timeout of 10 sec for each DC).\n",
1574 num_dcs);
1575 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1576 num_addrs, 0, 10, fd, &fd_index, NULL);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 for (i=0; i<num_dcs; i++) {
1579 char ab[INET6_ADDRSTRLEN];
1580 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1581 DBG_DEBUG("smbsock_any_connect failed for "
1582 "domain %s address %s. Error was %s\n",
1583 domain->name, ab, nt_errstr(status));
1584 winbind_add_failed_connection_entry(domain,
1585 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1587 return False;
1589 D_NOTICE("Successfully connected to DC '%s'.\n", dcs[fd_index].name);
1591 domain->dcaddr = addrs[fd_index];
1593 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1594 /* Ok, we've got a name for the DC */
1595 TALLOC_FREE(domain->dcname);
1596 domain->dcname = talloc_strdup(domain, dcnames[fd_index]);
1597 if (domain->dcname == NULL) {
1598 return false;
1600 return true;
1603 /* Try to figure out the name */
1604 TALLOC_FREE(domain->dcname);
1605 ok = dcip_check_name(domain,
1606 domain,
1607 &domain->dcaddr,
1608 &domain->dcname,
1609 request_flags);
1610 if (ok) {
1611 return true;
1614 /* We can not continue without the DC's name */
1615 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1616 NT_STATUS_UNSUCCESSFUL);
1618 /* Throw away all arrays as we're doing this again. */
1619 TALLOC_FREE(dcs);
1620 num_dcs = 0;
1622 TALLOC_FREE(dcnames);
1623 num_dcnames = 0;
1625 TALLOC_FREE(addrs);
1626 num_addrs = 0;
1628 if (*fd != -1) {
1629 close(*fd);
1630 *fd = -1;
1634 * This should not be an infinite loop, since get_dcs() will not return
1635 * the DC added to the negative connection cache in the above
1636 * winbind_add_failed_connection_entry() call.
1638 goto again;
1641 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1643 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1644 domain_name);
1647 static void store_current_dc_in_gencache(const char *domain_name,
1648 const char *dc_name,
1649 struct cli_state *cli)
1651 char addr[INET6_ADDRSTRLEN];
1652 char *key = NULL;
1653 char *value = NULL;
1655 if (!cli_state_is_connected(cli)) {
1656 return;
1659 print_sockaddr(addr, sizeof(addr),
1660 smbXcli_conn_remote_sockaddr(cli->conn));
1662 key = current_dc_key(talloc_tos(), domain_name);
1663 if (key == NULL) {
1664 goto done;
1667 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1668 if (value == NULL) {
1669 goto done;
1672 gencache_set(key, value, 0x7fffffff);
1673 done:
1674 TALLOC_FREE(value);
1675 TALLOC_FREE(key);
1678 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1679 const char *domain_name,
1680 char **p_dc_name, char **p_dc_ip)
1682 char *key, *p;
1683 char *value = NULL;
1684 bool ret = false;
1685 char *dc_name = NULL;
1686 char *dc_ip = NULL;
1688 key = current_dc_key(talloc_tos(), domain_name);
1689 if (key == NULL) {
1690 goto done;
1692 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1693 goto done;
1695 p = strchr(value, ' ');
1696 if (p == NULL) {
1697 goto done;
1699 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1700 if (dc_ip == NULL) {
1701 goto done;
1703 dc_name = talloc_strdup(mem_ctx, p+1);
1704 if (dc_name == NULL) {
1705 goto done;
1708 if (p_dc_ip != NULL) {
1709 *p_dc_ip = dc_ip;
1710 dc_ip = NULL;
1712 if (p_dc_name != NULL) {
1713 *p_dc_name = dc_name;
1714 dc_name = NULL;
1716 ret = true;
1717 done:
1718 TALLOC_FREE(dc_name);
1719 TALLOC_FREE(dc_ip);
1720 TALLOC_FREE(key);
1721 TALLOC_FREE(value);
1722 return ret;
1725 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1726 const struct ndr_interface_table *table,
1727 struct rpc_pipe_client **ret_pipe)
1729 struct rpc_pipe_client *cli = NULL;
1730 const struct auth_session_info *session_info = NULL;
1731 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1734 session_info = get_session_info_system();
1735 SMB_ASSERT(session_info != NULL);
1737 status = rpc_pipe_open_local_np(
1738 mem_ctx, table, NULL, NULL, NULL, NULL, session_info, &cli);
1739 if (!NT_STATUS_IS_OK(status)) {
1740 return status;
1743 if (ret_pipe) {
1744 *ret_pipe = cli;
1747 return NT_STATUS_OK;
1750 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1751 struct winbindd_cm_conn *new_conn,
1752 bool need_rw_dc)
1754 TALLOC_CTX *mem_ctx;
1755 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1756 int retries;
1757 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1758 int fd = -1;
1759 bool retry = false;
1760 bool seal_pipes = true;
1762 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1763 set_domain_offline(domain);
1764 return NT_STATUS_NO_MEMORY;
1767 D_NOTICE("Creating connection to domain controller. This is a start of "
1768 "a new connection or a DC failover. The failover only happens "
1769 "if the domain has more than one DC. We will try to connect 3 "
1770 "times at most.\n");
1771 for (retries = 0; retries < 3; retries++) {
1772 bool found_dc;
1774 D_DEBUG("Attempt %d/3: DC '%s' of domain '%s'.\n",
1775 retries,
1776 domain->dcname ? domain->dcname : "",
1777 domain->name);
1779 found_dc = find_dc(mem_ctx, domain, request_flags, &fd);
1780 if (!found_dc) {
1781 /* This is the one place where we will
1782 set the global winbindd offline state
1783 to true, if a "WINBINDD_OFFLINE" entry
1784 is found in the winbindd cache. */
1785 set_global_winbindd_state_offline();
1786 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1787 break;
1790 new_conn->cli = NULL;
1792 result = cm_prepare_connection(domain, fd, domain->dcname,
1793 &new_conn->cli, &retry);
1794 if (NT_STATUS_IS_OK(result)) {
1795 break;
1797 if (!retry) {
1798 break;
1802 if (!NT_STATUS_IS_OK(result)) {
1803 /* Ensure we setup the retry handler. */
1804 set_domain_offline(domain);
1805 goto out;
1808 winbindd_set_locator_kdc_envs(domain);
1810 if (domain->online == False) {
1811 /* We're changing state from offline to online. */
1812 set_global_winbindd_state_online();
1814 set_domain_online(domain);
1817 * Much as I hate global state, this seems to be the point
1818 * where we can be certain that we have a proper connection to
1819 * a DC. wbinfo --dc-info needs that information, store it in
1820 * gencache with a looong timeout. This will need revisiting
1821 * once we start to connect to multiple DCs, wbcDcInfo is
1822 * already prepared for that.
1824 store_current_dc_in_gencache(domain->name, domain->dcname,
1825 new_conn->cli);
1827 seal_pipes = lp_winbind_sealed_pipes();
1828 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1829 domain->name,
1830 seal_pipes);
1832 if (seal_pipes) {
1833 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1834 } else {
1835 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1838 out:
1839 talloc_destroy(mem_ctx);
1840 return result;
1843 /* Close down all open pipes on a connection. */
1845 void invalidate_cm_connection(struct winbindd_domain *domain)
1847 NTSTATUS result;
1848 struct winbindd_cm_conn *conn = &domain->conn;
1850 domain->sequence_number = DOM_SEQUENCE_NONE;
1851 domain->last_seq_check = 0;
1852 domain->last_status = NT_STATUS_SERVER_DISABLED;
1854 /* We're closing down a possibly dead
1855 connection. Don't have impossibly long (10s) timeouts. */
1857 if (conn->cli) {
1858 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1861 if (conn->samr_pipe != NULL) {
1862 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1863 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1864 talloc_tos(),
1865 &conn->sam_connect_handle,
1866 &result);
1868 TALLOC_FREE(conn->samr_pipe);
1869 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1870 if (conn->cli) {
1871 cli_set_timeout(conn->cli, 500);
1875 if (conn->lsa_pipe != NULL) {
1876 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1877 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1878 talloc_tos(),
1879 &conn->lsa_policy,
1880 &result);
1882 TALLOC_FREE(conn->lsa_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_tcp != NULL) {
1890 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1891 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1892 talloc_tos(),
1893 &conn->lsa_policy,
1894 &result);
1896 TALLOC_FREE(conn->lsa_pipe_tcp);
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->netlogon_pipe != NULL) {
1904 TALLOC_FREE(conn->netlogon_pipe);
1905 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1906 if (conn->cli) {
1907 cli_set_timeout(conn->cli, 500);
1911 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1912 TALLOC_FREE(conn->netlogon_creds_ctx);
1914 if (conn->cli) {
1915 cli_shutdown(conn->cli);
1918 conn->cli = NULL;
1921 void close_conns_after_fork(void)
1923 struct winbindd_domain *domain;
1924 struct winbindd_cli_state *cli_state;
1926 for (domain = domain_list(); domain; domain = domain->next) {
1928 * first close the low level SMB TCP connection
1929 * so that we don't generate any SMBclose
1930 * requests in invalidate_cm_connection()
1932 if (cli_state_is_connected(domain->conn.cli)) {
1933 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1936 invalidate_cm_connection(domain);
1939 for (cli_state = winbindd_client_list();
1940 cli_state != NULL;
1941 cli_state = cli_state->next) {
1942 if (cli_state->sock >= 0) {
1943 close(cli_state->sock);
1944 cli_state->sock = -1;
1949 static bool connection_ok(struct winbindd_domain *domain)
1951 bool ok;
1953 ok = cli_state_is_connected(domain->conn.cli);
1954 if (!ok) {
1955 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1956 domain->dcname, domain->name));
1957 return False;
1960 if (!domain->online) {
1961 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1962 return False;
1965 return True;
1968 /* Initialize a new connection up to the RPC BIND.
1969 Bypass online status check so always does network calls. */
1971 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
1973 NTSTATUS result;
1974 bool skip_connection = domain->internal;
1975 if (need_rw_dc && domain->rodc) {
1976 skip_connection = false;
1979 /* Internal connections never use the network. */
1980 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
1981 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1984 /* Still ask the internal LSA and SAMR server about the local domain */
1985 if (skip_connection || connection_ok(domain)) {
1986 if (!domain->initialized) {
1987 set_dc_type_and_flags(domain);
1989 return NT_STATUS_OK;
1992 invalidate_cm_connection(domain);
1994 if (!domain->primary && !domain->initialized) {
1996 * Before we connect to a trust, work out if it is an
1997 * AD domain by asking our own domain.
1999 set_dc_type_and_flags_trustinfo(domain);
2002 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2004 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2005 set_dc_type_and_flags(domain);
2008 return result;
2011 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2013 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2014 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2017 SMB_ASSERT(wb_child_domain() || idmap_child());
2019 return init_dc_connection_network(domain, need_rw_dc);
2022 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2024 NTSTATUS status;
2026 status = init_dc_connection(domain, need_rw_dc);
2027 if (!NT_STATUS_IS_OK(status)) {
2028 return status;
2031 if (!domain->internal && domain->conn.cli == NULL) {
2032 /* happens for trusted domains without inbound trust */
2033 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2036 return NT_STATUS_OK;
2039 /******************************************************************************
2040 Set the trust flags (direction and forest location) for a domain
2041 ******************************************************************************/
2043 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2045 struct winbindd_domain *our_domain;
2046 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2047 WERROR werr;
2048 struct netr_DomainTrustList trusts;
2049 int i;
2050 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2051 NETR_TRUST_FLAG_OUTBOUND |
2052 NETR_TRUST_FLAG_INBOUND);
2053 struct rpc_pipe_client *cli;
2054 TALLOC_CTX *mem_ctx = NULL;
2055 struct dcerpc_binding_handle *b;
2057 if (IS_DC) {
2059 * On a DC we loaded all trusts
2060 * from configuration and never learn
2061 * new domains.
2063 return true;
2066 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2068 /* Our primary domain doesn't need to worry about trust flags.
2069 Force it to go through the network setup */
2070 if ( domain->primary ) {
2071 return False;
2074 mem_ctx = talloc_stackframe();
2075 our_domain = find_our_domain();
2076 if (our_domain->internal) {
2077 result = init_dc_connection(our_domain, false);
2078 if (!NT_STATUS_IS_OK(result)) {
2079 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2080 "Not able to make a connection to our domain: %s\n",
2081 nt_errstr(result)));
2082 TALLOC_FREE(mem_ctx);
2083 return false;
2087 /* This won't work unless our domain is AD */
2088 if ( !our_domain->active_directory ) {
2089 TALLOC_FREE(mem_ctx);
2090 return False;
2093 if (our_domain->internal) {
2094 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2095 } else if (!connection_ok(our_domain)) {
2096 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2097 "No connection to our domain!\n"));
2098 TALLOC_FREE(mem_ctx);
2099 return False;
2100 } else {
2101 result = cm_connect_netlogon(our_domain, &cli);
2104 if (!NT_STATUS_IS_OK(result)) {
2105 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2106 "a connection to %s for PIPE_NETLOGON (%s)\n",
2107 domain->name, nt_errstr(result)));
2108 TALLOC_FREE(mem_ctx);
2109 return False;
2111 b = cli->binding_handle;
2113 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2114 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2115 cli->desthost,
2116 flags,
2117 &trusts,
2118 &werr);
2119 if (!NT_STATUS_IS_OK(result)) {
2120 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2121 "failed to query trusted domain list: %s\n",
2122 nt_errstr(result)));
2123 TALLOC_FREE(mem_ctx);
2124 return false;
2126 if (!W_ERROR_IS_OK(werr)) {
2127 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2128 "failed to query trusted domain list: %s\n",
2129 win_errstr(werr)));
2130 TALLOC_FREE(mem_ctx);
2131 return false;
2134 /* Now find the domain name and get the flags */
2136 for ( i=0; i<trusts.count; i++ ) {
2137 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2138 domain->domain_flags = trusts.array[i].trust_flags;
2139 domain->domain_type = trusts.array[i].trust_type;
2140 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2142 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2143 domain->active_directory = True;
2145 /* This flag is only set if the domain is *our*
2146 primary domain and the primary domain is in
2147 native mode */
2149 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2151 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2152 "native mode.\n", domain->name,
2153 domain->native_mode ? "" : "NOT "));
2155 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2156 "running active directory.\n", domain->name,
2157 domain->active_directory ? "" : "NOT "));
2159 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2161 domain->initialized = True;
2163 break;
2167 TALLOC_FREE(mem_ctx);
2169 return domain->initialized;
2172 /******************************************************************************
2173 We can 'sense' certain things about the DC by it's replies to certain
2174 questions.
2176 This tells us if this particular remote server is Active Directory, and if it
2177 is native mode.
2178 ******************************************************************************/
2180 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2182 NTSTATUS status, result;
2183 NTSTATUS close_status = NT_STATUS_UNSUCCESSFUL;
2184 WERROR werr;
2185 TALLOC_CTX *mem_ctx = NULL;
2186 struct rpc_pipe_client *cli = NULL;
2187 struct policy_handle pol = { .handle_type = 0 };
2188 union dssetup_DsRoleInfo info;
2189 union lsa_PolicyInformation *lsa_info = NULL;
2190 union lsa_revision_info out_revision_info = {
2191 .info1 = {
2192 .revision = 0,
2195 uint32_t out_version = 0;
2197 if (!domain->internal && !connection_ok(domain)) {
2198 return;
2201 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2202 domain->name);
2203 if (!mem_ctx) {
2204 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2205 return;
2208 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2210 if (domain->internal) {
2211 status = wb_open_internal_pipe(mem_ctx,
2212 &ndr_table_dssetup,
2213 &cli);
2214 } else {
2215 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2216 &ndr_table_dssetup,
2217 &cli);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2222 "PI_DSSETUP on domain %s: (%s)\n",
2223 domain->name, nt_errstr(status)));
2225 /* if this is just a non-AD domain we need to continue
2226 * identifying so that we can in the end return with
2227 * domain->initialized = True - gd */
2229 goto no_dssetup;
2232 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2233 DS_ROLE_BASIC_INFORMATION,
2234 &info,
2235 &werr);
2236 TALLOC_FREE(cli);
2238 if (NT_STATUS_IS_OK(status)) {
2239 result = werror_to_ntstatus(werr);
2241 if (!NT_STATUS_IS_OK(status)) {
2242 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2243 "on domain %s failed: (%s)\n",
2244 domain->name, nt_errstr(status)));
2246 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2247 * every opcode on the DSSETUP pipe, continue with
2248 * no_dssetup mode here as well to get domain->initialized
2249 * set - gd */
2251 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2252 goto no_dssetup;
2255 TALLOC_FREE(mem_ctx);
2256 return;
2259 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2260 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2261 domain->native_mode = True;
2262 } else {
2263 domain->native_mode = False;
2266 no_dssetup:
2267 if (domain->internal) {
2268 status = wb_open_internal_pipe(mem_ctx,
2269 &ndr_table_lsarpc,
2270 &cli);
2271 } else {
2272 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2273 &ndr_table_lsarpc, &cli);
2275 if (!NT_STATUS_IS_OK(status)) {
2276 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2277 "PI_LSARPC on domain %s: (%s)\n",
2278 domain->name, nt_errstr(status)));
2279 TALLOC_FREE(cli);
2280 TALLOC_FREE(mem_ctx);
2281 return;
2284 status = dcerpc_lsa_open_policy_fallback(cli->binding_handle,
2285 mem_ctx,
2286 cli->srv_name_slash,
2287 true,
2288 SEC_FLAG_MAXIMUM_ALLOWED,
2289 &out_version,
2290 &out_revision_info,
2291 &pol,
2292 &result);
2294 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2295 /* This particular query is exactly what Win2k clients use
2296 to determine that the DC is active directory */
2297 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2298 &pol,
2299 LSA_POLICY_INFO_DNS,
2300 &lsa_info,
2301 &result);
2305 * If the status and result will not be OK we will fallback to
2306 * OpenPolicy.
2308 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2309 domain->active_directory = True;
2311 if (lsa_info->dns.name.string) {
2312 if (!strequal(domain->name, lsa_info->dns.name.string))
2314 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2315 "for domain %s claimed it was a DC "
2316 "for domain %s, refusing to "
2317 "initialize\n",
2318 domain->name,
2319 lsa_info->dns.name.string));
2320 TALLOC_FREE(cli);
2321 TALLOC_FREE(mem_ctx);
2322 return;
2324 talloc_free(domain->name);
2325 domain->name = talloc_strdup(domain,
2326 lsa_info->dns.name.string);
2327 if (domain->name == NULL) {
2328 goto done;
2332 if (lsa_info->dns.dns_domain.string) {
2333 if (domain->alt_name != NULL &&
2334 !strequal(domain->alt_name,
2335 lsa_info->dns.dns_domain.string))
2337 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2338 "for domain %s (%s) claimed it was "
2339 "a DC for domain %s, refusing to "
2340 "initialize\n",
2341 domain->alt_name, domain->name,
2342 lsa_info->dns.dns_domain.string));
2343 TALLOC_FREE(cli);
2344 TALLOC_FREE(mem_ctx);
2345 return;
2347 talloc_free(domain->alt_name);
2348 domain->alt_name =
2349 talloc_strdup(domain,
2350 lsa_info->dns.dns_domain.string);
2351 if (domain->alt_name == NULL) {
2352 goto done;
2356 /* See if we can set some domain trust flags about
2357 ourself */
2359 if (lsa_info->dns.dns_forest.string) {
2360 talloc_free(domain->forest_name);
2361 domain->forest_name =
2362 talloc_strdup(domain,
2363 lsa_info->dns.dns_forest.string);
2364 if (domain->forest_name == NULL) {
2365 goto done;
2368 if (strequal(domain->forest_name, domain->alt_name)) {
2369 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2373 if (lsa_info->dns.sid) {
2374 if (!is_null_sid(&domain->sid) &&
2375 !dom_sid_equal(&domain->sid,
2376 lsa_info->dns.sid))
2378 struct dom_sid_buf buf1, buf2;
2379 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2380 "for domain %s (%s) claimed it was "
2381 "a DC for domain %s, refusing to "
2382 "initialize\n",
2383 dom_sid_str_buf(&domain->sid, &buf1),
2384 domain->name,
2385 dom_sid_str_buf(lsa_info->dns.sid,
2386 &buf2)));
2387 TALLOC_FREE(cli);
2388 TALLOC_FREE(mem_ctx);
2389 return;
2391 sid_copy(&domain->sid, lsa_info->dns.sid);
2393 } else {
2394 domain->active_directory = False;
2396 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2397 SEC_FLAG_MAXIMUM_ALLOWED,
2398 &pol);
2400 if (!NT_STATUS_IS_OK(status)) {
2401 goto done;
2404 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2405 &pol,
2406 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2407 &lsa_info,
2408 &result);
2409 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2411 if (lsa_info->account_domain.name.string) {
2412 if (!strequal(domain->name,
2413 lsa_info->account_domain.name.string))
2415 DEBUG(1,
2416 ("set_dc_type_and_flags_connect: "
2417 "DC for domain %s claimed it was"
2418 " a DC for domain %s, refusing "
2419 "to initialize\n", domain->name,
2420 lsa_info->
2421 account_domain.name.string));
2422 TALLOC_FREE(cli);
2423 TALLOC_FREE(mem_ctx);
2424 return;
2426 talloc_free(domain->name);
2427 domain->name =
2428 talloc_strdup(domain,
2429 lsa_info->account_domain.name.string);
2432 if (lsa_info->account_domain.sid) {
2433 if (!is_null_sid(&domain->sid) &&
2434 !dom_sid_equal(&domain->sid,
2435 lsa_info->account_domain.sid))
2437 struct dom_sid_buf buf1, buf2;
2438 DEBUG(1,
2439 ("set_dc_type_and_flags_connect: "
2440 "DC for domain %s (%s) claimed "
2441 "it was a DC for domain %s, "
2442 "refusing to initialize\n",
2443 dom_sid_str_buf(
2444 &domain->sid, &buf1),
2445 domain->name,
2446 dom_sid_str_buf(
2447 lsa_info->account_domain.sid,
2448 &buf2)));
2449 TALLOC_FREE(cli);
2450 TALLOC_FREE(mem_ctx);
2451 return;
2453 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2457 done:
2458 if (is_valid_policy_hnd(&pol)) {
2459 dcerpc_lsa_Close(cli->binding_handle,
2460 mem_ctx,
2461 &pol,
2462 &close_status);
2465 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2466 domain->name, domain->native_mode ? "" : "NOT "));
2468 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2469 domain->name, domain->active_directory ? "" : "NOT "));
2471 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2473 TALLOC_FREE(cli);
2475 TALLOC_FREE(mem_ctx);
2477 domain->initialized = True;
2480 /**********************************************************************
2481 Set the domain_flags (trust attributes, domain operating modes, etc...
2482 ***********************************************************************/
2484 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2486 if (IS_DC) {
2488 * On a DC we loaded all trusts
2489 * from configuration and never learn
2490 * new domains.
2492 return;
2495 /* we always have to contact our primary domain */
2497 if ( domain->primary || domain->internal) {
2498 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2499 "primary or internal domain\n"));
2500 set_dc_type_and_flags_connect( domain );
2501 return;
2504 /* Use our DC to get the information if possible */
2506 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2507 /* Otherwise, fallback to contacting the
2508 domain directly */
2509 set_dc_type_and_flags_connect( domain );
2512 return;
2517 /**********************************************************************
2518 ***********************************************************************/
2520 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2521 struct netlogon_creds_cli_context **ppdc)
2523 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2524 struct rpc_pipe_client *netlogon_pipe;
2526 *ppdc = NULL;
2528 if ((!IS_DC) && (!domain->primary)) {
2529 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2532 if (domain->conn.netlogon_creds_ctx != NULL) {
2533 *ppdc = domain->conn.netlogon_creds_ctx;
2534 return NT_STATUS_OK;
2537 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2538 if (!NT_STATUS_IS_OK(result)) {
2539 return result;
2542 return NT_STATUS_OK;
2545 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2546 bool need_rw_dc,
2547 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2549 struct winbindd_cm_conn *conn;
2550 NTSTATUS status, result;
2551 struct netlogon_creds_cli_context *p_creds;
2552 struct cli_credentials *creds = NULL;
2553 bool retry = false; /* allow one retry attempt for expired session */
2554 const char *remote_name = NULL;
2555 const struct sockaddr_storage *remote_sockaddr = NULL;
2556 bool sealed_pipes = true;
2557 bool strong_key = true;
2559 if (sid_check_is_our_sam(&domain->sid)) {
2560 if (domain->rodc == false || need_rw_dc == false) {
2561 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2565 if (IS_AD_DC) {
2567 * In theory we should not use SAMR within
2568 * winbindd at all, but that's a larger task to
2569 * remove this and avoid breaking existing
2570 * setups.
2572 * At least as AD DC we have the restriction
2573 * to avoid SAMR against trusted domains,
2574 * as there're no existing setups.
2576 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2579 retry:
2580 status = init_dc_connection_rpc(domain, need_rw_dc);
2581 if (!NT_STATUS_IS_OK(status)) {
2582 return status;
2585 conn = &domain->conn;
2587 if (rpccli_is_connected(conn->samr_pipe)) {
2588 goto done;
2591 TALLOC_FREE(conn->samr_pipe);
2594 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2595 * sign and sealed pipe using the machine account password by
2596 * preference. If we can't - try schannel, if that fails, try
2597 * anonymous.
2600 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2601 if (!NT_STATUS_IS_OK(result)) {
2602 DEBUG(10, ("cm_connect_sam: No user available for "
2603 "domain %s, trying schannel\n", domain->name));
2604 goto schannel;
2607 if (cli_credentials_is_anonymous(creds)) {
2608 goto anonymous;
2611 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2612 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2615 * We have an authenticated connection. Use a SPNEGO
2616 * authenticated SAMR pipe with sign & seal.
2618 status = cli_rpc_pipe_open_with_creds(conn->cli,
2619 &ndr_table_samr,
2620 NCACN_NP,
2621 DCERPC_AUTH_TYPE_SPNEGO,
2622 conn->auth_level,
2623 remote_name,
2624 remote_sockaddr,
2625 creds,
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 "
2637 "pipe for domain %s using NTLMSSP "
2638 "authenticated pipe: user %s. Error was "
2639 "%s\n", domain->name,
2640 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2641 nt_errstr(status)));
2642 goto schannel;
2645 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2646 "domain %s using NTLMSSP authenticated "
2647 "pipe: user %s\n", domain->name,
2648 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2650 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2651 conn->samr_pipe->desthost,
2652 SEC_FLAG_MAXIMUM_ALLOWED,
2653 &conn->sam_connect_handle,
2654 &result);
2656 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2657 invalidate_cm_connection(domain);
2658 TALLOC_FREE(conn->samr_pipe);
2659 retry = true;
2660 goto retry;
2663 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2664 goto open_domain;
2666 if (NT_STATUS_IS_OK(status)) {
2667 status = result;
2670 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2671 "failed for domain %s, error was %s. Trying schannel\n",
2672 domain->name, nt_errstr(status) ));
2673 TALLOC_FREE(conn->samr_pipe);
2675 schannel:
2677 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2679 status = cm_get_schannel_creds(domain, &p_creds);
2680 if (!NT_STATUS_IS_OK(status)) {
2681 /* If this call fails - conn->cli can now be NULL ! */
2682 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2683 "for domain %s (error %s), trying anon\n",
2684 domain->name,
2685 nt_errstr(status) ));
2686 goto anonymous;
2688 TALLOC_FREE(creds);
2689 status = cli_rpc_pipe_open_schannel_with_creds(
2690 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2691 remote_name,
2692 remote_sockaddr,
2693 &conn->samr_pipe);
2695 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2696 && !retry) {
2697 invalidate_cm_connection(domain);
2698 retry = true;
2699 goto retry;
2702 if (!NT_STATUS_IS_OK(status)) {
2703 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2704 "domain %s using schannel. Error was %s\n",
2705 domain->name, nt_errstr(status) ));
2706 goto anonymous;
2708 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2709 "schannel.\n", domain->name ));
2711 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2712 conn->samr_pipe->desthost,
2713 SEC_FLAG_MAXIMUM_ALLOWED,
2714 &conn->sam_connect_handle,
2715 &result);
2717 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2718 invalidate_cm_connection(domain);
2719 TALLOC_FREE(conn->samr_pipe);
2720 retry = true;
2721 goto retry;
2724 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2725 goto open_domain;
2727 if (NT_STATUS_IS_OK(status)) {
2728 status = result;
2730 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2731 "for domain %s, error was %s. Trying anonymous\n",
2732 domain->name, nt_errstr(status) ));
2733 TALLOC_FREE(conn->samr_pipe);
2735 anonymous:
2737 sealed_pipes = lp_winbind_sealed_pipes();
2738 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2739 domain->name,
2740 sealed_pipes);
2741 strong_key = lp_require_strong_key();
2742 strong_key = lp_parm_bool(-1, "require strong key",
2743 domain->name,
2744 strong_key);
2746 /* Finally fall back to anonymous. */
2747 if (sealed_pipes || strong_key) {
2748 status = NT_STATUS_DOWNGRADE_DETECTED;
2749 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2750 "without connection level security, "
2751 "must set 'winbind sealed pipes:%s = false' and "
2752 "'require strong key:%s = false' to proceed: %s\n",
2753 domain->name, domain->name, domain->name,
2754 nt_errstr(status)));
2755 goto done;
2757 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2758 &conn->samr_pipe);
2760 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2761 && !retry) {
2762 invalidate_cm_connection(domain);
2763 retry = true;
2764 goto retry;
2767 if (!NT_STATUS_IS_OK(status)) {
2768 goto done;
2771 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2772 conn->samr_pipe->desthost,
2773 SEC_FLAG_MAXIMUM_ALLOWED,
2774 &conn->sam_connect_handle,
2775 &result);
2777 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2778 invalidate_cm_connection(domain);
2779 TALLOC_FREE(conn->samr_pipe);
2780 retry = true;
2781 goto retry;
2784 if (!NT_STATUS_IS_OK(status)) {
2785 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2786 "for domain %s Error was %s\n",
2787 domain->name, nt_errstr(status) ));
2788 goto done;
2790 if (!NT_STATUS_IS_OK(result)) {
2791 status = result;
2792 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2793 "for domain %s Error was %s\n",
2794 domain->name, nt_errstr(result)));
2795 goto done;
2798 open_domain:
2799 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2800 mem_ctx,
2801 &conn->sam_connect_handle,
2802 SEC_FLAG_MAXIMUM_ALLOWED,
2803 &domain->sid,
2804 &conn->sam_domain_handle,
2805 &result);
2806 if (!NT_STATUS_IS_OK(status)) {
2807 goto done;
2810 status = result;
2811 done:
2813 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2815 * if we got access denied, we might just have no access rights
2816 * to talk to the remote samr server server (e.g. when we are a
2817 * PDC and we are connecting a w2k8 pdc via an interdomain
2818 * trust). In that case do not invalidate the whole connection
2819 * stack
2821 TALLOC_FREE(conn->samr_pipe);
2822 ZERO_STRUCT(conn->sam_domain_handle);
2823 return status;
2824 } else if (!NT_STATUS_IS_OK(status)) {
2825 invalidate_cm_connection(domain);
2826 return status;
2829 *cli = conn->samr_pipe;
2830 *sam_handle = conn->sam_domain_handle;
2831 return status;
2834 /**********************************************************************
2835 open an schanneld ncacn_ip_tcp connection to LSA
2836 ***********************************************************************/
2838 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2839 TALLOC_CTX *mem_ctx,
2840 struct rpc_pipe_client **cli)
2842 struct winbindd_cm_conn *conn;
2843 struct netlogon_creds_cli_context *p_creds = NULL;
2844 NTSTATUS status;
2845 const char *remote_name = NULL;
2846 const struct sockaddr_storage *remote_sockaddr = NULL;
2848 DEBUG(10,("cm_connect_lsa_tcp\n"));
2850 status = init_dc_connection_rpc(domain, false);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 return status;
2855 conn = &domain->conn;
2858 * rpccli_is_connected handles more error cases
2860 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2861 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2862 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2863 goto done;
2866 TALLOC_FREE(conn->lsa_pipe_tcp);
2868 status = cm_get_schannel_creds(domain, &p_creds);
2869 if (!NT_STATUS_IS_OK(status)) {
2870 goto done;
2873 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2874 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2876 status = cli_rpc_pipe_open_schannel_with_creds(
2877 conn->cli,
2878 &ndr_table_lsarpc,
2879 NCACN_IP_TCP,
2880 p_creds,
2881 remote_name,
2882 remote_sockaddr,
2883 &conn->lsa_pipe_tcp);
2884 if (!NT_STATUS_IS_OK(status)) {
2885 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2886 nt_errstr(status)));
2887 goto done;
2890 done:
2891 if (!NT_STATUS_IS_OK(status)) {
2892 TALLOC_FREE(conn->lsa_pipe_tcp);
2893 return status;
2896 *cli = conn->lsa_pipe_tcp;
2898 return status;
2901 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2902 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2904 struct winbindd_cm_conn *conn;
2905 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2906 struct netlogon_creds_cli_context *p_creds;
2907 struct cli_credentials *creds = NULL;
2908 bool retry = false; /* allow one retry attempt for expired session */
2909 const char *remote_name = NULL;
2910 const struct sockaddr_storage *remote_sockaddr = NULL;
2911 bool sealed_pipes = true;
2912 bool strong_key = true;
2914 retry:
2915 result = init_dc_connection_rpc(domain, false);
2916 if (!NT_STATUS_IS_OK(result))
2917 return result;
2919 conn = &domain->conn;
2921 if (rpccli_is_connected(conn->lsa_pipe)) {
2922 goto done;
2925 TALLOC_FREE(conn->lsa_pipe);
2927 if (IS_DC) {
2929 * Make sure we only use schannel as AD DC.
2931 goto schannel;
2934 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2935 if (!NT_STATUS_IS_OK(result)) {
2936 DEBUG(10, ("cm_connect_lsa: No user available for "
2937 "domain %s, trying schannel\n", domain->name));
2938 goto schannel;
2941 if (cli_credentials_is_anonymous(creds)) {
2942 goto anonymous;
2945 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2946 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2949 * We have an authenticated connection. Use a SPNEGO
2950 * authenticated LSA pipe with sign & seal.
2952 result = cli_rpc_pipe_open_with_creds
2953 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2954 DCERPC_AUTH_TYPE_SPNEGO,
2955 conn->auth_level,
2956 remote_name,
2957 remote_sockaddr,
2958 creds,
2959 &conn->lsa_pipe);
2961 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
2962 && !retry) {
2963 invalidate_cm_connection(domain);
2964 retry = true;
2965 goto retry;
2968 if (!NT_STATUS_IS_OK(result)) {
2969 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2970 "domain %s using NTLMSSP authenticated pipe: user "
2971 "%s. Error was %s. Trying schannel.\n",
2972 domain->name,
2973 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2974 nt_errstr(result)));
2975 goto schannel;
2978 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2979 "NTLMSSP authenticated pipe: user %s\n",
2980 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
2982 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2983 SEC_FLAG_MAXIMUM_ALLOWED,
2984 &conn->lsa_policy);
2985 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2986 invalidate_cm_connection(domain);
2987 TALLOC_FREE(conn->lsa_pipe);
2988 retry = true;
2989 goto retry;
2992 if (NT_STATUS_IS_OK(result)) {
2993 goto done;
2996 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2997 "schannel\n"));
2999 TALLOC_FREE(conn->lsa_pipe);
3001 schannel:
3003 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3005 result = cm_get_schannel_creds(domain, &p_creds);
3006 if (!NT_STATUS_IS_OK(result)) {
3007 /* If this call fails - conn->cli can now be NULL ! */
3008 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3009 "for domain %s (error %s), trying anon\n",
3010 domain->name,
3011 nt_errstr(result) ));
3012 goto anonymous;
3015 TALLOC_FREE(creds);
3016 result = cli_rpc_pipe_open_schannel_with_creds(
3017 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3018 remote_name,
3019 remote_sockaddr,
3020 &conn->lsa_pipe);
3022 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3023 && !retry) {
3024 invalidate_cm_connection(domain);
3025 retry = true;
3026 goto retry;
3029 if (!NT_STATUS_IS_OK(result)) {
3030 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3031 "domain %s using schannel. Error was %s\n",
3032 domain->name, nt_errstr(result) ));
3033 goto anonymous;
3035 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3036 "schannel.\n", domain->name ));
3038 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3039 SEC_FLAG_MAXIMUM_ALLOWED,
3040 &conn->lsa_policy);
3042 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3043 invalidate_cm_connection(domain);
3044 TALLOC_FREE(conn->lsa_pipe);
3045 retry = true;
3046 goto retry;
3049 if (NT_STATUS_IS_OK(result)) {
3050 goto done;
3053 if (IS_DC) {
3055 * Make sure we only use schannel as AD DC.
3057 goto done;
3060 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3061 "anonymous\n"));
3063 TALLOC_FREE(conn->lsa_pipe);
3065 anonymous:
3067 if (IS_DC) {
3069 * Make sure we only use schannel as AD DC.
3071 goto done;
3074 sealed_pipes = lp_winbind_sealed_pipes();
3075 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
3076 domain->name,
3077 sealed_pipes);
3078 strong_key = lp_require_strong_key();
3079 strong_key = lp_parm_bool(-1, "require strong key",
3080 domain->name,
3081 strong_key);
3083 /* Finally fall back to anonymous. */
3084 if (sealed_pipes || strong_key) {
3085 result = NT_STATUS_DOWNGRADE_DETECTED;
3086 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3087 "without connection level security, "
3088 "must set 'winbind sealed pipes:%s = false' and "
3089 "'require strong key:%s = false' to proceed: %s\n",
3090 domain->name, domain->name, domain->name,
3091 nt_errstr(result)));
3092 goto done;
3095 result = cli_rpc_pipe_open_noauth(conn->cli,
3096 &ndr_table_lsarpc,
3097 &conn->lsa_pipe);
3099 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3100 && !retry) {
3101 invalidate_cm_connection(domain);
3102 retry = true;
3103 goto retry;
3106 if (!NT_STATUS_IS_OK(result)) {
3107 goto done;
3110 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3111 SEC_FLAG_MAXIMUM_ALLOWED,
3112 &conn->lsa_policy);
3114 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3115 invalidate_cm_connection(domain);
3116 TALLOC_FREE(conn->lsa_pipe);
3117 retry = true;
3118 goto retry;
3121 done:
3122 if (!NT_STATUS_IS_OK(result)) {
3123 invalidate_cm_connection(domain);
3124 return result;
3127 *cli = conn->lsa_pipe;
3128 *lsa_policy = conn->lsa_policy;
3129 return result;
3132 /****************************************************************************
3133 Open a LSA connection to a DC, suitable for LSA lookup calls.
3134 ****************************************************************************/
3136 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3137 TALLOC_CTX *mem_ctx,
3138 struct rpc_pipe_client **cli,
3139 struct policy_handle *lsa_policy)
3141 NTSTATUS status;
3143 if (domain->can_do_ncacn_ip_tcp) {
3144 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3145 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3146 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3147 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3148 invalidate_cm_connection(domain);
3149 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3151 if (NT_STATUS_IS_OK(status)) {
3152 return status;
3156 * we tried twice to connect via ncan_ip_tcp and schannel and
3157 * failed - maybe it is a trusted domain we can't connect to ?
3158 * do not try tcp next time - gd
3160 * This also prevents NETLOGON over TCP
3162 domain->can_do_ncacn_ip_tcp = false;
3165 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3167 return status;
3170 /****************************************************************************
3171 Open the netlogon pipe to this DC.
3172 ****************************************************************************/
3174 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3175 enum dcerpc_transport_t transport,
3176 struct rpc_pipe_client **cli)
3178 struct messaging_context *msg_ctx = global_messaging_context();
3179 struct winbindd_cm_conn *conn;
3180 NTSTATUS result;
3181 enum netr_SchannelType sec_chan_type;
3182 struct cli_credentials *creds = NULL;
3184 *cli = NULL;
3186 if (IS_DC) {
3187 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3189 * Make sure we don't even try to
3190 * connect to a foreign domain
3191 * without a direct outbound trust.
3193 return NT_STATUS_NO_TRUST_LSA_SECRET;
3197 result = init_dc_connection_rpc(domain, domain->rodc);
3198 if (!NT_STATUS_IS_OK(result)) {
3199 return result;
3202 conn = &domain->conn;
3204 if (rpccli_is_connected(conn->netlogon_pipe)) {
3205 *cli = conn->netlogon_pipe;
3206 return NT_STATUS_OK;
3209 TALLOC_FREE(conn->netlogon_pipe);
3210 TALLOC_FREE(conn->netlogon_creds_ctx);
3212 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3213 if (!NT_STATUS_IS_OK(result)) {
3214 DBG_DEBUG("No user available for domain %s when trying "
3215 "schannel\n", domain->name);
3216 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3219 if (cli_credentials_is_anonymous(creds)) {
3220 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3221 "unable to make get NETLOGON credentials\n",
3222 domain->name);
3223 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3226 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3227 if (sec_chan_type == SEC_CHAN_NULL) {
3228 const char *remote_name =
3229 smbXcli_conn_remote_name(conn->cli->conn);
3230 const struct sockaddr_storage *remote_sockaddr =
3231 smbXcli_conn_remote_sockaddr(conn->cli->conn);
3233 if (transport == NCACN_IP_TCP) {
3234 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3235 "for %s, deny NCACN_IP_TCP and let the "
3236 "caller fallback to NCACN_NP.\n",
3237 domain->name);
3238 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3241 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3242 "fallback to noauth on NCACN_NP.\n",
3243 domain->name);
3245 result = cli_rpc_pipe_open_noauth_transport(
3246 conn->cli,
3247 transport,
3248 &ndr_table_netlogon,
3249 remote_name,
3250 remote_sockaddr,
3251 &conn->netlogon_pipe);
3252 if (!NT_STATUS_IS_OK(result)) {
3253 invalidate_cm_connection(domain);
3254 return result;
3257 *cli = conn->netlogon_pipe;
3258 return NT_STATUS_OK;
3261 result = rpccli_create_netlogon_creds_ctx(creds,
3262 domain->dcname,
3263 msg_ctx,
3264 domain,
3265 &conn->netlogon_creds_ctx);
3266 if (!NT_STATUS_IS_OK(result)) {
3267 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3268 "unable to create NETLOGON credentials: %s\n",
3269 domain->name, nt_errstr(result)));
3270 return result;
3273 result = rpccli_connect_netlogon(
3274 conn->cli, transport,
3275 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3276 &conn->netlogon_pipe);
3277 conn->netlogon_force_reauth = false;
3278 if (!NT_STATUS_IS_OK(result)) {
3279 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3280 nt_errstr(result));
3281 return result;
3284 *cli = conn->netlogon_pipe;
3285 return NT_STATUS_OK;
3288 /****************************************************************************
3289 Open a NETLOGON connection to a DC, suitable for SamLogon calls.
3290 ****************************************************************************/
3292 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3293 struct rpc_pipe_client **cli)
3295 NTSTATUS status;
3297 status = init_dc_connection_rpc(domain, domain->rodc);
3298 if (!NT_STATUS_IS_OK(status)) {
3299 return status;
3302 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3303 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3304 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3305 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3306 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3307 invalidate_cm_connection(domain);
3308 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3310 if (NT_STATUS_IS_OK(status)) {
3311 return status;
3315 * we tried twice to connect via ncan_ip_tcp and schannel and
3316 * failed - maybe it is a trusted domain we can't connect to ?
3317 * do not try tcp next time - gd
3319 * This also prevents LSA over TCP
3321 domain->can_do_ncacn_ip_tcp = false;
3324 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3325 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3327 * SMB2 session expired, needs reauthentication. Drop
3328 * connection and retry.
3330 invalidate_cm_connection(domain);
3331 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3334 return status;
3337 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3338 struct rpc_pipe_client **cli,
3339 struct netlogon_creds_cli_context **ppdc)
3341 NTSTATUS status;
3343 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3344 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3347 status = cm_connect_netlogon(domain, cli);
3348 if (!NT_STATUS_IS_OK(status)) {
3349 return status;
3352 if (domain->conn.netlogon_creds_ctx == NULL) {
3353 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3356 *ppdc = domain->conn.netlogon_creds_ctx;
3357 return NT_STATUS_OK;
3360 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3361 void *private_data,
3362 uint32_t msg_type,
3363 struct server_id server_id,
3364 DATA_BLOB *data)
3366 struct winbindd_domain *domain;
3367 char *freeit = NULL;
3368 char *addr;
3370 if ((data == NULL)
3371 || (data->data == NULL)
3372 || (data->length == 0)
3373 || (data->data[data->length-1] != '\0')) {
3374 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3375 "string\n"));
3376 return;
3379 addr = (char *)data->data;
3380 DEBUG(10, ("IP %s dropped\n", addr));
3382 if (!is_ipaddress(addr)) {
3383 char *slash;
3385 * Some code sends us ip addresses with the /netmask
3386 * suffix
3388 slash = strchr(addr, '/');
3389 if (slash == NULL) {
3390 DEBUG(1, ("invalid msg_ip_dropped message: %s\n",
3391 addr));
3392 return;
3394 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3395 if (freeit == NULL) {
3396 DEBUG(1, ("talloc failed\n"));
3397 return;
3399 addr = freeit;
3400 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3403 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3404 char sockaddr[INET6_ADDRSTRLEN];
3406 if (!cli_state_is_connected(domain->conn.cli)) {
3407 continue;
3410 print_sockaddr(sockaddr, sizeof(sockaddr),
3411 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3413 if (strequal(sockaddr, addr)) {
3414 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3417 TALLOC_FREE(freeit);
3420 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3421 void *private_data,
3422 uint32_t msg_type,
3423 struct server_id server_id,
3424 DATA_BLOB *data)
3426 struct winbindd_domain *domain;
3428 for (domain = domain_list(); domain; domain = domain->next) {
3429 if (domain->internal) {
3430 continue;
3432 invalidate_cm_connection(domain);