s3:winbindd: make use of ads_connect_cldap_only() in dcip_check_name_ads()
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob5f8018e996e13c6def87516c1a13ccdfd82a7400
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
34 selection etc
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
46 implementation. -tpot
51 TODO:
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
57 various sam handles.
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "libsmb/namequery.h"
64 #include "../libcli/auth/libcli_auth.h"
65 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
66 #include "rpc_client/cli_pipe.h"
67 #include "rpc_client/cli_netlogon.h"
68 #include "../librpc/gen_ndr/ndr_samr_c.h"
69 #include "../librpc/gen_ndr/ndr_lsa_c.h"
70 #include "rpc_client/cli_lsarpc.h"
71 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
72 #include "libads/sitename_cache.h"
73 #include "libsmb/libsmb.h"
74 #include "libsmb/clidgram.h"
75 #include "ads.h"
76 #include "secrets.h"
77 #include "../libcli/security/security.h"
78 #include "passdb.h"
79 #include "messages.h"
80 #include "auth/gensec/gensec.h"
81 #include "../libcli/smb/smbXcli_base.h"
82 #include "libcli/auth/netlogon_creds_cli.h"
83 #include "auth.h"
84 #include "rpc_server/rpc_ncacn_np.h"
85 #include "auth/credentials/credentials.h"
86 #include "lib/param/param.h"
87 #include "lib/gencache.h"
88 #include "lib/util/string_wrappers.h"
89 #include "lib/global_contexts.h"
90 #include "librpc/gen_ndr/ndr_winbind_c.h"
92 #undef DBGC_CLASS
93 #define DBGC_CLASS DBGC_WINBIND
95 struct dc_name_ip {
96 fstring name;
97 struct sockaddr_storage ss;
100 extern struct winbindd_methods reconnect_methods;
102 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
103 static void set_dc_type_and_flags( struct winbindd_domain *domain );
104 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
105 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
106 struct dc_name_ip **dcs, int *num_dcs,
107 uint32_t request_flags);
109 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
110 void *private_data,
111 uint32_t msg_type,
112 struct server_id server_id,
113 DATA_BLOB *data)
115 const char *domain_name = (const char *)data->data;
116 struct winbindd_domain *domain;
118 domain = find_domain_from_name_noinit(domain_name);
119 if (domain == NULL) {
120 DBG_DEBUG("Domain %s not found!\n", domain_name);
121 return;
124 DBG_DEBUG("Domain %s was %s, change to offline now.\n",
125 domain_name,
126 domain->online ? "online" : "offline");
128 domain->online = false;
131 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
132 void *private_data,
133 uint32_t msg_type,
134 struct server_id server_id,
135 DATA_BLOB *data)
137 const char *domain_name = (const char *)data->data;
138 struct winbindd_domain *domain;
140 domain = find_domain_from_name_noinit(domain_name);
141 if (domain == NULL) {
142 return;
145 SMB_ASSERT(wb_child_domain() == NULL);
147 DBG_DEBUG("Domain %s was %s, marking as online now!\n",
148 domain_name,
149 domain->online ? "online" : "offline");
151 domain->online = true;
154 /****************************************************************
155 Set domain offline and also add handler to put us back online
156 if we detect a DC.
157 ****************************************************************/
159 void set_domain_offline(struct winbindd_domain *domain)
161 pid_t parent_pid = getppid();
163 DEBUG(10,("set_domain_offline: called for domain %s\n",
164 domain->name ));
166 if (domain->internal) {
167 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
168 domain->name ));
169 return;
172 domain->online = False;
174 /* Offline domains are always initialized. They're
175 re-initialized when they go back online. */
177 domain->initialized = True;
179 /* Send a message to the parent that the domain is offline. */
180 if (parent_pid > 1 && !domain->internal) {
181 messaging_send_buf(global_messaging_context(),
182 pid_to_procid(parent_pid),
183 MSG_WINBIND_DOMAIN_OFFLINE,
184 (uint8_t *)domain->name,
185 strlen(domain->name) + 1);
188 /* Send an offline message to the idmap child when our
189 primary domain goes offline */
190 if ( domain->primary ) {
191 pid_t idmap_pid = idmap_child_pid();
193 if (idmap_pid != 0) {
194 messaging_send_buf(global_messaging_context(),
195 pid_to_procid(idmap_pid),
196 MSG_WINBIND_OFFLINE,
197 (const uint8_t *)domain->name,
198 strlen(domain->name)+1);
202 return;
205 /****************************************************************
206 Set domain online - if allowed.
207 ****************************************************************/
209 static void set_domain_online(struct winbindd_domain *domain)
211 pid_t parent_pid = getppid();
213 DEBUG(10,("set_domain_online: called for domain %s\n",
214 domain->name ));
216 if (domain->internal) {
217 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
218 domain->name ));
219 return;
222 if (get_global_winbindd_state_offline()) {
223 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
224 domain->name ));
225 return;
228 winbindd_set_locator_kdc_envs(domain);
230 /* If we are waiting to get a krb5 ticket, trigger immediately. */
231 ccache_regain_all_now();
233 /* Ok, we're out of any startup mode now... */
234 domain->startup = False;
236 if (domain->online == False) {
237 /* We were offline - now we're online. We default to
238 using the MS-RPC backend if we started offline,
239 and if we're going online for the first time we
240 should really re-initialize the backends and the
241 checks to see if we're talking to an AD or NT domain.
244 domain->initialized = False;
246 /* 'reconnect_methods' is the MS-RPC backend. */
247 if (domain->backend == &reconnect_methods) {
248 domain->backend = NULL;
252 domain->online = True;
254 /* Send a message to the parent that the domain is online. */
255 if (parent_pid > 1 && !domain->internal) {
256 messaging_send_buf(global_messaging_context(),
257 pid_to_procid(parent_pid),
258 MSG_WINBIND_DOMAIN_ONLINE,
259 (uint8_t *)domain->name,
260 strlen(domain->name) + 1);
263 /* Send an online message to the idmap child when our
264 primary domain comes online */
266 if ( domain->primary ) {
267 pid_t idmap_pid = idmap_child_pid();
269 if (idmap_pid != 0) {
270 messaging_send_buf(global_messaging_context(),
271 pid_to_procid(idmap_pid),
272 MSG_WINBIND_ONLINE,
273 (const uint8_t *)domain->name,
274 strlen(domain->name)+1);
278 return;
281 /****************************************************************
282 Requested to set a domain online.
283 ****************************************************************/
285 void set_domain_online_request(struct winbindd_domain *domain)
287 NTSTATUS status;
289 SMB_ASSERT(wb_child_domain() || idmap_child());
291 DEBUG(10,("set_domain_online_request: called for domain %s\n",
292 domain->name ));
294 if (get_global_winbindd_state_offline()) {
295 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
296 domain->name ));
297 return;
300 if (domain->internal) {
301 DEBUG(10, ("set_domain_online_request: Internal domains are "
302 "always online\n"));
303 return;
307 * This call takes care of setting the online flag to true if we
308 * connected, or tell the parent to ping us back if false. Bypasses
309 * online check so always does network calls.
311 status = init_dc_connection_network(domain, true);
312 DBG_DEBUG("init_dc_connection_network(), returned %s, called for "
313 "domain %s (online = %s)\n",
314 nt_errstr(status),
315 domain->name,
316 domain->online ? "true" : "false");
319 /****************************************************************
320 Add -ve connection cache entries for domain and realm.
321 ****************************************************************/
323 static void winbind_add_failed_connection_entry(
324 const struct winbindd_domain *domain,
325 const char *server,
326 NTSTATUS result)
328 add_failed_connection_entry(domain->name, server, result);
329 /* If this was the saf name for the last thing we talked to,
330 remove it. */
331 saf_delete(domain->name);
332 if (domain->alt_name != NULL) {
333 add_failed_connection_entry(domain->alt_name, server, result);
334 saf_delete(domain->alt_name);
336 winbindd_unset_locator_kdc_env(domain);
339 /* Choose between anonymous or authenticated connections. We need to use
340 an authenticated connection if DCs have the RestrictAnonymous registry
341 entry set > 0, or the "Additional restrictions for anonymous
342 connections" set in the win2k Local Security Policy.
344 Caller to free() result in domain, username, password
347 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
349 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
350 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
351 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
353 if (*username && **username) {
355 if (!*domain || !**domain)
356 *domain = smb_xstrdup(lp_workgroup());
358 if (!*password || !**password)
359 *password = smb_xstrdup("");
361 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
362 *domain, *username));
364 } else {
365 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
366 *username = smb_xstrdup("");
367 *domain = smb_xstrdup("");
368 *password = smb_xstrdup("");
372 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
373 struct cli_credentials **_creds)
376 TALLOC_CTX *frame = talloc_stackframe();
377 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
378 struct loadparm_context *lp_ctx;
379 char *username = NULL;
380 char *netbios_domain = NULL;
381 char *password = NULL;
382 struct cli_credentials *creds = NULL;
383 bool ok;
385 cm_get_ipc_userpass(&username, &netbios_domain, &password);
387 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
388 if (lp_ctx == NULL) {
389 DEBUG(1, ("loadparm_init_s3 failed\n"));
390 status = NT_STATUS_INTERNAL_ERROR;
391 goto fail;
394 creds = cli_credentials_init(mem_ctx);
395 if (creds == NULL) {
396 status = NT_STATUS_NO_MEMORY;
397 goto fail;
400 ok = cli_credentials_set_conf(creds, lp_ctx);
401 if (!ok) {
402 status = NT_STATUS_INTERNAL_ERROR;
403 goto fail;
406 cli_credentials_set_kerberos_state(creds,
407 CRED_USE_KERBEROS_DISABLED,
408 CRED_SPECIFIED);
410 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
411 if (!ok) {
412 status = NT_STATUS_NO_MEMORY;
413 goto fail;
416 ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
417 if (!ok) {
418 status = NT_STATUS_NO_MEMORY;
419 goto fail;
422 ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
423 if (!ok) {
424 status = NT_STATUS_NO_MEMORY;
425 goto fail;
428 *_creds = creds;
429 creds = NULL;
430 status = NT_STATUS_OK;
431 fail:
432 TALLOC_FREE(creds);
433 SAFE_FREE(username);
434 SAFE_FREE(netbios_domain);
435 SAFE_FREE(password);
436 TALLOC_FREE(frame);
437 return status;
440 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
442 TALLOC_CTX *frame = talloc_stackframe();
443 char *ipc_account = NULL;
444 char *ipc_domain = NULL;
445 char *ipc_password = NULL;
446 const char *creds_account = NULL;
447 const char *creds_domain = NULL;
448 const char *creds_password = NULL;
449 bool ret = false;
451 cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
453 creds_account = cli_credentials_get_username(creds);
454 creds_domain = cli_credentials_get_domain(creds);
455 creds_password = cli_credentials_get_password(creds);
457 if (!strequal(ipc_domain, creds_domain)) {
458 goto done;
461 if (!strequal(ipc_account, creds_account)) {
462 goto done;
465 if (!strcsequal(ipc_password, creds_password)) {
466 goto done;
469 ret = true;
470 done:
471 SAFE_FREE(ipc_account);
472 SAFE_FREE(ipc_domain);
473 SAFE_FREE(ipc_password);
474 TALLOC_FREE(frame);
475 return ret;
478 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
479 fstring dcname,
480 struct sockaddr_storage *dc_ss,
481 uint32_t request_flags)
483 struct winbindd_domain *our_domain = NULL;
484 struct rpc_pipe_client *netlogon_pipe = NULL;
485 NTSTATUS result;
486 WERROR werr;
487 TALLOC_CTX *mem_ctx;
488 unsigned int orig_timeout;
489 const char *tmp = NULL;
490 const char *p;
491 struct dcerpc_binding_handle *b;
493 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
494 * moment.... */
496 if (IS_DC) {
497 return False;
500 if (domain->primary) {
501 return False;
504 our_domain = find_our_domain();
506 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
507 return False;
510 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
511 if (!NT_STATUS_IS_OK(result)) {
512 talloc_destroy(mem_ctx);
513 return False;
516 b = netlogon_pipe->binding_handle;
518 /* This call can take a long time - allow the server to time out.
519 35 seconds should do it. */
521 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
523 if (our_domain->active_directory) {
524 struct netr_DsRGetDCNameInfo *domain_info = NULL;
527 * TODO request flags are not respected in the server
528 * (and in some cases, like REQUIRE_PDC, causes an error)
530 result = dcerpc_netr_DsRGetDCName(b,
531 mem_ctx,
532 our_domain->dcname,
533 domain->name,
534 NULL,
535 NULL,
536 request_flags|DS_RETURN_DNS_NAME,
537 &domain_info,
538 &werr);
539 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
540 tmp = talloc_strdup(
541 mem_ctx, domain_info->dc_unc);
542 if (tmp == NULL) {
543 DBG_ERR("talloc_strdup failed for dc_unc[%s]\n",
544 domain_info->dc_unc);
545 talloc_destroy(mem_ctx);
546 return false;
548 if (domain->alt_name == NULL) {
549 domain->alt_name = talloc_strdup(domain,
550 domain_info->domain_name);
551 if (domain->alt_name == NULL) {
552 DBG_ERR("talloc_strdup failed for "
553 "domain_info->domain_name[%s]\n",
554 domain_info->domain_name);
555 talloc_destroy(mem_ctx);
556 return false;
559 if (domain->forest_name == NULL) {
560 domain->forest_name = talloc_strdup(domain,
561 domain_info->forest_name);
562 if (domain->forest_name == NULL) {
563 DBG_ERR("talloc_strdup failed for "
564 "domain_info->forest_name[%s]\n",
565 domain_info->forest_name);
566 talloc_destroy(mem_ctx);
567 return false;
571 } else {
572 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
573 our_domain->dcname,
574 domain->name,
575 &tmp,
576 &werr);
579 /* And restore our original timeout. */
580 rpccli_set_timeout(netlogon_pipe, orig_timeout);
582 if (!NT_STATUS_IS_OK(result)) {
583 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
584 nt_errstr(result)));
585 talloc_destroy(mem_ctx);
586 return false;
589 if (!W_ERROR_IS_OK(werr)) {
590 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
591 win_errstr(werr)));
592 talloc_destroy(mem_ctx);
593 return false;
596 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
597 p = strip_hostname(tmp);
599 fstrcpy(dcname, p);
601 talloc_destroy(mem_ctx);
603 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
605 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
606 return False;
609 return True;
613 * Helper function to assemble trust password and account name
615 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
616 TALLOC_CTX *mem_ctx,
617 bool netlogon,
618 struct cli_credentials **_creds)
620 const struct winbindd_domain *creds_domain = NULL;
621 struct cli_credentials *creds;
622 NTSTATUS status;
623 bool force_machine_account = false;
625 /* If we are a DC and this is not our own domain */
627 if (!domain->active_directory) {
628 if (!netlogon) {
630 * For non active directory domains
631 * we can only use NTLMSSP for SMB.
633 * But the trust account is not allowed
634 * to use SMB with NTLMSSP.
636 force_machine_account = true;
640 if (IS_DC && !force_machine_account) {
641 creds_domain = domain;
642 } else {
643 creds_domain = find_our_domain();
644 if (creds_domain == NULL) {
645 return NT_STATUS_INVALID_SERVER_STATE;
649 status = pdb_get_trust_credentials(creds_domain->name,
650 creds_domain->alt_name,
651 mem_ctx,
652 &creds);
653 if (!NT_STATUS_IS_OK(status)) {
654 goto ipc_fallback;
657 if (creds_domain != domain) {
659 * We can only use schannel against a direct trust
661 cli_credentials_set_secure_channel_type(creds,
662 SEC_CHAN_NULL);
665 *_creds = creds;
666 return NT_STATUS_OK;
668 ipc_fallback:
669 if (netlogon) {
670 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
673 status = cm_get_ipc_credentials(mem_ctx, &creds);
674 if (!NT_STATUS_IS_OK(status)) {
675 return status;
678 *_creds = creds;
679 return NT_STATUS_OK;
682 /************************************************************************
683 Given a fd with a just-connected TCP connection to a DC, open a connection
684 to the pipe.
685 ************************************************************************/
687 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
688 const int sockfd,
689 const char *controller,
690 struct cli_state **cli,
691 bool *retry)
693 bool try_ipc_auth = false;
694 const char *machine_principal = NULL;
695 const char *machine_realm = NULL;
696 const char *machine_account = NULL;
697 const char *machine_domain = NULL;
698 int flags = 0;
699 struct cli_credentials *creds = NULL;
701 struct named_mutex *mutex;
703 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
704 NTSTATUS tmp_status;
705 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
707 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
709 if (IS_DC) {
710 if (domain->secure_channel_type == SEC_CHAN_NULL) {
712 * Make sure we don't even try to
713 * connect to a foreign domain
714 * without a direct outbound trust.
716 close(sockfd);
717 return NT_STATUS_NO_TRUST_LSA_SECRET;
721 * As AD DC we only use netlogon and lsa
722 * using schannel over an anonymous transport
723 * (ncacn_ip_tcp or ncacn_np).
725 * Currently we always establish the SMB connection,
726 * even if we don't use it, because we later use ncacn_ip_tcp.
728 * As we won't use the SMB connection there's no
729 * need to try kerberos. And NT4 domains expect
730 * an anonymous IPC$ connection anyway.
732 smb_sign_client_connections = SMB_SIGNING_OFF;
735 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
737 * If we are connecting to our own AD domain, require
738 * smb signing to disrupt MITM attacks
740 if (domain->primary && lp_security() == SEC_ADS) {
741 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
743 * If we are in or are an AD domain and connecting to another
744 * AD domain in our forest
745 * then require smb signing to disrupt MITM attacks
747 } else if ((lp_security() == SEC_ADS)
748 && domain->active_directory
749 && (domain->domain_trust_attribs
750 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
751 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
755 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
756 controller, domain->name ));
758 *retry = True;
760 mutex = grab_named_mutex(talloc_tos(), controller,
761 WINBIND_SERVER_MUTEX_WAIT_TIME);
762 if (mutex == NULL) {
763 close(sockfd);
764 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
765 controller));
766 result = NT_STATUS_POSSIBLE_DEADLOCK;
767 goto done;
771 * cm_prepare_connection() is responsible that sockfd does not leak.
772 * Once cli_state_create() returns with success, the
773 * smbXcli_conn_destructor() makes sure that close(sockfd) is finally
774 * called. Till that, close(sockfd) must be called on every unsuccessful
775 * return.
777 *cli = cli_state_create(NULL, sockfd, controller,
778 smb_sign_client_connections, flags);
779 if (*cli == NULL) {
780 close(sockfd);
781 DEBUG(1, ("Could not cli_initialize\n"));
782 result = NT_STATUS_NO_MEMORY;
783 goto done;
786 cli_set_timeout(*cli, 10000); /* 10 seconds */
788 set_socket_options(sockfd, lp_socket_options());
790 result = smbXcli_negprot((*cli)->conn,
791 (*cli)->timeout,
792 lp_client_ipc_min_protocol(),
793 lp_client_ipc_max_protocol(),
794 NULL,
795 NULL,
796 NULL);
798 if (!NT_STATUS_IS_OK(result)) {
799 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
800 goto done;
803 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
804 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
805 try_ipc_auth = true;
806 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
807 try_ipc_auth = true;
808 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
810 * If we are forcing on SMB signing, then we must
811 * require authentication unless this is a one-way
812 * trust, and we have no stored user/password
814 try_ipc_auth = true;
817 if (IS_DC) {
819 * As AD DC we only use netlogon and lsa
820 * using schannel over an anonymous transport
821 * (ncacn_ip_tcp or ncacn_np).
823 * Currently we always establish the SMB connection,
824 * even if we don't use it, because we later use ncacn_ip_tcp.
826 * As we won't use the SMB connection there's no
827 * need to try kerberos. And NT4 domains expect
828 * an anonymous IPC$ connection anyway.
830 try_ipc_auth = false;
833 if (try_ipc_auth) {
834 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
835 if (!NT_STATUS_IS_OK(result)) {
836 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
837 domain->name, nt_errstr(result)));
838 goto done;
840 } else {
842 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
843 * would try and authentication with our machine
844 * account password and fail. This is very rare in
845 * the modern world however
847 creds = cli_credentials_init_anon(talloc_tos());
848 if (creds == NULL) {
849 result = NT_STATUS_NO_MEMORY;
850 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
851 domain->name, nt_errstr(result)));
852 goto done;
856 machine_principal = cli_credentials_get_principal(creds,
857 talloc_tos());
858 machine_realm = cli_credentials_get_realm(creds);
859 machine_account = cli_credentials_get_username(creds);
860 machine_domain = cli_credentials_get_domain(creds);
862 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
863 "[%s] and realm [%s]\n",
864 controller, domain->name, domain->alt_name,
865 machine_domain, machine_account,
866 machine_principal, machine_realm));
868 if (cli_credentials_is_anonymous(creds)) {
869 goto anon_fallback;
872 winbindd_set_locator_kdc_envs(domain);
874 result = cli_session_setup_creds(*cli, creds);
875 if (NT_STATUS_IS_OK(result)) {
876 goto session_setup_done;
879 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
880 controller,
881 cli_credentials_get_unparsed_name(creds, talloc_tos()),
882 nt_errstr(result)));
885 * If we are not going to validate the connection
886 * with SMB signing, then allow us to fall back to
887 * anonymous
889 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
890 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
891 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
892 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
893 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
894 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
895 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
897 if (!cm_is_ipc_credentials(creds)) {
898 goto ipc_fallback;
901 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
902 goto done;
905 goto anon_fallback;
908 goto done;
910 ipc_fallback:
911 TALLOC_FREE(creds);
912 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
913 if (!NT_STATUS_IS_OK(tmp_status)) {
914 result = tmp_status;
915 goto done;
918 if (cli_credentials_is_anonymous(creds)) {
919 goto anon_fallback;
922 machine_account = cli_credentials_get_username(creds);
923 machine_domain = cli_credentials_get_domain(creds);
925 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
926 "[%s]\\[%s]\n", controller, lp_netbios_name(),
927 machine_domain, machine_account));
929 result = cli_session_setup_creds(*cli, creds);
930 if (NT_STATUS_IS_OK(result)) {
931 goto session_setup_done;
934 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
935 controller,
936 cli_credentials_get_unparsed_name(creds, talloc_tos()),
937 nt_errstr(result)));
940 * If we are not going to validate the connection
941 * with SMB signing, then allow us to fall back to
942 * anonymous
944 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
945 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
946 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
947 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
948 || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
949 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
950 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
952 goto anon_fallback;
955 goto done;
957 anon_fallback:
958 TALLOC_FREE(creds);
960 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
961 goto done;
964 /* Fall back to anonymous connection, this might fail later */
965 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
966 "connection for DC %s\n",
967 controller ));
969 result = cli_session_setup_anon(*cli);
970 if (NT_STATUS_IS_OK(result)) {
971 DEBUG(5, ("Connected anonymously\n"));
972 goto session_setup_done;
975 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
976 controller, nt_errstr(result)));
978 /* We can't session setup */
979 goto done;
981 session_setup_done:
982 TALLOC_FREE(creds);
985 * This should be a short term hack until
986 * dynamic re-authentication is implemented.
988 * See Bug 9175 - winbindd doesn't recover from
989 * NT_STATUS_NETWORK_SESSION_EXPIRED
991 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
992 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
995 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
996 if (!NT_STATUS_IS_OK(result)) {
997 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
998 goto done;
1000 tcon_status = result;
1002 /* cache the server name for later connections */
1004 saf_store(domain->name, controller);
1005 if (domain->alt_name) {
1006 saf_store(domain->alt_name, controller);
1009 winbindd_set_locator_kdc_envs(domain);
1011 TALLOC_FREE(mutex);
1012 *retry = False;
1014 result = NT_STATUS_OK;
1016 done:
1017 TALLOC_FREE(mutex);
1018 TALLOC_FREE(creds);
1020 if (NT_STATUS_IS_OK(result)) {
1021 result = tcon_status;
1024 if (!NT_STATUS_IS_OK(result)) {
1025 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1026 controller, nt_errstr(result)));
1027 winbind_add_failed_connection_entry(domain, controller, result);
1028 if ((*cli) != NULL) {
1029 cli_shutdown(*cli);
1030 *cli = NULL;
1034 return result;
1037 /*******************************************************************
1038 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1039 array.
1041 Keeps the list unique by not adding duplicate entries.
1043 @param[in] mem_ctx talloc memory context to allocate from
1044 @param[in] domain_name domain of the DC
1045 @param[in] dcname name of the DC to add to the list
1046 @param[in] pss Internet address and port pair to add to the list
1047 @param[in,out] dcs array of dc_name_ip structures to add to
1048 @param[in,out] num_dcs number of dcs returned in the dcs array
1049 @return true if the list was added to, false otherwise
1050 *******************************************************************/
1052 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1053 const char *dcname, struct sockaddr_storage *pss,
1054 struct dc_name_ip **dcs, int *num)
1056 int i = 0;
1058 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1059 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1060 return False;
1063 /* Make sure there's no duplicates in the list */
1064 for (i=0; i<*num; i++)
1065 if (sockaddr_equal(
1066 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1067 (struct sockaddr *)(void *)pss))
1068 return False;
1070 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1072 if (*dcs == NULL)
1073 return False;
1075 fstrcpy((*dcs)[*num].name, dcname);
1076 (*dcs)[*num].ss = *pss;
1077 *num += 1;
1078 return True;
1081 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1082 struct sockaddr_storage *pss, uint16_t port,
1083 struct sockaddr_storage **addrs, int *num)
1085 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1087 if (*addrs == NULL) {
1088 *num = 0;
1089 return False;
1092 (*addrs)[*num] = *pss;
1093 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1095 *num += 1;
1096 return True;
1099 #ifdef HAVE_ADS
1100 static bool dcip_check_name_ads(const struct winbindd_domain *domain,
1101 struct samba_sockaddr *sa,
1102 uint32_t request_flags,
1103 TALLOC_CTX *mem_ctx,
1104 char **namep)
1106 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1107 char *name = NULL;
1108 ADS_STRUCT *ads = NULL;
1109 ADS_STATUS ads_status;
1110 char addr[INET6_ADDRSTRLEN];
1112 print_sockaddr(addr, sizeof(addr), &sa->u.ss);
1113 D_DEBUG("Trying to figure out the DC name for domain '%s' at IP '%s'.\n",
1114 domain->name,
1115 addr);
1117 ads = ads_init(tmp_ctx,
1118 domain->alt_name,
1119 domain->name,
1120 addr,
1121 ADS_SASL_PLAIN);
1122 if (ads == NULL) {
1123 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1124 goto out;
1126 ads->config.flags |= request_flags;
1127 ads->server.no_fallback = true;
1129 ads_status = ads_connect_cldap_only(ads);
1130 if (!ADS_ERR_OK(ads_status)) {
1131 goto out;
1134 /* We got a cldap packet. */
1135 name = talloc_strdup(tmp_ctx, ads->config.ldap_server_name);
1136 if (name == NULL) {
1137 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1138 goto out;
1140 namecache_store(name, 0x20, 1, sa);
1142 DBG_DEBUG("CLDAP flags = 0x%"PRIx32"\n", ads->config.flags);
1144 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1145 if (ads_closest_dc(ads)) {
1146 char *sitename = sitename_fetch(tmp_ctx,
1147 ads->config.realm);
1149 /* We're going to use this KDC for this realm/domain.
1150 If we are using sites, then force the krb5 libs
1151 to use this KDC. */
1153 create_local_private_krb5_conf_for_domain(domain->alt_name,
1154 domain->name,
1155 sitename,
1156 &sa->u.ss);
1158 TALLOC_FREE(sitename);
1159 } else {
1160 /* use an off site KDC */
1161 create_local_private_krb5_conf_for_domain(domain->alt_name,
1162 domain->name,
1163 NULL,
1164 &sa->u.ss);
1166 winbindd_set_locator_kdc_envs(domain);
1168 /* Ensure we contact this DC also. */
1169 saf_store(domain->name, name);
1170 saf_store(domain->alt_name, name);
1173 D_DEBUG("DC name for domain '%s' at IP '%s' is '%s'\n",
1174 domain->name,
1175 addr,
1176 name);
1177 *namep = talloc_move(mem_ctx, &name);
1179 out:
1180 TALLOC_FREE(tmp_ctx);
1182 return ADS_ERR_OK(ads_status) ? true : false;
1184 #endif
1186 /*******************************************************************
1187 convert an ip to a name
1188 For an AD Domain, it checks the requirements of the request flags.
1189 *******************************************************************/
1191 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1192 const struct winbindd_domain *domain,
1193 struct sockaddr_storage *pss,
1194 char **name, uint32_t request_flags)
1196 struct samba_sockaddr sa = {0};
1197 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1198 NTSTATUS status;
1199 const char *dc_name;
1200 fstring nbtname;
1201 #ifdef HAVE_ADS
1202 bool is_ad_domain = false;
1203 #endif
1204 bool ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
1205 if (!ok) {
1206 return false;
1209 #ifdef HAVE_ADS
1210 /* For active directory servers, try to get the ldap server name.
1211 None of these failures should be considered critical for now */
1213 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1214 is_ad_domain = true;
1215 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1216 is_ad_domain = domain->active_directory;
1219 if (is_ad_domain) {
1220 return dcip_check_name_ads(domain,
1221 &sa,
1222 request_flags,
1223 mem_ctx,
1224 name);
1226 #endif
1229 size_t len = strlen(lp_netbios_name());
1230 char my_acct_name[len+2];
1232 snprintf(my_acct_name,
1233 sizeof(my_acct_name),
1234 "%s$",
1235 lp_netbios_name());
1237 status = nbt_getdc(global_messaging_context(), 10, &sa.u.ss,
1238 domain->name, &domain->sid,
1239 my_acct_name, ACB_WSTRUST,
1240 nt_version, mem_ctx, &nt_version,
1241 &dc_name, NULL);
1243 if (NT_STATUS_IS_OK(status)) {
1244 *name = talloc_strdup(mem_ctx, dc_name);
1245 if (*name == NULL) {
1246 return false;
1248 namecache_store(*name, 0x20, 1, &sa);
1249 return True;
1252 /* try node status request */
1254 if (name_status_find(domain->name, 0x1c, 0x20, &sa.u.ss, nbtname) ) {
1255 namecache_store(nbtname, 0x20, 1, &sa);
1257 if (name != NULL) {
1258 *name = talloc_strdup(mem_ctx, nbtname);
1259 if (*name == NULL) {
1260 return false;
1264 return true;
1266 return False;
1269 /*******************************************************************
1270 Retrieve a list of IP addresses for domain controllers.
1272 The array is sorted in the preferred connection order.
1274 @param[in] mem_ctx talloc memory context to allocate from
1275 @param[in] domain domain to retrieve DCs for
1276 @param[out] dcs array of dcs that will be returned
1277 @param[out] num_dcs number of dcs returned in the dcs array
1278 @return always true
1279 *******************************************************************/
1281 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1282 struct dc_name_ip **dcs, int *num_dcs,
1283 uint32_t request_flags)
1285 fstring dcname;
1286 struct sockaddr_storage ss;
1287 struct samba_sockaddr *sa_list = NULL;
1288 size_t salist_size = 0;
1289 size_t i;
1290 bool is_our_domain;
1291 enum security_types sec = (enum security_types)lp_security();
1293 is_our_domain = strequal(domain->name, lp_workgroup());
1295 /* If not our domain, get the preferred DC, by asking our primary DC */
1296 if ( !is_our_domain
1297 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1298 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1299 num_dcs) )
1301 char addr[INET6_ADDRSTRLEN];
1302 print_sockaddr(addr, sizeof(addr), &ss);
1303 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1304 dcname, addr));
1305 return True;
1308 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1309 char *sitename = NULL;
1311 /* We need to make sure we know the local site before
1312 doing any DNS queries, as this will restrict the
1313 get_sorted_dc_list() call below to only fetching
1314 DNS records for the correct site. */
1316 /* Find any DC to get the site record.
1317 We deliberately don't care about the
1318 return here. */
1320 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1322 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1323 if (sitename) {
1325 /* Do the site-specific AD dns lookup first. */
1326 (void)get_sorted_dc_list(mem_ctx,
1327 domain->alt_name,
1328 sitename,
1329 &sa_list,
1330 &salist_size,
1331 true);
1333 /* Add ips to the DC array. We don't look up the name
1334 of the DC in this function, but we fill in the char*
1335 of the ip now to make the failed connection cache
1336 work */
1337 for ( i=0; i<salist_size; i++ ) {
1338 char addr[INET6_ADDRSTRLEN];
1339 print_sockaddr(addr, sizeof(addr),
1340 &sa_list[i].u.ss);
1341 add_one_dc_unique(mem_ctx,
1342 domain->name,
1343 addr,
1344 &sa_list[i].u.ss,
1345 dcs,
1346 num_dcs);
1349 TALLOC_FREE(sa_list);
1350 TALLOC_FREE(sitename);
1351 salist_size = 0;
1354 /* Now we add DCs from the main AD DNS lookup. */
1355 (void)get_sorted_dc_list(mem_ctx,
1356 domain->alt_name,
1357 NULL,
1358 &sa_list,
1359 &salist_size,
1360 true);
1362 for ( i=0; i<salist_size; i++ ) {
1363 char addr[INET6_ADDRSTRLEN];
1364 print_sockaddr(addr, sizeof(addr),
1365 &sa_list[i].u.ss);
1366 add_one_dc_unique(mem_ctx,
1367 domain->name,
1368 addr,
1369 &sa_list[i].u.ss,
1370 dcs,
1371 num_dcs);
1374 TALLOC_FREE(sa_list);
1375 salist_size = 0;
1378 /* Try standard netbios queries if no ADS and fall back to DNS queries
1379 * if alt_name is available */
1380 if (*num_dcs == 0) {
1381 (void)get_sorted_dc_list(mem_ctx,
1382 domain->name,
1383 NULL,
1384 &sa_list,
1385 &salist_size,
1386 false);
1387 if (salist_size == 0) {
1388 if (domain->alt_name != NULL) {
1389 (void)get_sorted_dc_list(mem_ctx,
1390 domain->alt_name,
1391 NULL,
1392 &sa_list,
1393 &salist_size,
1394 true);
1398 for ( i=0; i<salist_size; i++ ) {
1399 char addr[INET6_ADDRSTRLEN];
1400 print_sockaddr(addr, sizeof(addr),
1401 &sa_list[i].u.ss);
1402 add_one_dc_unique(mem_ctx,
1403 domain->name,
1404 addr,
1405 &sa_list[i].u.ss,
1406 dcs,
1407 num_dcs);
1410 TALLOC_FREE(sa_list);
1411 salist_size = 0;
1414 return True;
1417 static bool connect_preferred_dc(TALLOC_CTX *mem_ctx,
1418 struct winbindd_domain *domain,
1419 uint32_t request_flags,
1420 int *fd)
1422 char *saf_servername = NULL;
1423 NTSTATUS status;
1424 bool ok;
1427 * We have to check the server affinity cache here since later we select
1428 * a DC based on response time and not preference.
1430 if (domain->force_dc) {
1431 saf_servername = domain->dcname;
1432 } else {
1433 saf_servername = saf_fetch(mem_ctx, domain->name);
1437 * Check the negative connection cache before talking to it. It going
1438 * down may have triggered the reconnection.
1440 if (saf_servername != NULL) {
1441 status = check_negative_conn_cache(domain->name,
1442 saf_servername);
1443 if (!NT_STATUS_IS_OK(status)) {
1444 saf_servername = NULL;
1448 if (saf_servername != NULL) {
1449 DBG_DEBUG("saf_servername is '%s' for domain %s\n",
1450 saf_servername, domain->name);
1452 /* convert an ip address to a name */
1453 if (is_ipaddress(saf_servername)) {
1454 ok = interpret_string_addr(&domain->dcaddr,
1455 saf_servername,
1456 AI_NUMERICHOST);
1457 if (!ok) {
1458 return false;
1460 } else {
1461 ok = resolve_name(saf_servername,
1462 &domain->dcaddr,
1463 0x20,
1464 true);
1465 if (!ok) {
1466 goto fail;
1470 TALLOC_FREE(domain->dcname);
1471 ok = dcip_check_name(domain,
1472 domain,
1473 &domain->dcaddr,
1474 &domain->dcname,
1475 request_flags);
1476 if (!ok) {
1477 goto fail;
1481 if (domain->dcname == NULL) {
1482 return false;
1485 status = check_negative_conn_cache(domain->name, domain->dcname);
1486 if (!NT_STATUS_IS_OK(status)) {
1487 return false;
1490 status = smbsock_connect(&domain->dcaddr, 0,
1491 NULL, -1, NULL, -1,
1492 fd, NULL, 10);
1493 if (!NT_STATUS_IS_OK(status)) {
1494 winbind_add_failed_connection_entry(domain,
1495 domain->dcname,
1496 NT_STATUS_UNSUCCESSFUL);
1497 return false;
1499 return true;
1501 fail:
1502 winbind_add_failed_connection_entry(domain,
1503 saf_servername,
1504 NT_STATUS_UNSUCCESSFUL);
1505 return false;
1509 /*******************************************************************
1510 Find and make a connection to a DC in the given domain.
1512 @param[in] mem_ctx talloc memory context to allocate from
1513 @param[in] domain domain to find a dc in
1514 @param[out] fd fd of the open socket connected to the newly found dc
1515 @return true when a DC connection is made, false otherwise
1516 *******************************************************************/
1518 static bool find_dc(TALLOC_CTX *mem_ctx,
1519 struct winbindd_domain *domain,
1520 uint32_t request_flags,
1521 int *fd)
1523 struct dc_name_ip *dcs = NULL;
1524 int num_dcs = 0;
1526 const char **dcnames = NULL;
1527 size_t num_dcnames = 0;
1529 struct sockaddr_storage *addrs = NULL;
1530 int num_addrs = 0;
1532 int i;
1533 size_t fd_index;
1535 NTSTATUS status;
1536 bool ok;
1538 *fd = -1;
1540 D_NOTICE("First try to connect to the closest DC (using server "
1541 "affinity cache). If this fails, try to lookup the DC using "
1542 "DNS afterwards.\n");
1543 ok = connect_preferred_dc(mem_ctx, domain, request_flags, fd);
1544 if (ok) {
1545 return true;
1548 if (domain->force_dc) {
1549 return false;
1552 again:
1553 D_DEBUG("Retrieving a list of IP addresses for DCs.\n");
1554 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1555 return False;
1557 D_DEBUG("Retrieved IP addresses for %d DCs.\n", num_dcs);
1558 for (i=0; i<num_dcs; i++) {
1560 if (!add_string_to_array(mem_ctx, dcs[i].name,
1561 &dcnames, &num_dcnames)) {
1562 return False;
1564 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1565 &addrs, &num_addrs)) {
1566 return False;
1570 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1571 return False;
1573 if ((addrs == NULL) || (dcnames == NULL))
1574 return False;
1576 D_DEBUG("Trying to establish a connection to one of the %d DCs "
1577 "(timeout of 10 sec for each DC).\n",
1578 num_dcs);
1579 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1580 num_addrs, 0, 10, fd, &fd_index, NULL);
1581 if (!NT_STATUS_IS_OK(status)) {
1582 for (i=0; i<num_dcs; i++) {
1583 char ab[INET6_ADDRSTRLEN];
1584 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1585 DBG_DEBUG("smbsock_any_connect failed for "
1586 "domain %s address %s. Error was %s\n",
1587 domain->name, ab, nt_errstr(status));
1588 winbind_add_failed_connection_entry(domain,
1589 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1591 return False;
1593 D_NOTICE("Successfully connected to DC '%s'.\n", dcs[fd_index].name);
1595 domain->dcaddr = addrs[fd_index];
1597 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1598 /* Ok, we've got a name for the DC */
1599 TALLOC_FREE(domain->dcname);
1600 domain->dcname = talloc_strdup(domain, dcnames[fd_index]);
1601 if (domain->dcname == NULL) {
1602 return false;
1604 return true;
1607 /* Try to figure out the name */
1608 TALLOC_FREE(domain->dcname);
1609 ok = dcip_check_name(domain,
1610 domain,
1611 &domain->dcaddr,
1612 &domain->dcname,
1613 request_flags);
1614 if (ok) {
1615 return true;
1618 /* We can not continue without the DC's name */
1619 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1620 NT_STATUS_UNSUCCESSFUL);
1622 /* Throw away all arrays as we're doing this again. */
1623 TALLOC_FREE(dcs);
1624 num_dcs = 0;
1626 TALLOC_FREE(dcnames);
1627 num_dcnames = 0;
1629 TALLOC_FREE(addrs);
1630 num_addrs = 0;
1632 if (*fd != -1) {
1633 close(*fd);
1634 *fd = -1;
1638 * This should not be an infinite loop, since get_dcs() will not return
1639 * the DC added to the negative connection cache in the above
1640 * winbind_add_failed_connection_entry() call.
1642 goto again;
1645 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1647 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1648 domain_name);
1651 static void store_current_dc_in_gencache(const char *domain_name,
1652 const char *dc_name,
1653 struct cli_state *cli)
1655 char addr[INET6_ADDRSTRLEN];
1656 char *key = NULL;
1657 char *value = NULL;
1659 if (!cli_state_is_connected(cli)) {
1660 return;
1663 print_sockaddr(addr, sizeof(addr),
1664 smbXcli_conn_remote_sockaddr(cli->conn));
1666 key = current_dc_key(talloc_tos(), domain_name);
1667 if (key == NULL) {
1668 goto done;
1671 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1672 if (value == NULL) {
1673 goto done;
1676 gencache_set(key, value, 0x7fffffff);
1677 done:
1678 TALLOC_FREE(value);
1679 TALLOC_FREE(key);
1682 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1683 const char *domain_name,
1684 char **p_dc_name, char **p_dc_ip)
1686 char *key, *p;
1687 char *value = NULL;
1688 bool ret = false;
1689 char *dc_name = NULL;
1690 char *dc_ip = NULL;
1692 key = current_dc_key(talloc_tos(), domain_name);
1693 if (key == NULL) {
1694 goto done;
1696 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1697 goto done;
1699 p = strchr(value, ' ');
1700 if (p == NULL) {
1701 goto done;
1703 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1704 if (dc_ip == NULL) {
1705 goto done;
1707 dc_name = talloc_strdup(mem_ctx, p+1);
1708 if (dc_name == NULL) {
1709 goto done;
1712 if (p_dc_ip != NULL) {
1713 *p_dc_ip = dc_ip;
1714 dc_ip = NULL;
1716 if (p_dc_name != NULL) {
1717 *p_dc_name = dc_name;
1718 dc_name = NULL;
1720 ret = true;
1721 done:
1722 TALLOC_FREE(dc_name);
1723 TALLOC_FREE(dc_ip);
1724 TALLOC_FREE(key);
1725 TALLOC_FREE(value);
1726 return ret;
1729 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1730 const struct ndr_interface_table *table,
1731 struct rpc_pipe_client **ret_pipe)
1733 struct rpc_pipe_client *cli = NULL;
1734 const struct auth_session_info *session_info = NULL;
1735 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1738 session_info = get_session_info_system();
1739 SMB_ASSERT(session_info != NULL);
1741 status = rpc_pipe_open_local_np(
1742 mem_ctx, table, NULL, NULL, NULL, NULL, session_info, &cli);
1743 if (!NT_STATUS_IS_OK(status)) {
1744 return status;
1747 if (ret_pipe) {
1748 *ret_pipe = cli;
1751 return NT_STATUS_OK;
1754 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1755 struct winbindd_cm_conn *new_conn,
1756 bool need_rw_dc)
1758 TALLOC_CTX *mem_ctx;
1759 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1760 int retries;
1761 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1762 int fd = -1;
1763 bool retry = false;
1764 bool seal_pipes = true;
1766 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1767 set_domain_offline(domain);
1768 return NT_STATUS_NO_MEMORY;
1771 D_NOTICE("Creating connection to domain controller. This is a start of "
1772 "a new connection or a DC failover. The failover only happens "
1773 "if the domain has more than one DC. We will try to connect 3 "
1774 "times at most.\n");
1775 for (retries = 0; retries < 3; retries++) {
1776 bool found_dc;
1778 D_DEBUG("Attempt %d/3: DC '%s' of domain '%s'.\n",
1779 retries,
1780 domain->dcname ? domain->dcname : "",
1781 domain->name);
1783 found_dc = find_dc(mem_ctx, domain, request_flags, &fd);
1784 if (!found_dc) {
1785 /* This is the one place where we will
1786 set the global winbindd offline state
1787 to true, if a "WINBINDD_OFFLINE" entry
1788 is found in the winbindd cache. */
1789 set_global_winbindd_state_offline();
1790 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1791 break;
1794 new_conn->cli = NULL;
1796 result = cm_prepare_connection(domain, fd, domain->dcname,
1797 &new_conn->cli, &retry);
1798 if (NT_STATUS_IS_OK(result)) {
1799 break;
1801 if (!retry) {
1802 break;
1806 if (!NT_STATUS_IS_OK(result)) {
1807 /* Ensure we setup the retry handler. */
1808 set_domain_offline(domain);
1809 goto out;
1812 winbindd_set_locator_kdc_envs(domain);
1814 if (domain->online == False) {
1815 /* We're changing state from offline to online. */
1816 set_global_winbindd_state_online();
1818 set_domain_online(domain);
1821 * Much as I hate global state, this seems to be the point
1822 * where we can be certain that we have a proper connection to
1823 * a DC. wbinfo --dc-info needs that information, store it in
1824 * gencache with a looong timeout. This will need revisiting
1825 * once we start to connect to multiple DCs, wbcDcInfo is
1826 * already prepared for that.
1828 store_current_dc_in_gencache(domain->name, domain->dcname,
1829 new_conn->cli);
1831 seal_pipes = lp_winbind_sealed_pipes();
1832 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1833 domain->name,
1834 seal_pipes);
1836 if (seal_pipes) {
1837 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1838 } else {
1839 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1842 out:
1843 talloc_destroy(mem_ctx);
1844 return result;
1847 /* Close down all open pipes on a connection. */
1849 void invalidate_cm_connection(struct winbindd_domain *domain)
1851 NTSTATUS result;
1852 struct winbindd_cm_conn *conn = &domain->conn;
1854 domain->sequence_number = DOM_SEQUENCE_NONE;
1855 domain->last_seq_check = 0;
1856 domain->last_status = NT_STATUS_SERVER_DISABLED;
1858 /* We're closing down a possibly dead
1859 connection. Don't have impossibly long (10s) timeouts. */
1861 if (conn->cli) {
1862 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1865 if (conn->samr_pipe != NULL) {
1866 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1867 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1868 talloc_tos(),
1869 &conn->sam_connect_handle,
1870 &result);
1872 TALLOC_FREE(conn->samr_pipe);
1873 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1874 if (conn->cli) {
1875 cli_set_timeout(conn->cli, 500);
1879 if (conn->lsa_pipe != NULL) {
1880 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1881 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1882 talloc_tos(),
1883 &conn->lsa_policy,
1884 &result);
1886 TALLOC_FREE(conn->lsa_pipe);
1887 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1888 if (conn->cli) {
1889 cli_set_timeout(conn->cli, 500);
1893 if (conn->lsa_pipe_tcp != NULL) {
1894 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1895 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1896 talloc_tos(),
1897 &conn->lsa_policy,
1898 &result);
1900 TALLOC_FREE(conn->lsa_pipe_tcp);
1901 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1902 if (conn->cli) {
1903 cli_set_timeout(conn->cli, 500);
1907 if (conn->netlogon_pipe != NULL) {
1908 TALLOC_FREE(conn->netlogon_pipe);
1909 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1910 if (conn->cli) {
1911 cli_set_timeout(conn->cli, 500);
1915 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1916 TALLOC_FREE(conn->netlogon_creds_ctx);
1918 if (conn->cli) {
1919 cli_shutdown(conn->cli);
1922 conn->cli = NULL;
1925 void close_conns_after_fork(void)
1927 struct winbindd_domain *domain;
1928 struct winbindd_cli_state *cli_state;
1930 for (domain = domain_list(); domain; domain = domain->next) {
1932 * first close the low level SMB TCP connection
1933 * so that we don't generate any SMBclose
1934 * requests in invalidate_cm_connection()
1936 if (cli_state_is_connected(domain->conn.cli)) {
1937 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1940 invalidate_cm_connection(domain);
1943 for (cli_state = winbindd_client_list();
1944 cli_state != NULL;
1945 cli_state = cli_state->next) {
1946 if (cli_state->sock >= 0) {
1947 close(cli_state->sock);
1948 cli_state->sock = -1;
1953 static bool connection_ok(struct winbindd_domain *domain)
1955 bool ok;
1957 ok = cli_state_is_connected(domain->conn.cli);
1958 if (!ok) {
1959 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1960 domain->dcname, domain->name));
1961 return False;
1964 if (!domain->online) {
1965 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1966 return False;
1969 return True;
1972 /* Initialize a new connection up to the RPC BIND.
1973 Bypass online status check so always does network calls. */
1975 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
1977 NTSTATUS result;
1978 bool skip_connection = domain->internal;
1979 if (need_rw_dc && domain->rodc) {
1980 skip_connection = false;
1983 /* Internal connections never use the network. */
1984 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
1985 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1988 /* Still ask the internal LSA and SAMR server about the local domain */
1989 if (skip_connection || connection_ok(domain)) {
1990 if (!domain->initialized) {
1991 set_dc_type_and_flags(domain);
1993 return NT_STATUS_OK;
1996 invalidate_cm_connection(domain);
1998 if (!domain->primary && !domain->initialized) {
2000 * Before we connect to a trust, work out if it is an
2001 * AD domain by asking our own domain.
2003 set_dc_type_and_flags_trustinfo(domain);
2006 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2008 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2009 set_dc_type_and_flags(domain);
2012 return result;
2015 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2017 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2018 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2021 SMB_ASSERT(wb_child_domain() || idmap_child());
2023 return init_dc_connection_network(domain, need_rw_dc);
2026 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2028 NTSTATUS status;
2030 status = init_dc_connection(domain, need_rw_dc);
2031 if (!NT_STATUS_IS_OK(status)) {
2032 return status;
2035 if (!domain->internal && domain->conn.cli == NULL) {
2036 /* happens for trusted domains without inbound trust */
2037 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2040 return NT_STATUS_OK;
2043 /******************************************************************************
2044 Set the trust flags (direction and forest location) for a domain
2045 ******************************************************************************/
2047 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2049 struct winbindd_domain *our_domain;
2050 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2051 WERROR werr;
2052 struct netr_DomainTrustList trusts;
2053 int i;
2054 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2055 NETR_TRUST_FLAG_OUTBOUND |
2056 NETR_TRUST_FLAG_INBOUND);
2057 struct rpc_pipe_client *cli;
2058 TALLOC_CTX *mem_ctx = NULL;
2059 struct dcerpc_binding_handle *b;
2061 if (IS_DC) {
2063 * On a DC we loaded all trusts
2064 * from configuration and never learn
2065 * new domains.
2067 return true;
2070 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2072 /* Our primary domain doesn't need to worry about trust flags.
2073 Force it to go through the network setup */
2074 if ( domain->primary ) {
2075 return False;
2078 mem_ctx = talloc_stackframe();
2079 our_domain = find_our_domain();
2080 if (our_domain->internal) {
2081 result = init_dc_connection(our_domain, false);
2082 if (!NT_STATUS_IS_OK(result)) {
2083 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2084 "Not able to make a connection to our domain: %s\n",
2085 nt_errstr(result)));
2086 TALLOC_FREE(mem_ctx);
2087 return false;
2091 /* This won't work unless our domain is AD */
2092 if ( !our_domain->active_directory ) {
2093 TALLOC_FREE(mem_ctx);
2094 return False;
2097 if (our_domain->internal) {
2098 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2099 } else if (!connection_ok(our_domain)) {
2100 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2101 "No connection to our domain!\n"));
2102 TALLOC_FREE(mem_ctx);
2103 return False;
2104 } else {
2105 result = cm_connect_netlogon(our_domain, &cli);
2108 if (!NT_STATUS_IS_OK(result)) {
2109 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2110 "a connection to %s for PIPE_NETLOGON (%s)\n",
2111 domain->name, nt_errstr(result)));
2112 TALLOC_FREE(mem_ctx);
2113 return False;
2115 b = cli->binding_handle;
2117 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2118 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2119 cli->desthost,
2120 flags,
2121 &trusts,
2122 &werr);
2123 if (!NT_STATUS_IS_OK(result)) {
2124 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2125 "failed to query trusted domain list: %s\n",
2126 nt_errstr(result)));
2127 TALLOC_FREE(mem_ctx);
2128 return false;
2130 if (!W_ERROR_IS_OK(werr)) {
2131 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2132 "failed to query trusted domain list: %s\n",
2133 win_errstr(werr)));
2134 TALLOC_FREE(mem_ctx);
2135 return false;
2138 /* Now find the domain name and get the flags */
2140 for ( i=0; i<trusts.count; i++ ) {
2141 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2142 domain->domain_flags = trusts.array[i].trust_flags;
2143 domain->domain_type = trusts.array[i].trust_type;
2144 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2146 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2147 domain->active_directory = True;
2149 /* This flag is only set if the domain is *our*
2150 primary domain and the primary domain is in
2151 native mode */
2153 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2155 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2156 "native mode.\n", domain->name,
2157 domain->native_mode ? "" : "NOT "));
2159 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2160 "running active directory.\n", domain->name,
2161 domain->active_directory ? "" : "NOT "));
2163 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2165 domain->initialized = True;
2167 break;
2171 TALLOC_FREE(mem_ctx);
2173 return domain->initialized;
2176 /******************************************************************************
2177 We can 'sense' certain things about the DC by it's replies to certain
2178 questions.
2180 This tells us if this particular remote server is Active Directory, and if it
2181 is native mode.
2182 ******************************************************************************/
2184 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2186 NTSTATUS status, result;
2187 NTSTATUS close_status = NT_STATUS_UNSUCCESSFUL;
2188 WERROR werr;
2189 TALLOC_CTX *mem_ctx = NULL;
2190 struct rpc_pipe_client *cli = NULL;
2191 struct policy_handle pol = { .handle_type = 0 };
2192 union dssetup_DsRoleInfo info;
2193 union lsa_PolicyInformation *lsa_info = NULL;
2194 union lsa_revision_info out_revision_info = {
2195 .info1 = {
2196 .revision = 0,
2199 uint32_t out_version = 0;
2201 if (!domain->internal && !connection_ok(domain)) {
2202 return;
2205 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2206 domain->name);
2207 if (!mem_ctx) {
2208 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2209 return;
2212 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2214 if (domain->internal) {
2215 status = wb_open_internal_pipe(mem_ctx,
2216 &ndr_table_dssetup,
2217 &cli);
2218 } else {
2219 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2220 &ndr_table_dssetup,
2221 &cli);
2224 if (!NT_STATUS_IS_OK(status)) {
2225 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2226 "PI_DSSETUP on domain %s: (%s)\n",
2227 domain->name, nt_errstr(status)));
2229 /* if this is just a non-AD domain we need to continue
2230 * identifying so that we can in the end return with
2231 * domain->initialized = True - gd */
2233 goto no_dssetup;
2236 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2237 DS_ROLE_BASIC_INFORMATION,
2238 &info,
2239 &werr);
2240 TALLOC_FREE(cli);
2242 if (NT_STATUS_IS_OK(status)) {
2243 result = werror_to_ntstatus(werr);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2247 "on domain %s failed: (%s)\n",
2248 domain->name, nt_errstr(status)));
2250 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2251 * every opcode on the DSSETUP pipe, continue with
2252 * no_dssetup mode here as well to get domain->initialized
2253 * set - gd */
2255 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2256 goto no_dssetup;
2259 TALLOC_FREE(mem_ctx);
2260 return;
2263 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2264 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2265 domain->native_mode = True;
2266 } else {
2267 domain->native_mode = False;
2270 no_dssetup:
2271 if (domain->internal) {
2272 status = wb_open_internal_pipe(mem_ctx,
2273 &ndr_table_lsarpc,
2274 &cli);
2275 } else {
2276 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2277 &ndr_table_lsarpc, &cli);
2279 if (!NT_STATUS_IS_OK(status)) {
2280 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2281 "PI_LSARPC on domain %s: (%s)\n",
2282 domain->name, nt_errstr(status)));
2283 TALLOC_FREE(cli);
2284 TALLOC_FREE(mem_ctx);
2285 return;
2288 status = dcerpc_lsa_open_policy_fallback(cli->binding_handle,
2289 mem_ctx,
2290 cli->srv_name_slash,
2291 true,
2292 SEC_FLAG_MAXIMUM_ALLOWED,
2293 &out_version,
2294 &out_revision_info,
2295 &pol,
2296 &result);
2298 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2299 /* This particular query is exactly what Win2k clients use
2300 to determine that the DC is active directory */
2301 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2302 &pol,
2303 LSA_POLICY_INFO_DNS,
2304 &lsa_info,
2305 &result);
2309 * If the status and result will not be OK we will fallback to
2310 * OpenPolicy.
2312 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2313 domain->active_directory = True;
2315 if (lsa_info->dns.name.string) {
2316 if (!strequal(domain->name, lsa_info->dns.name.string))
2318 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2319 "for domain %s claimed it was a DC "
2320 "for domain %s, refusing to "
2321 "initialize\n",
2322 domain->name,
2323 lsa_info->dns.name.string));
2324 TALLOC_FREE(cli);
2325 TALLOC_FREE(mem_ctx);
2326 return;
2328 talloc_free(domain->name);
2329 domain->name = talloc_strdup(domain,
2330 lsa_info->dns.name.string);
2331 if (domain->name == NULL) {
2332 goto done;
2336 if (lsa_info->dns.dns_domain.string) {
2337 if (domain->alt_name != NULL &&
2338 !strequal(domain->alt_name,
2339 lsa_info->dns.dns_domain.string))
2341 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2342 "for domain %s (%s) claimed it was "
2343 "a DC for domain %s, refusing to "
2344 "initialize\n",
2345 domain->alt_name, domain->name,
2346 lsa_info->dns.dns_domain.string));
2347 TALLOC_FREE(cli);
2348 TALLOC_FREE(mem_ctx);
2349 return;
2351 talloc_free(domain->alt_name);
2352 domain->alt_name =
2353 talloc_strdup(domain,
2354 lsa_info->dns.dns_domain.string);
2355 if (domain->alt_name == NULL) {
2356 goto done;
2360 /* See if we can set some domain trust flags about
2361 ourself */
2363 if (lsa_info->dns.dns_forest.string) {
2364 talloc_free(domain->forest_name);
2365 domain->forest_name =
2366 talloc_strdup(domain,
2367 lsa_info->dns.dns_forest.string);
2368 if (domain->forest_name == NULL) {
2369 goto done;
2372 if (strequal(domain->forest_name, domain->alt_name)) {
2373 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2377 if (lsa_info->dns.sid) {
2378 if (!is_null_sid(&domain->sid) &&
2379 !dom_sid_equal(&domain->sid,
2380 lsa_info->dns.sid))
2382 struct dom_sid_buf buf1, buf2;
2383 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2384 "for domain %s (%s) claimed it was "
2385 "a DC for domain %s, refusing to "
2386 "initialize\n",
2387 dom_sid_str_buf(&domain->sid, &buf1),
2388 domain->name,
2389 dom_sid_str_buf(lsa_info->dns.sid,
2390 &buf2)));
2391 TALLOC_FREE(cli);
2392 TALLOC_FREE(mem_ctx);
2393 return;
2395 sid_copy(&domain->sid, lsa_info->dns.sid);
2397 } else {
2398 domain->active_directory = False;
2400 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2401 SEC_FLAG_MAXIMUM_ALLOWED,
2402 &pol);
2404 if (!NT_STATUS_IS_OK(status)) {
2405 goto done;
2408 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2409 &pol,
2410 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2411 &lsa_info,
2412 &result);
2413 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2415 if (lsa_info->account_domain.name.string) {
2416 if (!strequal(domain->name,
2417 lsa_info->account_domain.name.string))
2419 DEBUG(1,
2420 ("set_dc_type_and_flags_connect: "
2421 "DC for domain %s claimed it was"
2422 " a DC for domain %s, refusing "
2423 "to initialize\n", domain->name,
2424 lsa_info->
2425 account_domain.name.string));
2426 TALLOC_FREE(cli);
2427 TALLOC_FREE(mem_ctx);
2428 return;
2430 talloc_free(domain->name);
2431 domain->name =
2432 talloc_strdup(domain,
2433 lsa_info->account_domain.name.string);
2436 if (lsa_info->account_domain.sid) {
2437 if (!is_null_sid(&domain->sid) &&
2438 !dom_sid_equal(&domain->sid,
2439 lsa_info->account_domain.sid))
2441 struct dom_sid_buf buf1, buf2;
2442 DEBUG(1,
2443 ("set_dc_type_and_flags_connect: "
2444 "DC for domain %s (%s) claimed "
2445 "it was a DC for domain %s, "
2446 "refusing to initialize\n",
2447 dom_sid_str_buf(
2448 &domain->sid, &buf1),
2449 domain->name,
2450 dom_sid_str_buf(
2451 lsa_info->account_domain.sid,
2452 &buf2)));
2453 TALLOC_FREE(cli);
2454 TALLOC_FREE(mem_ctx);
2455 return;
2457 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2461 done:
2462 if (is_valid_policy_hnd(&pol)) {
2463 dcerpc_lsa_Close(cli->binding_handle,
2464 mem_ctx,
2465 &pol,
2466 &close_status);
2469 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2470 domain->name, domain->native_mode ? "" : "NOT "));
2472 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2473 domain->name, domain->active_directory ? "" : "NOT "));
2475 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2477 TALLOC_FREE(cli);
2479 TALLOC_FREE(mem_ctx);
2481 domain->initialized = True;
2484 /**********************************************************************
2485 Set the domain_flags (trust attributes, domain operating modes, etc...
2486 ***********************************************************************/
2488 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2490 if (IS_DC) {
2492 * On a DC we loaded all trusts
2493 * from configuration and never learn
2494 * new domains.
2496 return;
2499 /* we always have to contact our primary domain */
2501 if ( domain->primary || domain->internal) {
2502 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2503 "primary or internal domain\n"));
2504 set_dc_type_and_flags_connect( domain );
2505 return;
2508 /* Use our DC to get the information if possible */
2510 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2511 /* Otherwise, fallback to contacting the
2512 domain directly */
2513 set_dc_type_and_flags_connect( domain );
2516 return;
2521 /**********************************************************************
2522 ***********************************************************************/
2524 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2525 struct netlogon_creds_cli_context **ppdc)
2527 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2528 struct rpc_pipe_client *netlogon_pipe;
2530 *ppdc = NULL;
2532 if ((!IS_DC) && (!domain->primary)) {
2533 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2536 if (domain->conn.netlogon_creds_ctx != NULL) {
2537 *ppdc = domain->conn.netlogon_creds_ctx;
2538 return NT_STATUS_OK;
2541 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2542 if (!NT_STATUS_IS_OK(result)) {
2543 return result;
2546 return NT_STATUS_OK;
2549 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2550 bool need_rw_dc,
2551 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2553 struct winbindd_cm_conn *conn;
2554 NTSTATUS status, result;
2555 struct netlogon_creds_cli_context *p_creds;
2556 struct cli_credentials *creds = NULL;
2557 bool retry = false; /* allow one retry attempt for expired session */
2558 const char *remote_name = NULL;
2559 const struct sockaddr_storage *remote_sockaddr = NULL;
2560 bool sealed_pipes = true;
2561 bool strong_key = true;
2563 if (sid_check_is_our_sam(&domain->sid)) {
2564 if (domain->rodc == false || need_rw_dc == false) {
2565 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2569 if (IS_AD_DC) {
2571 * In theory we should not use SAMR within
2572 * winbindd at all, but that's a larger task to
2573 * remove this and avoid breaking existing
2574 * setups.
2576 * At least as AD DC we have the restriction
2577 * to avoid SAMR against trusted domains,
2578 * as there're no existing setups.
2580 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2583 retry:
2584 status = init_dc_connection_rpc(domain, need_rw_dc);
2585 if (!NT_STATUS_IS_OK(status)) {
2586 return status;
2589 conn = &domain->conn;
2591 if (rpccli_is_connected(conn->samr_pipe)) {
2592 goto done;
2595 TALLOC_FREE(conn->samr_pipe);
2598 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2599 * sign and sealed pipe using the machine account password by
2600 * preference. If we can't - try schannel, if that fails, try
2601 * anonymous.
2604 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2605 if (!NT_STATUS_IS_OK(result)) {
2606 DEBUG(10, ("cm_connect_sam: No user available for "
2607 "domain %s, trying schannel\n", domain->name));
2608 goto schannel;
2611 if (cli_credentials_is_anonymous(creds)) {
2612 goto anonymous;
2615 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2616 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2619 * We have an authenticated connection. Use a SPNEGO
2620 * authenticated SAMR pipe with sign & seal.
2622 status = cli_rpc_pipe_open_with_creds(conn->cli,
2623 &ndr_table_samr,
2624 NCACN_NP,
2625 DCERPC_AUTH_TYPE_SPNEGO,
2626 conn->auth_level,
2627 remote_name,
2628 remote_sockaddr,
2629 creds,
2630 &conn->samr_pipe);
2632 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2633 && !retry) {
2634 invalidate_cm_connection(domain);
2635 retry = true;
2636 goto retry;
2639 if (!NT_STATUS_IS_OK(status)) {
2640 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2641 "pipe for domain %s using NTLMSSP "
2642 "authenticated pipe: user %s. Error was "
2643 "%s\n", domain->name,
2644 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2645 nt_errstr(status)));
2646 goto schannel;
2649 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2650 "domain %s using NTLMSSP authenticated "
2651 "pipe: user %s\n", domain->name,
2652 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2654 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2655 conn->samr_pipe->desthost,
2656 SEC_FLAG_MAXIMUM_ALLOWED,
2657 &conn->sam_connect_handle,
2658 &result);
2660 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2661 invalidate_cm_connection(domain);
2662 TALLOC_FREE(conn->samr_pipe);
2663 retry = true;
2664 goto retry;
2667 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2668 goto open_domain;
2670 if (NT_STATUS_IS_OK(status)) {
2671 status = result;
2674 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2675 "failed for domain %s, error was %s. Trying schannel\n",
2676 domain->name, nt_errstr(status) ));
2677 TALLOC_FREE(conn->samr_pipe);
2679 schannel:
2681 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2683 status = cm_get_schannel_creds(domain, &p_creds);
2684 if (!NT_STATUS_IS_OK(status)) {
2685 /* If this call fails - conn->cli can now be NULL ! */
2686 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2687 "for domain %s (error %s), trying anon\n",
2688 domain->name,
2689 nt_errstr(status) ));
2690 goto anonymous;
2692 TALLOC_FREE(creds);
2693 status = cli_rpc_pipe_open_schannel_with_creds(
2694 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2695 remote_name,
2696 remote_sockaddr,
2697 &conn->samr_pipe);
2699 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2700 && !retry) {
2701 invalidate_cm_connection(domain);
2702 retry = true;
2703 goto retry;
2706 if (!NT_STATUS_IS_OK(status)) {
2707 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2708 "domain %s using schannel. Error was %s\n",
2709 domain->name, nt_errstr(status) ));
2710 goto anonymous;
2712 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2713 "schannel.\n", domain->name ));
2715 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2716 conn->samr_pipe->desthost,
2717 SEC_FLAG_MAXIMUM_ALLOWED,
2718 &conn->sam_connect_handle,
2719 &result);
2721 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2722 invalidate_cm_connection(domain);
2723 TALLOC_FREE(conn->samr_pipe);
2724 retry = true;
2725 goto retry;
2728 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2729 goto open_domain;
2731 if (NT_STATUS_IS_OK(status)) {
2732 status = result;
2734 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2735 "for domain %s, error was %s. Trying anonymous\n",
2736 domain->name, nt_errstr(status) ));
2737 TALLOC_FREE(conn->samr_pipe);
2739 anonymous:
2741 sealed_pipes = lp_winbind_sealed_pipes();
2742 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2743 domain->name,
2744 sealed_pipes);
2745 strong_key = lp_require_strong_key();
2746 strong_key = lp_parm_bool(-1, "require strong key",
2747 domain->name,
2748 strong_key);
2750 /* Finally fall back to anonymous. */
2751 if (sealed_pipes || strong_key) {
2752 status = NT_STATUS_DOWNGRADE_DETECTED;
2753 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2754 "without connection level security, "
2755 "must set 'winbind sealed pipes:%s = false' and "
2756 "'require strong key:%s = false' to proceed: %s\n",
2757 domain->name, domain->name, domain->name,
2758 nt_errstr(status)));
2759 goto done;
2761 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2762 &conn->samr_pipe);
2764 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2765 && !retry) {
2766 invalidate_cm_connection(domain);
2767 retry = true;
2768 goto retry;
2771 if (!NT_STATUS_IS_OK(status)) {
2772 goto done;
2775 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2776 conn->samr_pipe->desthost,
2777 SEC_FLAG_MAXIMUM_ALLOWED,
2778 &conn->sam_connect_handle,
2779 &result);
2781 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2782 invalidate_cm_connection(domain);
2783 TALLOC_FREE(conn->samr_pipe);
2784 retry = true;
2785 goto retry;
2788 if (!NT_STATUS_IS_OK(status)) {
2789 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2790 "for domain %s Error was %s\n",
2791 domain->name, nt_errstr(status) ));
2792 goto done;
2794 if (!NT_STATUS_IS_OK(result)) {
2795 status = result;
2796 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2797 "for domain %s Error was %s\n",
2798 domain->name, nt_errstr(result)));
2799 goto done;
2802 open_domain:
2803 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2804 mem_ctx,
2805 &conn->sam_connect_handle,
2806 SEC_FLAG_MAXIMUM_ALLOWED,
2807 &domain->sid,
2808 &conn->sam_domain_handle,
2809 &result);
2810 if (!NT_STATUS_IS_OK(status)) {
2811 goto done;
2814 status = result;
2815 done:
2817 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2819 * if we got access denied, we might just have no access rights
2820 * to talk to the remote samr server server (e.g. when we are a
2821 * PDC and we are connecting a w2k8 pdc via an interdomain
2822 * trust). In that case do not invalidate the whole connection
2823 * stack
2825 TALLOC_FREE(conn->samr_pipe);
2826 ZERO_STRUCT(conn->sam_domain_handle);
2827 return status;
2828 } else if (!NT_STATUS_IS_OK(status)) {
2829 invalidate_cm_connection(domain);
2830 return status;
2833 *cli = conn->samr_pipe;
2834 *sam_handle = conn->sam_domain_handle;
2835 return status;
2838 /**********************************************************************
2839 open an schanneld ncacn_ip_tcp connection to LSA
2840 ***********************************************************************/
2842 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2843 TALLOC_CTX *mem_ctx,
2844 struct rpc_pipe_client **cli)
2846 struct winbindd_cm_conn *conn;
2847 struct netlogon_creds_cli_context *p_creds = NULL;
2848 NTSTATUS status;
2849 const char *remote_name = NULL;
2850 const struct sockaddr_storage *remote_sockaddr = NULL;
2852 DEBUG(10,("cm_connect_lsa_tcp\n"));
2854 status = init_dc_connection_rpc(domain, false);
2855 if (!NT_STATUS_IS_OK(status)) {
2856 return status;
2859 conn = &domain->conn;
2862 * rpccli_is_connected handles more error cases
2864 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2865 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2866 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2867 goto done;
2870 TALLOC_FREE(conn->lsa_pipe_tcp);
2872 status = cm_get_schannel_creds(domain, &p_creds);
2873 if (!NT_STATUS_IS_OK(status)) {
2874 goto done;
2877 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2878 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2880 status = cli_rpc_pipe_open_schannel_with_creds(
2881 conn->cli,
2882 &ndr_table_lsarpc,
2883 NCACN_IP_TCP,
2884 p_creds,
2885 remote_name,
2886 remote_sockaddr,
2887 &conn->lsa_pipe_tcp);
2888 if (!NT_STATUS_IS_OK(status)) {
2889 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2890 nt_errstr(status)));
2891 goto done;
2894 done:
2895 if (!NT_STATUS_IS_OK(status)) {
2896 TALLOC_FREE(conn->lsa_pipe_tcp);
2897 return status;
2900 *cli = conn->lsa_pipe_tcp;
2902 return status;
2905 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2906 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2908 struct winbindd_cm_conn *conn;
2909 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2910 struct netlogon_creds_cli_context *p_creds;
2911 struct cli_credentials *creds = NULL;
2912 bool retry = false; /* allow one retry attempt for expired session */
2913 const char *remote_name = NULL;
2914 const struct sockaddr_storage *remote_sockaddr = NULL;
2915 bool sealed_pipes = true;
2916 bool strong_key = true;
2918 retry:
2919 result = init_dc_connection_rpc(domain, false);
2920 if (!NT_STATUS_IS_OK(result))
2921 return result;
2923 conn = &domain->conn;
2925 if (rpccli_is_connected(conn->lsa_pipe)) {
2926 goto done;
2929 TALLOC_FREE(conn->lsa_pipe);
2931 if (IS_DC) {
2933 * Make sure we only use schannel as AD DC.
2935 goto schannel;
2938 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2939 if (!NT_STATUS_IS_OK(result)) {
2940 DEBUG(10, ("cm_connect_lsa: No user available for "
2941 "domain %s, trying schannel\n", domain->name));
2942 goto schannel;
2945 if (cli_credentials_is_anonymous(creds)) {
2946 goto anonymous;
2949 remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2950 remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2953 * We have an authenticated connection. Use a SPNEGO
2954 * authenticated LSA pipe with sign & seal.
2956 result = cli_rpc_pipe_open_with_creds
2957 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2958 DCERPC_AUTH_TYPE_SPNEGO,
2959 conn->auth_level,
2960 remote_name,
2961 remote_sockaddr,
2962 creds,
2963 &conn->lsa_pipe);
2965 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
2966 && !retry) {
2967 invalidate_cm_connection(domain);
2968 retry = true;
2969 goto retry;
2972 if (!NT_STATUS_IS_OK(result)) {
2973 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2974 "domain %s using NTLMSSP authenticated pipe: user "
2975 "%s. Error was %s. Trying schannel.\n",
2976 domain->name,
2977 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2978 nt_errstr(result)));
2979 goto schannel;
2982 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2983 "NTLMSSP authenticated pipe: user %s\n",
2984 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
2986 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2987 SEC_FLAG_MAXIMUM_ALLOWED,
2988 &conn->lsa_policy);
2989 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2990 invalidate_cm_connection(domain);
2991 TALLOC_FREE(conn->lsa_pipe);
2992 retry = true;
2993 goto retry;
2996 if (NT_STATUS_IS_OK(result)) {
2997 goto done;
3000 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3001 "schannel\n"));
3003 TALLOC_FREE(conn->lsa_pipe);
3005 schannel:
3007 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3009 result = cm_get_schannel_creds(domain, &p_creds);
3010 if (!NT_STATUS_IS_OK(result)) {
3011 /* If this call fails - conn->cli can now be NULL ! */
3012 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3013 "for domain %s (error %s), trying anon\n",
3014 domain->name,
3015 nt_errstr(result) ));
3016 goto anonymous;
3019 TALLOC_FREE(creds);
3020 result = cli_rpc_pipe_open_schannel_with_creds(
3021 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3022 remote_name,
3023 remote_sockaddr,
3024 &conn->lsa_pipe);
3026 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3027 && !retry) {
3028 invalidate_cm_connection(domain);
3029 retry = true;
3030 goto retry;
3033 if (!NT_STATUS_IS_OK(result)) {
3034 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3035 "domain %s using schannel. Error was %s\n",
3036 domain->name, nt_errstr(result) ));
3037 goto anonymous;
3039 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3040 "schannel.\n", domain->name ));
3042 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3043 SEC_FLAG_MAXIMUM_ALLOWED,
3044 &conn->lsa_policy);
3046 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3047 invalidate_cm_connection(domain);
3048 TALLOC_FREE(conn->lsa_pipe);
3049 retry = true;
3050 goto retry;
3053 if (NT_STATUS_IS_OK(result)) {
3054 goto done;
3057 if (IS_DC) {
3059 * Make sure we only use schannel as AD DC.
3061 goto done;
3064 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3065 "anonymous\n"));
3067 TALLOC_FREE(conn->lsa_pipe);
3069 anonymous:
3071 if (IS_DC) {
3073 * Make sure we only use schannel as AD DC.
3075 goto done;
3078 sealed_pipes = lp_winbind_sealed_pipes();
3079 sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
3080 domain->name,
3081 sealed_pipes);
3082 strong_key = lp_require_strong_key();
3083 strong_key = lp_parm_bool(-1, "require strong key",
3084 domain->name,
3085 strong_key);
3087 /* Finally fall back to anonymous. */
3088 if (sealed_pipes || strong_key) {
3089 result = NT_STATUS_DOWNGRADE_DETECTED;
3090 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3091 "without connection level security, "
3092 "must set 'winbind sealed pipes:%s = false' and "
3093 "'require strong key:%s = false' to proceed: %s\n",
3094 domain->name, domain->name, domain->name,
3095 nt_errstr(result)));
3096 goto done;
3099 result = cli_rpc_pipe_open_noauth(conn->cli,
3100 &ndr_table_lsarpc,
3101 &conn->lsa_pipe);
3103 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3104 && !retry) {
3105 invalidate_cm_connection(domain);
3106 retry = true;
3107 goto retry;
3110 if (!NT_STATUS_IS_OK(result)) {
3111 goto done;
3114 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3115 SEC_FLAG_MAXIMUM_ALLOWED,
3116 &conn->lsa_policy);
3118 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3119 invalidate_cm_connection(domain);
3120 TALLOC_FREE(conn->lsa_pipe);
3121 retry = true;
3122 goto retry;
3125 done:
3126 if (!NT_STATUS_IS_OK(result)) {
3127 invalidate_cm_connection(domain);
3128 return result;
3131 *cli = conn->lsa_pipe;
3132 *lsa_policy = conn->lsa_policy;
3133 return result;
3136 /****************************************************************************
3137 Open a LSA connection to a DC, suitable for LSA lookup calls.
3138 ****************************************************************************/
3140 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3141 TALLOC_CTX *mem_ctx,
3142 struct rpc_pipe_client **cli,
3143 struct policy_handle *lsa_policy)
3145 NTSTATUS status;
3147 if (domain->can_do_ncacn_ip_tcp) {
3148 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3149 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3150 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3151 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3152 invalidate_cm_connection(domain);
3153 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3155 if (NT_STATUS_IS_OK(status)) {
3156 return status;
3160 * we tried twice to connect via ncan_ip_tcp and schannel and
3161 * failed - maybe it is a trusted domain we can't connect to ?
3162 * do not try tcp next time - gd
3164 * This also prevents NETLOGON over TCP
3166 domain->can_do_ncacn_ip_tcp = false;
3169 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3171 return status;
3174 /****************************************************************************
3175 Open the netlogon pipe to this DC.
3176 ****************************************************************************/
3178 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3179 enum dcerpc_transport_t transport,
3180 struct rpc_pipe_client **cli)
3182 struct messaging_context *msg_ctx = global_messaging_context();
3183 struct winbindd_cm_conn *conn;
3184 NTSTATUS result;
3185 enum netr_SchannelType sec_chan_type;
3186 struct cli_credentials *creds = NULL;
3188 *cli = NULL;
3190 if (IS_DC) {
3191 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3193 * Make sure we don't even try to
3194 * connect to a foreign domain
3195 * without a direct outbound trust.
3197 return NT_STATUS_NO_TRUST_LSA_SECRET;
3201 result = init_dc_connection_rpc(domain, domain->rodc);
3202 if (!NT_STATUS_IS_OK(result)) {
3203 return result;
3206 conn = &domain->conn;
3208 if (rpccli_is_connected(conn->netlogon_pipe)) {
3209 *cli = conn->netlogon_pipe;
3210 return NT_STATUS_OK;
3213 TALLOC_FREE(conn->netlogon_pipe);
3214 TALLOC_FREE(conn->netlogon_creds_ctx);
3216 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3217 if (!NT_STATUS_IS_OK(result)) {
3218 DBG_DEBUG("No user available for domain %s when trying "
3219 "schannel\n", domain->name);
3220 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3223 if (cli_credentials_is_anonymous(creds)) {
3224 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3225 "unable to make get NETLOGON credentials\n",
3226 domain->name);
3227 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3230 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3231 if (sec_chan_type == SEC_CHAN_NULL) {
3232 const char *remote_name =
3233 smbXcli_conn_remote_name(conn->cli->conn);
3234 const struct sockaddr_storage *remote_sockaddr =
3235 smbXcli_conn_remote_sockaddr(conn->cli->conn);
3237 if (transport == NCACN_IP_TCP) {
3238 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3239 "for %s, deny NCACN_IP_TCP and let the "
3240 "caller fallback to NCACN_NP.\n",
3241 domain->name);
3242 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3245 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3246 "fallback to noauth on NCACN_NP.\n",
3247 domain->name);
3249 result = cli_rpc_pipe_open_noauth_transport(
3250 conn->cli,
3251 transport,
3252 &ndr_table_netlogon,
3253 remote_name,
3254 remote_sockaddr,
3255 &conn->netlogon_pipe);
3256 if (!NT_STATUS_IS_OK(result)) {
3257 invalidate_cm_connection(domain);
3258 return result;
3261 *cli = conn->netlogon_pipe;
3262 return NT_STATUS_OK;
3265 result = rpccli_create_netlogon_creds_ctx(creds,
3266 domain->dcname,
3267 msg_ctx,
3268 domain,
3269 &conn->netlogon_creds_ctx);
3270 if (!NT_STATUS_IS_OK(result)) {
3271 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3272 "unable to create NETLOGON credentials: %s\n",
3273 domain->name, nt_errstr(result)));
3274 return result;
3277 result = rpccli_connect_netlogon(
3278 conn->cli, transport,
3279 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3280 &conn->netlogon_pipe);
3281 conn->netlogon_force_reauth = false;
3282 if (!NT_STATUS_IS_OK(result)) {
3283 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3284 nt_errstr(result));
3285 return result;
3288 *cli = conn->netlogon_pipe;
3289 return NT_STATUS_OK;
3292 /****************************************************************************
3293 Open a NETLOGON connection to a DC, suitable for SamLogon calls.
3294 ****************************************************************************/
3296 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3297 struct rpc_pipe_client **cli)
3299 NTSTATUS status;
3301 status = init_dc_connection_rpc(domain, domain->rodc);
3302 if (!NT_STATUS_IS_OK(status)) {
3303 return status;
3306 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3307 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3308 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3309 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3310 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3311 invalidate_cm_connection(domain);
3312 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3314 if (NT_STATUS_IS_OK(status)) {
3315 return status;
3319 * we tried twice to connect via ncan_ip_tcp and schannel and
3320 * failed - maybe it is a trusted domain we can't connect to ?
3321 * do not try tcp next time - gd
3323 * This also prevents LSA over TCP
3325 domain->can_do_ncacn_ip_tcp = false;
3328 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3329 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3331 * SMB2 session expired, needs reauthentication. Drop
3332 * connection and retry.
3334 invalidate_cm_connection(domain);
3335 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3338 return status;
3341 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3342 struct rpc_pipe_client **cli,
3343 struct netlogon_creds_cli_context **ppdc)
3345 NTSTATUS status;
3347 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3348 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3351 status = cm_connect_netlogon(domain, cli);
3352 if (!NT_STATUS_IS_OK(status)) {
3353 return status;
3356 if (domain->conn.netlogon_creds_ctx == NULL) {
3357 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3360 *ppdc = domain->conn.netlogon_creds_ctx;
3361 return NT_STATUS_OK;
3364 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3365 void *private_data,
3366 uint32_t msg_type,
3367 struct server_id server_id,
3368 DATA_BLOB *data)
3370 struct winbindd_domain *domain;
3371 char *freeit = NULL;
3372 char *addr;
3374 if ((data == NULL)
3375 || (data->data == NULL)
3376 || (data->length == 0)
3377 || (data->data[data->length-1] != '\0')) {
3378 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3379 "string\n"));
3380 return;
3383 addr = (char *)data->data;
3384 DEBUG(10, ("IP %s dropped\n", addr));
3386 if (!is_ipaddress(addr)) {
3387 char *slash;
3389 * Some code sends us ip addresses with the /netmask
3390 * suffix
3392 slash = strchr(addr, '/');
3393 if (slash == NULL) {
3394 DEBUG(1, ("invalid msg_ip_dropped message: %s\n",
3395 addr));
3396 return;
3398 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3399 if (freeit == NULL) {
3400 DEBUG(1, ("talloc failed\n"));
3401 return;
3403 addr = freeit;
3404 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3407 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3408 char sockaddr[INET6_ADDRSTRLEN];
3410 if (!cli_state_is_connected(domain->conn.cli)) {
3411 continue;
3414 print_sockaddr(sockaddr, sizeof(sockaddr),
3415 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3417 if (strequal(sockaddr, addr)) {
3418 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3421 TALLOC_FREE(freeit);
3424 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3425 void *private_data,
3426 uint32_t msg_type,
3427 struct server_id server_id,
3428 DATA_BLOB *data)
3430 struct winbindd_domain *domain;
3432 for (domain = domain_list(); domain; domain = domain->next) {
3433 if (domain->internal) {
3434 continue;
3436 invalidate_cm_connection(domain);