winbind: set_dc_type_and_flags() is not needed on a DC
[Samba.git] / source3 / winbindd / winbindd_cm.c
blobacccf104d3c5b4825cf297a4124aae822f1295c9
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 "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "libsmb/libsmb.h"
73 #include "libsmb/clidgram.h"
74 #include "ads.h"
75 #include "secrets.h"
76 #include "../libcli/security/security.h"
77 #include "passdb.h"
78 #include "messages.h"
79 #include "auth/gensec/gensec.h"
80 #include "../libcli/smb/smbXcli_base.h"
81 #include "libcli/auth/netlogon_creds_cli.h"
82 #include "auth.h"
83 #include "rpc_server/rpc_ncacn_np.h"
84 #include "auth/credentials/credentials.h"
85 #include "lib/param/param.h"
87 #undef DBGC_CLASS
88 #define DBGC_CLASS DBGC_WINBIND
90 struct dc_name_ip {
91 fstring name;
92 struct sockaddr_storage ss;
95 extern struct winbindd_methods reconnect_methods;
96 extern bool override_logfile;
98 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
99 static void set_dc_type_and_flags( struct winbindd_domain *domain );
100 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
101 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
102 struct dc_name_ip **dcs, int *num_dcs,
103 uint32_t request_flags);
105 /****************************************************************
106 Child failed to find DC's. Reschedule check.
107 ****************************************************************/
109 static void msg_failed_to_go_online(struct messaging_context *msg,
110 void *private_data,
111 uint32_t msg_type,
112 struct server_id server_id,
113 DATA_BLOB *data)
115 struct winbindd_domain *domain;
116 const char *domainname = (const char *)data->data;
118 if (data->data == NULL || data->length == 0) {
119 return;
122 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
124 for (domain = domain_list(); domain; domain = domain->next) {
125 if (domain->internal) {
126 continue;
129 if (strequal(domain->name, domainname)) {
130 if (domain->online) {
131 /* We're already online, ignore. */
132 DEBUG(5,("msg_fail_to_go_online: domain %s "
133 "already online.\n", domainname));
134 continue;
137 /* Reschedule the online check. */
138 set_domain_offline(domain);
139 break;
144 /****************************************************************
145 Actually cause a reconnect from a message.
146 ****************************************************************/
148 static void msg_try_to_go_online(struct messaging_context *msg,
149 void *private_data,
150 uint32_t msg_type,
151 struct server_id server_id,
152 DATA_BLOB *data)
154 struct winbindd_domain *domain;
155 const char *domainname = (const char *)data->data;
157 if (data->data == NULL || data->length == 0) {
158 return;
161 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
163 for (domain = domain_list(); domain; domain = domain->next) {
164 if (domain->internal) {
165 continue;
168 if (strequal(domain->name, domainname)) {
170 if (domain->online) {
171 /* We're already online, ignore. */
172 DEBUG(5,("msg_try_to_go_online: domain %s "
173 "already online.\n", domainname));
174 continue;
177 /* This call takes care of setting the online
178 flag to true if we connected, or re-adding
179 the offline handler if false. Bypasses online
180 check so always does network calls. */
182 init_dc_connection_network(domain, true);
183 break;
188 /****************************************************************
189 Fork a child to try and contact a DC. Do this as contacting a
190 DC requires blocking lookups and we don't want to block our
191 parent.
192 ****************************************************************/
194 static bool fork_child_dc_connect(struct winbindd_domain *domain)
196 struct dc_name_ip *dcs = NULL;
197 int num_dcs = 0;
198 TALLOC_CTX *mem_ctx = NULL;
199 pid_t parent_pid = getpid();
200 char *lfile = NULL;
201 NTSTATUS status;
203 if (domain->dc_probe_pid != (pid_t)-1) {
205 * We might already have a DC probe
206 * child working, check.
208 if (process_exists_by_pid(domain->dc_probe_pid)) {
209 DEBUG(10,("fork_child_dc_connect: pid %u already "
210 "checking for DC's.\n",
211 (unsigned int)domain->dc_probe_pid));
212 return true;
214 domain->dc_probe_pid = (pid_t)-1;
217 domain->dc_probe_pid = fork();
219 if (domain->dc_probe_pid == (pid_t)-1) {
220 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
221 return False;
224 if (domain->dc_probe_pid != (pid_t)0) {
225 /* Parent */
226 messaging_register(server_messaging_context(), NULL,
227 MSG_WINBIND_TRY_TO_GO_ONLINE,
228 msg_try_to_go_online);
229 messaging_register(server_messaging_context(), NULL,
230 MSG_WINBIND_FAILED_TO_GO_ONLINE,
231 msg_failed_to_go_online);
232 return True;
235 /* Child. */
237 /* Leave messages blocked - we will never process one. */
239 if (!override_logfile) {
240 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
241 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
242 _exit(1);
246 status = winbindd_reinit_after_fork(NULL, lfile);
247 if (!NT_STATUS_IS_OK(status)) {
248 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
249 nt_errstr(status)));
250 messaging_send_buf(server_messaging_context(),
251 pid_to_procid(parent_pid),
252 MSG_WINBIND_FAILED_TO_GO_ONLINE,
253 (const uint8_t *)domain->name,
254 strlen(domain->name)+1);
255 _exit(1);
257 SAFE_FREE(lfile);
259 setproctitle("dc-connect child");
261 mem_ctx = talloc_init("fork_child_dc_connect");
262 if (!mem_ctx) {
263 DEBUG(0,("talloc_init failed.\n"));
264 messaging_send_buf(server_messaging_context(),
265 pid_to_procid(parent_pid),
266 MSG_WINBIND_FAILED_TO_GO_ONLINE,
267 (const uint8_t *)domain->name,
268 strlen(domain->name)+1);
269 _exit(1);
272 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs, 0)) || (num_dcs == 0)) {
273 /* Still offline ? Can't find DC's. */
274 messaging_send_buf(server_messaging_context(),
275 pid_to_procid(parent_pid),
276 MSG_WINBIND_FAILED_TO_GO_ONLINE,
277 (const uint8_t *)domain->name,
278 strlen(domain->name)+1);
279 _exit(0);
282 /* We got a DC. Send a message to our parent to get it to
283 try and do the same. */
285 messaging_send_buf(server_messaging_context(),
286 pid_to_procid(parent_pid),
287 MSG_WINBIND_TRY_TO_GO_ONLINE,
288 (const uint8_t *)domain->name,
289 strlen(domain->name)+1);
290 _exit(0);
293 /****************************************************************
294 Handler triggered if we're offline to try and detect a DC.
295 ****************************************************************/
297 static void check_domain_online_handler(struct tevent_context *ctx,
298 struct tevent_timer *te,
299 struct timeval now,
300 void *private_data)
302 struct winbindd_domain *domain =
303 (struct winbindd_domain *)private_data;
305 DEBUG(10,("check_domain_online_handler: called for domain "
306 "%s (online = %s)\n", domain->name,
307 domain->online ? "True" : "False" ));
309 TALLOC_FREE(domain->check_online_event);
311 /* Are we still in "startup" mode ? */
313 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
314 /* No longer in "startup" mode. */
315 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
316 domain->name ));
317 domain->startup = False;
320 /* We've been told to stay offline, so stay
321 that way. */
323 if (get_global_winbindd_state_offline()) {
324 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
325 domain->name ));
326 return;
329 /* Fork a child to test if it can contact a DC.
330 If it can then send ourselves a message to
331 cause a reconnect. */
333 fork_child_dc_connect(domain);
336 /****************************************************************
337 If we're still offline setup the timeout check.
338 ****************************************************************/
340 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
342 int wbr = lp_winbind_reconnect_delay();
344 if (domain->startup) {
345 domain->check_online_timeout = 10;
346 } else if (domain->check_online_timeout < wbr) {
347 domain->check_online_timeout = wbr;
351 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
352 void *private_data,
353 uint32_t msg_type,
354 struct server_id server_id,
355 DATA_BLOB *data)
357 const char *domain_name = (const char *)data->data;
358 struct winbindd_domain *domain;
360 domain = find_domain_from_name_noinit(domain_name);
361 if (domain == NULL) {
362 return;
365 domain->online = false;
367 DEBUG(10, ("Domain %s is marked as offline now.\n",
368 domain_name));
371 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
372 void *private_data,
373 uint32_t msg_type,
374 struct server_id server_id,
375 DATA_BLOB *data)
377 const char *domain_name = (const char *)data->data;
378 struct winbindd_domain *domain;
380 domain = find_domain_from_name_noinit(domain_name);
381 if (domain == NULL) {
382 return;
385 domain->online = true;
387 DEBUG(10, ("Domain %s is marked as online now.\n",
388 domain_name));
391 /****************************************************************
392 Set domain offline and also add handler to put us back online
393 if we detect a DC.
394 ****************************************************************/
396 void set_domain_offline(struct winbindd_domain *domain)
398 pid_t parent_pid = getppid();
400 DEBUG(10,("set_domain_offline: called for domain %s\n",
401 domain->name ));
403 TALLOC_FREE(domain->check_online_event);
405 if (domain->internal) {
406 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
407 domain->name ));
408 return;
411 domain->online = False;
413 /* Offline domains are always initialized. They're
414 re-initialized when they go back online. */
416 domain->initialized = True;
418 /* We only add the timeout handler that checks and
419 allows us to go back online when we've not
420 been told to remain offline. */
422 if (get_global_winbindd_state_offline()) {
423 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
424 domain->name ));
425 return;
428 /* If we're in startup mode, check again in 10 seconds, not in
429 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
431 calc_new_online_timeout_check(domain);
433 domain->check_online_event = tevent_add_timer(server_event_context(),
434 NULL,
435 timeval_current_ofs(domain->check_online_timeout,0),
436 check_domain_online_handler,
437 domain);
439 /* The above *has* to succeed for winbindd to work. */
440 if (!domain->check_online_event) {
441 smb_panic("set_domain_offline: failed to add online handler");
444 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
445 domain->name ));
447 /* Send a message to the parent that the domain is offline. */
448 if (parent_pid > 1 && !domain->internal) {
449 messaging_send_buf(server_messaging_context(),
450 pid_to_procid(parent_pid),
451 MSG_WINBIND_DOMAIN_OFFLINE,
452 (uint8_t *)domain->name,
453 strlen(domain->name) + 1);
456 /* Send an offline message to the idmap child when our
457 primary domain goes offline */
459 if ( domain->primary ) {
460 struct winbindd_child *idmap = idmap_child();
462 if ( idmap->pid != 0 ) {
463 messaging_send_buf(server_messaging_context(),
464 pid_to_procid(idmap->pid),
465 MSG_WINBIND_OFFLINE,
466 (const uint8_t *)domain->name,
467 strlen(domain->name)+1);
471 return;
474 /****************************************************************
475 Set domain online - if allowed.
476 ****************************************************************/
478 static void set_domain_online(struct winbindd_domain *domain)
480 pid_t parent_pid = getppid();
482 DEBUG(10,("set_domain_online: called for domain %s\n",
483 domain->name ));
485 if (domain->internal) {
486 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
487 domain->name ));
488 return;
491 if (get_global_winbindd_state_offline()) {
492 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
493 domain->name ));
494 return;
497 winbindd_set_locator_kdc_envs(domain);
499 /* If we are waiting to get a krb5 ticket, trigger immediately. */
500 ccache_regain_all_now();
502 /* Ok, we're out of any startup mode now... */
503 domain->startup = False;
505 if (domain->online == False) {
506 /* We were offline - now we're online. We default to
507 using the MS-RPC backend if we started offline,
508 and if we're going online for the first time we
509 should really re-initialize the backends and the
510 checks to see if we're talking to an AD or NT domain.
513 domain->initialized = False;
515 /* 'reconnect_methods' is the MS-RPC backend. */
516 if (domain->backend == &reconnect_methods) {
517 domain->backend = NULL;
521 /* Ensure we have no online timeout checks. */
522 domain->check_online_timeout = 0;
523 TALLOC_FREE(domain->check_online_event);
525 /* Ensure we ignore any pending child messages. */
526 messaging_deregister(server_messaging_context(),
527 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
528 messaging_deregister(server_messaging_context(),
529 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
531 domain->online = True;
533 /* Send a message to the parent that the domain is online. */
534 if (parent_pid > 1 && !domain->internal) {
535 messaging_send_buf(server_messaging_context(),
536 pid_to_procid(parent_pid),
537 MSG_WINBIND_DOMAIN_ONLINE,
538 (uint8_t *)domain->name,
539 strlen(domain->name) + 1);
542 /* Send an online message to the idmap child when our
543 primary domain comes online */
545 if ( domain->primary ) {
546 struct winbindd_child *idmap = idmap_child();
548 if ( idmap->pid != 0 ) {
549 messaging_send_buf(server_messaging_context(),
550 pid_to_procid(idmap->pid),
551 MSG_WINBIND_ONLINE,
552 (const uint8_t *)domain->name,
553 strlen(domain->name)+1);
557 return;
560 /****************************************************************
561 Requested to set a domain online.
562 ****************************************************************/
564 void set_domain_online_request(struct winbindd_domain *domain)
566 struct timeval tev;
568 DEBUG(10,("set_domain_online_request: called for domain %s\n",
569 domain->name ));
571 if (get_global_winbindd_state_offline()) {
572 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
573 domain->name ));
574 return;
577 if (domain->internal) {
578 DEBUG(10, ("set_domain_online_request: Internal domains are "
579 "always online\n"));
580 return;
583 /* We've been told it's safe to go online and
584 try and connect to a DC. But I don't believe it
585 because network manager seems to lie.
586 Wait at least 5 seconds. Heuristics suck... */
589 GetTimeOfDay(&tev);
591 /* Go into "startup" mode again. */
592 domain->startup_time = time_mono(NULL);
593 domain->startup = True;
595 tev.tv_sec += 5;
597 if (!domain->check_online_event) {
598 /* If we've come from being globally offline we
599 don't have a check online event handler set.
600 We need to add one now we're trying to go
601 back online. */
603 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
604 domain->name ));
607 TALLOC_FREE(domain->check_online_event);
609 domain->check_online_event = tevent_add_timer(server_event_context(),
610 NULL,
611 tev,
612 check_domain_online_handler,
613 domain);
615 /* The above *has* to succeed for winbindd to work. */
616 if (!domain->check_online_event) {
617 smb_panic("set_domain_online_request: failed to add online handler");
621 /****************************************************************
622 Add -ve connection cache entries for domain and realm.
623 ****************************************************************/
625 static void winbind_add_failed_connection_entry(
626 const struct winbindd_domain *domain,
627 const char *server,
628 NTSTATUS result)
630 add_failed_connection_entry(domain->name, server, result);
631 /* If this was the saf name for the last thing we talked to,
632 remove it. */
633 saf_delete(domain->name);
634 if (domain->alt_name != NULL) {
635 add_failed_connection_entry(domain->alt_name, server, result);
636 saf_delete(domain->alt_name);
638 winbindd_unset_locator_kdc_env(domain);
641 /* Choose between anonymous or authenticated connections. We need to use
642 an authenticated connection if DCs have the RestrictAnonymous registry
643 entry set > 0, or the "Additional restrictions for anonymous
644 connections" set in the win2k Local Security Policy.
646 Caller to free() result in domain, username, password
649 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
651 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
652 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
653 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
655 if (*username && **username) {
657 if (!*domain || !**domain)
658 *domain = smb_xstrdup(lp_workgroup());
660 if (!*password || !**password)
661 *password = smb_xstrdup("");
663 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
664 *domain, *username));
666 } else {
667 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
668 *username = smb_xstrdup("");
669 *domain = smb_xstrdup("");
670 *password = smb_xstrdup("");
674 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
675 struct cli_credentials **_creds)
678 TALLOC_CTX *frame = talloc_stackframe();
679 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
680 struct loadparm_context *lp_ctx;
681 char *username = NULL;
682 char *netbios_domain = NULL;
683 char *password = NULL;
684 struct cli_credentials *creds = NULL;
685 bool ok;
687 cm_get_ipc_userpass(&username, &netbios_domain, &password);
689 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
690 if (lp_ctx == NULL) {
691 DEBUG(1, ("loadparm_init_s3 failed\n"));
692 status = NT_STATUS_INTERNAL_ERROR;
693 goto fail;
696 creds = cli_credentials_init(mem_ctx);
697 if (creds == NULL) {
698 status = NT_STATUS_NO_MEMORY;
699 goto fail;
702 cli_credentials_set_conf(creds, lp_ctx);
703 cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
705 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
706 if (!ok) {
707 status = NT_STATUS_NO_MEMORY;
708 goto fail;
711 ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
712 if (!ok) {
713 status = NT_STATUS_NO_MEMORY;
714 goto fail;
717 ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
718 if (!ok) {
719 status = NT_STATUS_NO_MEMORY;
720 goto fail;
723 *_creds = creds;
724 creds = NULL;
725 status = NT_STATUS_OK;
726 fail:
727 TALLOC_FREE(creds);
728 SAFE_FREE(username);
729 SAFE_FREE(netbios_domain);
730 SAFE_FREE(password);
731 TALLOC_FREE(frame);
732 return status;
735 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
737 TALLOC_CTX *frame = talloc_stackframe();
738 char *ipc_account = NULL;
739 char *ipc_domain = NULL;
740 char *ipc_password = NULL;
741 const char *creds_account = NULL;
742 const char *creds_domain = NULL;
743 const char *creds_password = NULL;
744 bool ret = false;
746 cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
748 creds_account = cli_credentials_get_username(creds);
749 creds_domain = cli_credentials_get_domain(creds);
750 creds_password = cli_credentials_get_password(creds);
752 if (!strequal(ipc_domain, creds_domain)) {
753 goto done;
756 if (!strequal(ipc_account, creds_account)) {
757 goto done;
760 if (!strcsequal(ipc_password, creds_password)) {
761 goto done;
764 ret = true;
765 done:
766 SAFE_FREE(ipc_account);
767 SAFE_FREE(ipc_domain);
768 SAFE_FREE(ipc_password);
769 TALLOC_FREE(frame);
770 return ret;
773 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
774 fstring dcname,
775 struct sockaddr_storage *dc_ss,
776 uint32_t request_flags)
778 struct winbindd_domain *our_domain = NULL;
779 struct rpc_pipe_client *netlogon_pipe = NULL;
780 NTSTATUS result;
781 WERROR werr;
782 TALLOC_CTX *mem_ctx;
783 unsigned int orig_timeout;
784 const char *tmp = NULL;
785 const char *p;
786 struct dcerpc_binding_handle *b;
788 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
789 * moment.... */
791 if (IS_DC) {
792 return False;
795 if (domain->primary) {
796 return False;
799 our_domain = find_our_domain();
801 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
802 return False;
805 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
806 if (!NT_STATUS_IS_OK(result)) {
807 talloc_destroy(mem_ctx);
808 return False;
811 b = netlogon_pipe->binding_handle;
813 /* This call can take a long time - allow the server to time out.
814 35 seconds should do it. */
816 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
818 if (our_domain->active_directory) {
819 struct netr_DsRGetDCNameInfo *domain_info = NULL;
822 * TODO request flags are not respected in the server
823 * (and in some cases, like REQUIRE_PDC, causes an error)
825 result = dcerpc_netr_DsRGetDCName(b,
826 mem_ctx,
827 our_domain->dcname,
828 domain->name,
829 NULL,
830 NULL,
831 request_flags|DS_RETURN_DNS_NAME,
832 &domain_info,
833 &werr);
834 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
835 tmp = talloc_strdup(
836 mem_ctx, domain_info->dc_unc);
837 if (tmp == NULL) {
838 DEBUG(0, ("talloc_strdup failed\n"));
839 talloc_destroy(mem_ctx);
840 return false;
842 if (domain->alt_name == NULL) {
843 domain->alt_name = talloc_strdup(domain,
844 domain_info->domain_name);
845 if (domain->alt_name == NULL) {
846 DEBUG(0, ("talloc_strdup failed\n"));
847 talloc_destroy(mem_ctx);
848 return false;
851 if (domain->forest_name == NULL) {
852 domain->forest_name = talloc_strdup(domain,
853 domain_info->forest_name);
854 if (domain->forest_name == NULL) {
855 DEBUG(0, ("talloc_strdup failed\n"));
856 talloc_destroy(mem_ctx);
857 return false;
861 } else {
862 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
863 our_domain->dcname,
864 domain->name,
865 &tmp,
866 &werr);
869 /* And restore our original timeout. */
870 rpccli_set_timeout(netlogon_pipe, orig_timeout);
872 if (!NT_STATUS_IS_OK(result)) {
873 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
874 nt_errstr(result)));
875 talloc_destroy(mem_ctx);
876 return false;
879 if (!W_ERROR_IS_OK(werr)) {
880 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
881 win_errstr(werr)));
882 talloc_destroy(mem_ctx);
883 return false;
886 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
887 p = strip_hostname(tmp);
889 fstrcpy(dcname, p);
891 talloc_destroy(mem_ctx);
893 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
895 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
896 return False;
899 return True;
903 * Helper function to assemble trust password and account name
905 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
906 TALLOC_CTX *mem_ctx,
907 bool netlogon,
908 struct cli_credentials **_creds)
910 const struct winbindd_domain *creds_domain = NULL;
911 struct cli_credentials *creds;
912 NTSTATUS status;
913 bool force_machine_account = false;
915 /* If we are a DC and this is not our own domain */
917 if (!domain->active_directory) {
918 if (!netlogon) {
920 * For non active directory domains
921 * we can only use NTLMSSP for SMB.
923 * But the trust account is not allowed
924 * to use SMB with NTLMSSP.
926 force_machine_account = true;
930 if (IS_DC && !force_machine_account) {
931 creds_domain = domain;
932 } else {
933 creds_domain = find_our_domain();
934 if (creds_domain == NULL) {
935 return NT_STATUS_INVALID_SERVER_STATE;
939 status = pdb_get_trust_credentials(creds_domain->name,
940 creds_domain->alt_name,
941 mem_ctx,
942 &creds);
943 if (!NT_STATUS_IS_OK(status)) {
944 goto ipc_fallback;
947 if (creds_domain != domain) {
949 * We can only use schannel against a direct trust
951 cli_credentials_set_secure_channel_type(creds,
952 SEC_CHAN_NULL);
955 *_creds = creds;
956 return NT_STATUS_OK;
958 ipc_fallback:
959 if (netlogon) {
960 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
963 status = cm_get_ipc_credentials(mem_ctx, &creds);
964 if (!NT_STATUS_IS_OK(status)) {
965 return status;
968 *_creds = creds;
969 return NT_STATUS_OK;
972 /************************************************************************
973 Given a fd with a just-connected TCP connection to a DC, open a connection
974 to the pipe.
975 ************************************************************************/
977 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
978 const int sockfd,
979 const char *controller,
980 struct cli_state **cli,
981 bool *retry)
983 bool try_ipc_auth = false;
984 const char *machine_principal = NULL;
985 const char *machine_realm = NULL;
986 const char *machine_account = NULL;
987 const char *machine_domain = NULL;
988 int flags = 0;
989 struct cli_credentials *creds = NULL;
991 struct named_mutex *mutex;
993 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
994 NTSTATUS tmp_status;
995 NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
997 enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
999 if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
1001 * If we are connecting to our own AD domain, require
1002 * smb signing to disrupt MITM attacks
1004 if (domain->primary && lp_security() == SEC_ADS) {
1005 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1007 * If we are in or are an AD domain and connecting to another
1008 * AD domain in our forest
1009 * then require smb signing to disrupt MITM attacks
1011 } else if ((lp_security() == SEC_ADS ||
1012 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)
1013 && domain->active_directory
1014 && (domain->domain_trust_attribs
1015 & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
1016 smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1020 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1021 controller, domain->name ));
1023 *retry = True;
1025 mutex = grab_named_mutex(talloc_tos(), controller,
1026 WINBIND_SERVER_MUTEX_WAIT_TIME);
1027 if (mutex == NULL) {
1028 close(sockfd);
1029 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1030 controller));
1031 result = NT_STATUS_POSSIBLE_DEADLOCK;
1032 goto done;
1035 *cli = cli_state_create(NULL, sockfd, controller,
1036 smb_sign_client_connections, flags);
1037 if (*cli == NULL) {
1038 close(sockfd);
1039 DEBUG(1, ("Could not cli_initialize\n"));
1040 result = NT_STATUS_NO_MEMORY;
1041 goto done;
1044 cli_set_timeout(*cli, 10000); /* 10 seconds */
1046 set_socket_options(sockfd, lp_socket_options());
1048 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
1049 lp_client_ipc_min_protocol(),
1050 lp_client_ipc_max_protocol());
1052 if (!NT_STATUS_IS_OK(result)) {
1053 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
1054 goto done;
1057 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
1058 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
1059 try_ipc_auth = true;
1060 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1061 try_ipc_auth = true;
1062 } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1064 * If we are forcing on SMB signing, then we must
1065 * require authentication unless this is a one-way
1066 * trust, and we have no stored user/password
1068 try_ipc_auth = true;
1071 if (try_ipc_auth) {
1072 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
1073 if (!NT_STATUS_IS_OK(result)) {
1074 DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1075 domain->name, nt_errstr(result)));
1076 goto done;
1078 } else {
1080 * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1081 * would try and authentication with our machine
1082 * account password and fail. This is very rare in
1083 * the modern world however
1085 creds = cli_credentials_init_anon(talloc_tos());
1086 if (creds == NULL) {
1087 result = NT_STATUS_NO_MEMORY;
1088 DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1089 domain->name, nt_errstr(result)));
1090 goto done;
1094 machine_principal = cli_credentials_get_principal(creds,
1095 talloc_tos());
1096 machine_realm = cli_credentials_get_realm(creds);
1097 machine_account = cli_credentials_get_username(creds);
1098 machine_domain = cli_credentials_get_domain(creds);
1100 DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1101 "[%s] and realm [%s]\n",
1102 controller, domain->name, domain->alt_name,
1103 machine_domain, machine_account,
1104 machine_principal, machine_realm));
1106 if (cli_credentials_is_anonymous(creds)) {
1107 goto anon_fallback;
1110 winbindd_set_locator_kdc_envs(domain);
1112 result = cli_session_setup_creds(*cli, creds);
1113 if (NT_STATUS_IS_OK(result)) {
1114 goto session_setup_done;
1117 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1118 controller,
1119 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1120 nt_errstr(result)));
1123 * If we are not going to validiate the conneciton
1124 * with SMB signing, then allow us to fall back to
1125 * anonymous
1127 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1128 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1129 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1130 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1131 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1133 if (!cm_is_ipc_credentials(creds)) {
1134 goto ipc_fallback;
1137 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1138 goto done;
1141 goto anon_fallback;
1144 goto done;
1146 ipc_fallback:
1147 TALLOC_FREE(creds);
1148 tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1149 if (!NT_STATUS_IS_OK(tmp_status)) {
1150 result = tmp_status;
1151 goto done;
1154 if (cli_credentials_is_anonymous(creds)) {
1155 goto anon_fallback;
1158 machine_account = cli_credentials_get_username(creds);
1159 machine_domain = cli_credentials_get_domain(creds);
1161 DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1162 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1163 machine_domain, machine_account));
1165 result = cli_session_setup_creds(*cli, creds);
1166 if (NT_STATUS_IS_OK(result)) {
1167 goto session_setup_done;
1170 DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1171 controller,
1172 cli_credentials_get_unparsed_name(creds, talloc_tos()),
1173 nt_errstr(result)));
1176 * If we are not going to validiate the conneciton
1177 * with SMB signing, then allow us to fall back to
1178 * anonymous
1180 if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1181 || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1182 || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1183 || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1184 || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1186 goto anon_fallback;
1189 goto done;
1191 anon_fallback:
1192 TALLOC_FREE(creds);
1194 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1195 goto done;
1198 /* Fall back to anonymous connection, this might fail later */
1199 DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1200 "connection for DC %s\n",
1201 controller ));
1203 result = cli_session_setup_anon(*cli);
1204 if (NT_STATUS_IS_OK(result)) {
1205 DEBUG(5, ("Connected anonymously\n"));
1206 goto session_setup_done;
1209 DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1210 controller, nt_errstr(result)));
1212 /* We can't session setup */
1213 goto done;
1215 session_setup_done:
1216 TALLOC_FREE(creds);
1219 * This should be a short term hack until
1220 * dynamic re-authentication is implemented.
1222 * See Bug 9175 - winbindd doesn't recover from
1223 * NT_STATUS_NETWORK_SESSION_EXPIRED
1225 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1226 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1229 result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1230 if (!NT_STATUS_IS_OK(result)) {
1231 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1232 goto done;
1234 tcon_status = result;
1236 /* cache the server name for later connections */
1238 saf_store(domain->name, controller);
1239 if (domain->alt_name) {
1240 saf_store(domain->alt_name, controller);
1243 winbindd_set_locator_kdc_envs(domain);
1245 TALLOC_FREE(mutex);
1246 *retry = False;
1248 result = NT_STATUS_OK;
1250 done:
1251 TALLOC_FREE(mutex);
1252 TALLOC_FREE(creds);
1254 if (NT_STATUS_IS_OK(result)) {
1255 result = tcon_status;
1258 if (!NT_STATUS_IS_OK(result)) {
1259 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1260 controller, nt_errstr(result)));
1261 winbind_add_failed_connection_entry(domain, controller, result);
1262 if ((*cli) != NULL) {
1263 cli_shutdown(*cli);
1264 *cli = NULL;
1268 return result;
1271 /*******************************************************************
1272 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1273 array.
1275 Keeps the list unique by not adding duplicate entries.
1277 @param[in] mem_ctx talloc memory context to allocate from
1278 @param[in] domain_name domain of the DC
1279 @param[in] dcname name of the DC to add to the list
1280 @param[in] pss Internet address and port pair to add to the list
1281 @param[in,out] dcs array of dc_name_ip structures to add to
1282 @param[in,out] num_dcs number of dcs returned in the dcs array
1283 @return true if the list was added to, false otherwise
1284 *******************************************************************/
1286 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1287 const char *dcname, struct sockaddr_storage *pss,
1288 struct dc_name_ip **dcs, int *num)
1290 int i = 0;
1292 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1293 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1294 return False;
1297 /* Make sure there's no duplicates in the list */
1298 for (i=0; i<*num; i++)
1299 if (sockaddr_equal(
1300 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1301 (struct sockaddr *)(void *)pss))
1302 return False;
1304 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1306 if (*dcs == NULL)
1307 return False;
1309 fstrcpy((*dcs)[*num].name, dcname);
1310 (*dcs)[*num].ss = *pss;
1311 *num += 1;
1312 return True;
1315 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1316 struct sockaddr_storage *pss, uint16_t port,
1317 struct sockaddr_storage **addrs, int *num)
1319 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1321 if (*addrs == NULL) {
1322 *num = 0;
1323 return False;
1326 (*addrs)[*num] = *pss;
1327 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1329 *num += 1;
1330 return True;
1333 /*******************************************************************
1334 convert an ip to a name
1335 For an AD Domain, it checks the requirements of the request flags.
1336 *******************************************************************/
1338 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1339 const struct winbindd_domain *domain,
1340 struct sockaddr_storage *pss,
1341 char **name, uint32_t request_flags)
1343 struct ip_service ip_list;
1344 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1345 NTSTATUS status;
1346 const char *dc_name;
1347 fstring nbtname;
1348 #ifdef HAVE_ADS
1349 bool is_ad_domain = false;
1350 #endif
1351 ip_list.ss = *pss;
1352 ip_list.port = 0;
1354 #ifdef HAVE_ADS
1355 /* For active directory servers, try to get the ldap server name.
1356 None of these failures should be considered critical for now */
1358 if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1359 is_ad_domain = true;
1360 } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1361 is_ad_domain = domain->active_directory;
1364 if (is_ad_domain) {
1365 ADS_STRUCT *ads;
1366 ADS_STATUS ads_status;
1367 char addr[INET6_ADDRSTRLEN];
1369 print_sockaddr(addr, sizeof(addr), pss);
1371 ads = ads_init(domain->alt_name, domain->name, addr);
1372 ads->auth.flags |= ADS_AUTH_NO_BIND;
1373 ads->config.flags |= request_flags;
1374 ads->server.no_fallback = true;
1376 ads_status = ads_connect(ads);
1377 if (ADS_ERR_OK(ads_status)) {
1378 /* We got a cldap packet. */
1379 *name = talloc_strdup(mem_ctx,
1380 ads->config.ldap_server_name);
1381 if (*name == NULL) {
1382 return false;
1384 namecache_store(*name, 0x20, 1, &ip_list);
1386 DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1388 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1389 if (ads_closest_dc(ads)) {
1390 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1392 /* We're going to use this KDC for this realm/domain.
1393 If we are using sites, then force the krb5 libs
1394 to use this KDC. */
1396 create_local_private_krb5_conf_for_domain(domain->alt_name,
1397 domain->name,
1398 sitename,
1399 pss);
1401 TALLOC_FREE(sitename);
1402 } else {
1403 /* use an off site KDC */
1404 create_local_private_krb5_conf_for_domain(domain->alt_name,
1405 domain->name,
1406 NULL,
1407 pss);
1409 winbindd_set_locator_kdc_envs(domain);
1411 /* Ensure we contact this DC also. */
1412 saf_store(domain->name, *name);
1413 saf_store(domain->alt_name, *name);
1416 ads_destroy( &ads );
1417 return True;
1420 ads_destroy( &ads );
1421 return false;
1423 #endif
1425 status = nbt_getdc(server_messaging_context(), 10, pss, domain->name,
1426 &domain->sid, nt_version, mem_ctx, &nt_version,
1427 &dc_name, NULL);
1428 if (NT_STATUS_IS_OK(status)) {
1429 *name = talloc_strdup(mem_ctx, dc_name);
1430 if (*name == NULL) {
1431 return false;
1433 namecache_store(*name, 0x20, 1, &ip_list);
1434 return True;
1437 /* try node status request */
1439 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1440 namecache_store(nbtname, 0x20, 1, &ip_list);
1442 if (name != NULL) {
1443 *name = talloc_strdup(mem_ctx, nbtname);
1444 if (*name == NULL) {
1445 return false;
1449 return true;
1451 return False;
1454 /*******************************************************************
1455 Retrieve a list of IP addresses for domain controllers.
1457 The array is sorted in the preferred connection order.
1459 @param[in] mem_ctx talloc memory context to allocate from
1460 @param[in] domain domain to retrieve DCs for
1461 @param[out] dcs array of dcs that will be returned
1462 @param[out] num_dcs number of dcs returned in the dcs array
1463 @return always true
1464 *******************************************************************/
1466 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1467 struct dc_name_ip **dcs, int *num_dcs,
1468 uint32_t request_flags)
1470 fstring dcname;
1471 struct sockaddr_storage ss;
1472 struct ip_service *ip_list = NULL;
1473 int iplist_size = 0;
1474 int i;
1475 bool is_our_domain;
1476 enum security_types sec = (enum security_types)lp_security();
1478 is_our_domain = strequal(domain->name, lp_workgroup());
1480 /* If not our domain, get the preferred DC, by asking our primary DC */
1481 if ( !is_our_domain
1482 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1483 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1484 num_dcs) )
1486 char addr[INET6_ADDRSTRLEN];
1487 print_sockaddr(addr, sizeof(addr), &ss);
1488 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1489 dcname, addr));
1490 return True;
1493 if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1494 char *sitename = NULL;
1496 /* We need to make sure we know the local site before
1497 doing any DNS queries, as this will restrict the
1498 get_sorted_dc_list() call below to only fetching
1499 DNS records for the correct site. */
1501 /* Find any DC to get the site record.
1502 We deliberately don't care about the
1503 return here. */
1505 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1507 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1508 if (sitename) {
1510 /* Do the site-specific AD dns lookup first. */
1511 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1512 &iplist_size, True);
1514 /* Add ips to the DC array. We don't look up the name
1515 of the DC in this function, but we fill in the char*
1516 of the ip now to make the failed connection cache
1517 work */
1518 for ( i=0; i<iplist_size; i++ ) {
1519 char addr[INET6_ADDRSTRLEN];
1520 print_sockaddr(addr, sizeof(addr),
1521 &ip_list[i].ss);
1522 add_one_dc_unique(mem_ctx,
1523 domain->name,
1524 addr,
1525 &ip_list[i].ss,
1526 dcs,
1527 num_dcs);
1530 SAFE_FREE(ip_list);
1531 TALLOC_FREE(sitename);
1532 iplist_size = 0;
1535 /* Now we add DCs from the main AD DNS lookup. */
1536 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1537 &iplist_size, True);
1539 for ( i=0; i<iplist_size; i++ ) {
1540 char addr[INET6_ADDRSTRLEN];
1541 print_sockaddr(addr, sizeof(addr),
1542 &ip_list[i].ss);
1543 add_one_dc_unique(mem_ctx,
1544 domain->name,
1545 addr,
1546 &ip_list[i].ss,
1547 dcs,
1548 num_dcs);
1551 SAFE_FREE(ip_list);
1552 iplist_size = 0;
1555 /* Try standard netbios queries if no ADS and fall back to DNS queries
1556 * if alt_name is available */
1557 if (*num_dcs == 0) {
1558 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1559 false);
1560 if (iplist_size == 0) {
1561 if (domain->alt_name != NULL) {
1562 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1563 &iplist_size, true);
1567 for ( i=0; i<iplist_size; i++ ) {
1568 char addr[INET6_ADDRSTRLEN];
1569 print_sockaddr(addr, sizeof(addr),
1570 &ip_list[i].ss);
1571 add_one_dc_unique(mem_ctx,
1572 domain->name,
1573 addr,
1574 &ip_list[i].ss,
1575 dcs,
1576 num_dcs);
1579 SAFE_FREE(ip_list);
1580 iplist_size = 0;
1583 return True;
1586 /*******************************************************************
1587 Find and make a connection to a DC in the given domain.
1589 @param[in] mem_ctx talloc memory context to allocate from
1590 @param[in] domain domain to find a dc in
1591 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1592 @param[out] pss DC Internet address and port
1593 @param[out] fd fd of the open socket connected to the newly found dc
1594 @return true when a DC connection is made, false otherwise
1595 *******************************************************************/
1597 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1598 struct winbindd_domain *domain,
1599 char **dcname, struct sockaddr_storage *pss, int *fd,
1600 uint32_t request_flags)
1602 struct dc_name_ip *dcs = NULL;
1603 int num_dcs = 0;
1605 const char **dcnames = NULL;
1606 size_t num_dcnames = 0;
1608 struct sockaddr_storage *addrs = NULL;
1609 int num_addrs = 0;
1611 int i;
1612 size_t fd_index;
1614 NTSTATUS status;
1616 *fd = -1;
1618 again:
1619 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1620 return False;
1622 for (i=0; i<num_dcs; i++) {
1624 if (!add_string_to_array(mem_ctx, dcs[i].name,
1625 &dcnames, &num_dcnames)) {
1626 return False;
1628 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1629 &addrs, &num_addrs)) {
1630 return False;
1634 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1635 return False;
1637 if ((addrs == NULL) || (dcnames == NULL))
1638 return False;
1640 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1641 num_addrs, 0, 10, fd, &fd_index, NULL);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 for (i=0; i<num_dcs; i++) {
1644 char ab[INET6_ADDRSTRLEN];
1645 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1646 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1647 "domain %s address %s. Error was %s\n",
1648 domain->name, ab, nt_errstr(status) ));
1649 winbind_add_failed_connection_entry(domain,
1650 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1652 return False;
1655 *pss = addrs[fd_index];
1657 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1658 /* Ok, we've got a name for the DC */
1659 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1660 if (*dcname == NULL) {
1661 return false;
1663 return true;
1666 /* Try to figure out the name */
1667 if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1668 return True;
1671 /* We can not continue without the DC's name */
1672 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1673 NT_STATUS_UNSUCCESSFUL);
1675 /* Throw away all arrays as we're doing this again. */
1676 TALLOC_FREE(dcs);
1677 num_dcs = 0;
1679 TALLOC_FREE(dcnames);
1680 num_dcnames = 0;
1682 TALLOC_FREE(addrs);
1683 num_addrs = 0;
1685 close(*fd);
1686 *fd = -1;
1688 goto again;
1691 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1693 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1694 domain_name);
1697 static void store_current_dc_in_gencache(const char *domain_name,
1698 const char *dc_name,
1699 struct cli_state *cli)
1701 char addr[INET6_ADDRSTRLEN];
1702 char *key = NULL;
1703 char *value = NULL;
1705 if (!cli_state_is_connected(cli)) {
1706 return;
1709 print_sockaddr(addr, sizeof(addr),
1710 smbXcli_conn_remote_sockaddr(cli->conn));
1712 key = current_dc_key(talloc_tos(), domain_name);
1713 if (key == NULL) {
1714 goto done;
1717 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1718 if (value == NULL) {
1719 goto done;
1722 gencache_set(key, value, 0x7fffffff);
1723 done:
1724 TALLOC_FREE(value);
1725 TALLOC_FREE(key);
1728 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1729 const char *domain_name,
1730 char **p_dc_name, char **p_dc_ip)
1732 char *key, *p;
1733 char *value = NULL;
1734 bool ret = false;
1735 char *dc_name = NULL;
1736 char *dc_ip = NULL;
1738 key = current_dc_key(talloc_tos(), domain_name);
1739 if (key == NULL) {
1740 goto done;
1742 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1743 goto done;
1745 p = strchr(value, ' ');
1746 if (p == NULL) {
1747 goto done;
1749 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1750 if (dc_ip == NULL) {
1751 goto done;
1753 dc_name = talloc_strdup(mem_ctx, p+1);
1754 if (dc_name == NULL) {
1755 goto done;
1758 if (p_dc_ip != NULL) {
1759 *p_dc_ip = dc_ip;
1760 dc_ip = NULL;
1762 if (p_dc_name != NULL) {
1763 *p_dc_name = dc_name;
1764 dc_name = NULL;
1766 ret = true;
1767 done:
1768 TALLOC_FREE(dc_name);
1769 TALLOC_FREE(dc_ip);
1770 TALLOC_FREE(key);
1771 TALLOC_FREE(value);
1772 return ret;
1775 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1776 const struct ndr_interface_table *table,
1777 struct rpc_pipe_client **ret_pipe)
1779 struct rpc_pipe_client *cli = NULL;
1780 const struct auth_session_info *session_info;
1781 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1784 session_info = get_session_info_system();
1785 SMB_ASSERT(session_info != NULL);
1787 /* create a connection to the specified pipe */
1788 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1789 status = rpc_pipe_open_interface(mem_ctx,
1790 table,
1791 session_info,
1792 NULL,
1793 NULL,
1794 server_messaging_context(),
1795 &cli);
1796 } else {
1797 status = rpc_pipe_open_internal(mem_ctx,
1798 table,
1799 session_info,
1800 NULL,
1801 NULL,
1802 server_messaging_context(),
1803 &cli);
1805 if (!NT_STATUS_IS_OK(status)) {
1806 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1807 table->name, nt_errstr(status)));
1808 return status;
1811 if (ret_pipe) {
1812 *ret_pipe = cli;
1815 return NT_STATUS_OK;
1818 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1819 struct winbindd_cm_conn *new_conn,
1820 bool need_rw_dc)
1822 TALLOC_CTX *mem_ctx;
1823 NTSTATUS result;
1824 char *saf_servername;
1825 int retries;
1826 uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1828 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1829 set_domain_offline(domain);
1830 return NT_STATUS_NO_MEMORY;
1833 saf_servername = saf_fetch(mem_ctx, domain->name );
1835 /* we have to check the server affinity cache here since
1836 later we select a DC based on response time and not preference */
1838 /* Check the negative connection cache
1839 before talking to it. It going down may have
1840 triggered the reconnection. */
1842 if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1843 struct sockaddr_storage ss;
1844 char *dcname = NULL;
1845 bool resolved = true;
1847 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1848 saf_servername, domain->name));
1850 /* convert an ip address to a name */
1851 if (is_ipaddress(saf_servername)) {
1852 if (!interpret_string_addr(&ss, saf_servername,
1853 AI_NUMERICHOST)) {
1854 TALLOC_FREE(mem_ctx);
1855 return NT_STATUS_UNSUCCESSFUL;
1857 } else {
1858 if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1859 resolved = false;
1863 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1864 domain->dcname = talloc_strdup(domain,
1865 dcname);
1866 if (domain->dcname == NULL) {
1867 TALLOC_FREE(mem_ctx);
1868 return NT_STATUS_NO_MEMORY;
1871 domain->dcaddr = ss;
1872 } else {
1873 winbind_add_failed_connection_entry(domain, saf_servername,
1874 NT_STATUS_UNSUCCESSFUL);
1878 for (retries = 0; retries < 3; retries++) {
1879 int fd = -1;
1880 bool retry = False;
1881 char *dcname = NULL;
1883 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1885 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1886 domain->dcname ? domain->dcname : "", domain->name));
1888 if (domain->dcname != NULL &&
1889 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1890 domain->dcname)))
1892 NTSTATUS status;
1894 status = smbsock_connect(&domain->dcaddr, 0,
1895 NULL, -1, NULL, -1,
1896 &fd, NULL, 10);
1897 if (!NT_STATUS_IS_OK(status)) {
1898 fd = -1;
1902 if ((fd == -1) &&
1903 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1905 /* This is the one place where we will
1906 set the global winbindd offline state
1907 to true, if a "WINBINDD_OFFLINE" entry
1908 is found in the winbindd cache. */
1909 set_global_winbindd_state_offline();
1910 break;
1912 if (dcname != NULL) {
1913 talloc_free(domain->dcname);
1915 domain->dcname = talloc_move(domain, &dcname);
1916 if (domain->dcname == NULL) {
1917 result = NT_STATUS_NO_MEMORY;
1918 break;
1922 new_conn->cli = NULL;
1924 result = cm_prepare_connection(domain, fd, domain->dcname,
1925 &new_conn->cli, &retry);
1926 if (!NT_STATUS_IS_OK(result)) {
1927 /* Don't leak the smb connection socket */
1928 close(fd);
1931 if (!retry)
1932 break;
1935 if (NT_STATUS_IS_OK(result)) {
1936 bool seal_pipes = true;
1938 winbindd_set_locator_kdc_envs(domain);
1940 if (domain->online == False) {
1941 /* We're changing state from offline to online. */
1942 set_global_winbindd_state_online();
1944 set_domain_online(domain);
1947 * Much as I hate global state, this seems to be the point
1948 * where we can be certain that we have a proper connection to
1949 * a DC. wbinfo --dc-info needs that information, store it in
1950 * gencache with a looong timeout. This will need revisiting
1951 * once we start to connect to multiple DCs, wbcDcInfo is
1952 * already prepared for that.
1954 store_current_dc_in_gencache(domain->name, domain->dcname,
1955 new_conn->cli);
1957 seal_pipes = lp_winbind_sealed_pipes();
1958 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1959 domain->name,
1960 seal_pipes);
1962 if (seal_pipes) {
1963 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1964 } else {
1965 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1967 } else {
1968 /* Ensure we setup the retry handler. */
1969 set_domain_offline(domain);
1972 talloc_destroy(mem_ctx);
1973 return result;
1976 /* Close down all open pipes on a connection. */
1978 void invalidate_cm_connection(struct winbindd_domain *domain)
1980 NTSTATUS result;
1981 struct winbindd_cm_conn *conn = &domain->conn;
1983 /* We're closing down a possibly dead
1984 connection. Don't have impossibly long (10s) timeouts. */
1986 if (conn->cli) {
1987 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1990 if (conn->samr_pipe != NULL) {
1991 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1992 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1993 talloc_tos(),
1994 &conn->sam_connect_handle,
1995 &result);
1997 TALLOC_FREE(conn->samr_pipe);
1998 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1999 if (conn->cli) {
2000 cli_set_timeout(conn->cli, 500);
2004 if (conn->lsa_pipe != NULL) {
2005 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2006 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2007 talloc_tos(),
2008 &conn->lsa_policy,
2009 &result);
2011 TALLOC_FREE(conn->lsa_pipe);
2012 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2013 if (conn->cli) {
2014 cli_set_timeout(conn->cli, 500);
2018 if (conn->lsa_pipe_tcp != NULL) {
2019 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2020 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2021 talloc_tos(),
2022 &conn->lsa_policy,
2023 &result);
2025 TALLOC_FREE(conn->lsa_pipe_tcp);
2026 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2027 if (conn->cli) {
2028 cli_set_timeout(conn->cli, 500);
2032 if (conn->netlogon_pipe != NULL) {
2033 TALLOC_FREE(conn->netlogon_pipe);
2034 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2035 if (conn->cli) {
2036 cli_set_timeout(conn->cli, 500);
2040 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2041 conn->netlogon_force_reauth = false;
2042 TALLOC_FREE(conn->netlogon_creds_ctx);
2044 if (conn->cli) {
2045 cli_shutdown(conn->cli);
2048 conn->cli = NULL;
2051 void close_conns_after_fork(void)
2053 struct winbindd_domain *domain;
2054 struct winbindd_cli_state *cli_state;
2056 for (domain = domain_list(); domain; domain = domain->next) {
2058 * first close the low level SMB TCP connection
2059 * so that we don't generate any SMBclose
2060 * requests in invalidate_cm_connection()
2062 if (cli_state_is_connected(domain->conn.cli)) {
2063 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2066 invalidate_cm_connection(domain);
2069 for (cli_state = winbindd_client_list();
2070 cli_state != NULL;
2071 cli_state = cli_state->next) {
2072 if (cli_state->sock >= 0) {
2073 close(cli_state->sock);
2074 cli_state->sock = -1;
2079 static bool connection_ok(struct winbindd_domain *domain)
2081 bool ok;
2083 ok = cli_state_is_connected(domain->conn.cli);
2084 if (!ok) {
2085 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2086 domain->dcname, domain->name));
2087 return False;
2090 if (domain->online == False) {
2091 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2092 return False;
2095 return True;
2098 /* Initialize a new connection up to the RPC BIND.
2099 Bypass online status check so always does network calls. */
2101 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2103 NTSTATUS result;
2104 bool skip_connection = domain->internal;
2105 if (need_rw_dc && domain->rodc) {
2106 skip_connection = false;
2109 /* Internal connections never use the network. */
2110 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2111 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2114 /* Still ask the internal LSA and SAMR server about the local domain */
2115 if (skip_connection || connection_ok(domain)) {
2116 if (!domain->initialized) {
2117 set_dc_type_and_flags(domain);
2119 return NT_STATUS_OK;
2122 invalidate_cm_connection(domain);
2124 if (!domain->primary && !domain->initialized) {
2126 * Before we connect to a trust, work out if it is an
2127 * AD domain by asking our own domain.
2129 set_dc_type_and_flags_trustinfo(domain);
2132 result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2134 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2135 set_dc_type_and_flags(domain);
2138 return result;
2141 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2143 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2144 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2147 if (domain->initialized && !domain->online) {
2148 /* We check for online status elsewhere. */
2149 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2152 return init_dc_connection_network(domain, need_rw_dc);
2155 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2157 NTSTATUS status;
2159 status = init_dc_connection(domain, need_rw_dc);
2160 if (!NT_STATUS_IS_OK(status)) {
2161 return status;
2164 if (!domain->internal && domain->conn.cli == NULL) {
2165 /* happens for trusted domains without inbound trust */
2166 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2169 return NT_STATUS_OK;
2172 /******************************************************************************
2173 Set the trust flags (direction and forest location) for a domain
2174 ******************************************************************************/
2176 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2178 struct winbindd_domain *our_domain;
2179 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2180 WERROR werr;
2181 struct netr_DomainTrustList trusts;
2182 int i;
2183 uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2184 NETR_TRUST_FLAG_OUTBOUND |
2185 NETR_TRUST_FLAG_INBOUND);
2186 struct rpc_pipe_client *cli;
2187 TALLOC_CTX *mem_ctx = NULL;
2188 struct dcerpc_binding_handle *b;
2190 if (IS_DC) {
2192 * On a DC we loaded all trusts
2193 * from configuration and never learn
2194 * new domains.
2196 return true;
2199 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2201 /* Our primary domain doesn't need to worry about trust flags.
2202 Force it to go through the network setup */
2203 if ( domain->primary ) {
2204 return False;
2207 mem_ctx = talloc_stackframe();
2208 our_domain = find_our_domain();
2209 if (our_domain->internal) {
2210 result = init_dc_connection(our_domain, false);
2211 if (!NT_STATUS_IS_OK(result)) {
2212 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2213 "Not able to make a connection to our domain: %s\n",
2214 nt_errstr(result)));
2215 TALLOC_FREE(mem_ctx);
2216 return false;
2220 /* This won't work unless our domain is AD */
2221 if ( !our_domain->active_directory ) {
2222 TALLOC_FREE(mem_ctx);
2223 return False;
2226 if (our_domain->internal) {
2227 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2228 } else if (!connection_ok(our_domain)) {
2229 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2230 "No connection to our domain!\n"));
2231 TALLOC_FREE(mem_ctx);
2232 return False;
2233 } else {
2234 result = cm_connect_netlogon(our_domain, &cli);
2237 if (!NT_STATUS_IS_OK(result)) {
2238 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2239 "a connection to %s for PIPE_NETLOGON (%s)\n",
2240 domain->name, nt_errstr(result)));
2241 TALLOC_FREE(mem_ctx);
2242 return False;
2244 b = cli->binding_handle;
2246 /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2247 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2248 cli->desthost,
2249 flags,
2250 &trusts,
2251 &werr);
2252 if (!NT_STATUS_IS_OK(result)) {
2253 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2254 "failed to query trusted domain list: %s\n",
2255 nt_errstr(result)));
2256 TALLOC_FREE(mem_ctx);
2257 return false;
2259 if (!W_ERROR_IS_OK(werr)) {
2260 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2261 "failed to query trusted domain list: %s\n",
2262 win_errstr(werr)));
2263 TALLOC_FREE(mem_ctx);
2264 return false;
2267 /* Now find the domain name and get the flags */
2269 for ( i=0; i<trusts.count; i++ ) {
2270 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2271 domain->domain_flags = trusts.array[i].trust_flags;
2272 domain->domain_type = trusts.array[i].trust_type;
2273 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2275 if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2276 domain->active_directory = True;
2278 /* This flag is only set if the domain is *our*
2279 primary domain and the primary domain is in
2280 native mode */
2282 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2284 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2285 "native mode.\n", domain->name,
2286 domain->native_mode ? "" : "NOT "));
2288 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2289 "running active directory.\n", domain->name,
2290 domain->active_directory ? "" : "NOT "));
2292 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2294 domain->initialized = True;
2296 break;
2300 TALLOC_FREE(mem_ctx);
2302 return domain->initialized;
2305 /******************************************************************************
2306 We can 'sense' certain things about the DC by it's replies to certain
2307 questions.
2309 This tells us if this particular remote server is Active Directory, and if it
2310 is native mode.
2311 ******************************************************************************/
2313 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2315 NTSTATUS status, result;
2316 WERROR werr;
2317 TALLOC_CTX *mem_ctx = NULL;
2318 struct rpc_pipe_client *cli = NULL;
2319 struct policy_handle pol;
2320 union dssetup_DsRoleInfo info;
2321 union lsa_PolicyInformation *lsa_info = NULL;
2323 if (!domain->internal && !connection_ok(domain)) {
2324 return;
2327 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2328 domain->name);
2329 if (!mem_ctx) {
2330 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2331 return;
2334 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2336 if (domain->internal) {
2337 status = wb_open_internal_pipe(mem_ctx,
2338 &ndr_table_dssetup,
2339 &cli);
2340 } else {
2341 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2342 &ndr_table_dssetup,
2343 &cli);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2348 "PI_DSSETUP on domain %s: (%s)\n",
2349 domain->name, nt_errstr(status)));
2351 /* if this is just a non-AD domain we need to continue
2352 * identifying so that we can in the end return with
2353 * domain->initialized = True - gd */
2355 goto no_dssetup;
2358 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2359 DS_ROLE_BASIC_INFORMATION,
2360 &info,
2361 &werr);
2362 TALLOC_FREE(cli);
2364 if (NT_STATUS_IS_OK(status)) {
2365 result = werror_to_ntstatus(werr);
2367 if (!NT_STATUS_IS_OK(status)) {
2368 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2369 "on domain %s failed: (%s)\n",
2370 domain->name, nt_errstr(status)));
2372 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2373 * every opcode on the DSSETUP pipe, continue with
2374 * no_dssetup mode here as well to get domain->initialized
2375 * set - gd */
2377 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2378 goto no_dssetup;
2381 TALLOC_FREE(mem_ctx);
2382 return;
2385 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2386 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2387 domain->native_mode = True;
2388 } else {
2389 domain->native_mode = False;
2392 no_dssetup:
2393 if (domain->internal) {
2394 status = wb_open_internal_pipe(mem_ctx,
2395 &ndr_table_lsarpc,
2396 &cli);
2397 } else {
2398 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2399 &ndr_table_lsarpc, &cli);
2401 if (!NT_STATUS_IS_OK(status)) {
2402 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2403 "PI_LSARPC on domain %s: (%s)\n",
2404 domain->name, nt_errstr(status)));
2405 TALLOC_FREE(cli);
2406 TALLOC_FREE(mem_ctx);
2407 return;
2410 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2411 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2413 if (NT_STATUS_IS_OK(status)) {
2414 /* This particular query is exactly what Win2k clients use
2415 to determine that the DC is active directory */
2416 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2417 &pol,
2418 LSA_POLICY_INFO_DNS,
2419 &lsa_info,
2420 &result);
2423 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2424 domain->active_directory = True;
2426 if (lsa_info->dns.name.string) {
2427 if (!strequal(domain->name, lsa_info->dns.name.string))
2429 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2430 "for domain %s claimed it was a DC "
2431 "for domain %s, refusing to "
2432 "initialize\n",
2433 domain->name,
2434 lsa_info->dns.name.string));
2435 TALLOC_FREE(cli);
2436 TALLOC_FREE(mem_ctx);
2437 return;
2439 talloc_free(domain->name);
2440 domain->name = talloc_strdup(domain,
2441 lsa_info->dns.name.string);
2442 if (domain->name == NULL) {
2443 goto done;
2447 if (lsa_info->dns.dns_domain.string) {
2448 if (domain->alt_name != NULL &&
2449 !strequal(domain->alt_name,
2450 lsa_info->dns.dns_domain.string))
2452 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2453 "for domain %s (%s) claimed it was "
2454 "a DC for domain %s, refusing to "
2455 "initialize\n",
2456 domain->alt_name, domain->name,
2457 lsa_info->dns.dns_domain.string));
2458 TALLOC_FREE(cli);
2459 TALLOC_FREE(mem_ctx);
2460 return;
2462 talloc_free(domain->alt_name);
2463 domain->alt_name =
2464 talloc_strdup(domain,
2465 lsa_info->dns.dns_domain.string);
2466 if (domain->alt_name == NULL) {
2467 goto done;
2471 /* See if we can set some domain trust flags about
2472 ourself */
2474 if (lsa_info->dns.dns_forest.string) {
2475 talloc_free(domain->forest_name);
2476 domain->forest_name =
2477 talloc_strdup(domain,
2478 lsa_info->dns.dns_forest.string);
2479 if (domain->forest_name == NULL) {
2480 goto done;
2483 if (strequal(domain->forest_name, domain->alt_name)) {
2484 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2488 if (lsa_info->dns.sid) {
2489 if (!is_null_sid(&domain->sid) &&
2490 !dom_sid_equal(&domain->sid,
2491 lsa_info->dns.sid))
2493 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2494 "for domain %s (%s) claimed it was "
2495 "a DC for domain %s, refusing to "
2496 "initialize\n",
2497 dom_sid_string(talloc_tos(),
2498 &domain->sid),
2499 domain->name,
2500 dom_sid_string(talloc_tos(),
2501 lsa_info->dns.sid)));
2502 TALLOC_FREE(cli);
2503 TALLOC_FREE(mem_ctx);
2504 return;
2506 sid_copy(&domain->sid, lsa_info->dns.sid);
2508 } else {
2509 domain->active_directory = False;
2511 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2512 SEC_FLAG_MAXIMUM_ALLOWED,
2513 &pol);
2515 if (!NT_STATUS_IS_OK(status)) {
2516 goto done;
2519 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2520 &pol,
2521 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2522 &lsa_info,
2523 &result);
2524 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2526 if (lsa_info->account_domain.name.string) {
2527 if (!strequal(domain->name,
2528 lsa_info->account_domain.name.string))
2530 DEBUG(1,
2531 ("set_dc_type_and_flags_connect: "
2532 "DC for domain %s claimed it was"
2533 " a DC for domain %s, refusing "
2534 "to initialize\n", domain->name,
2535 lsa_info->
2536 account_domain.name.string));
2537 TALLOC_FREE(cli);
2538 TALLOC_FREE(mem_ctx);
2539 return;
2541 talloc_free(domain->name);
2542 domain->name =
2543 talloc_strdup(domain,
2544 lsa_info->account_domain.name.string);
2547 if (lsa_info->account_domain.sid) {
2548 if (!is_null_sid(&domain->sid) &&
2549 !dom_sid_equal(&domain->sid,
2550 lsa_info->account_domain.sid))
2552 DEBUG(1,
2553 ("set_dc_type_and_flags_connect: "
2554 "DC for domain %s (%s) claimed "
2555 "it was a DC for domain %s, "
2556 "refusing to initialize\n",
2557 dom_sid_string(talloc_tos(),
2558 &domain->sid),
2559 domain->name,
2560 dom_sid_string(talloc_tos(),
2561 lsa_info->account_domain.sid)));
2562 TALLOC_FREE(cli);
2563 TALLOC_FREE(mem_ctx);
2564 return;
2566 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2570 done:
2572 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2573 domain->name, domain->native_mode ? "" : "NOT "));
2575 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2576 domain->name, domain->active_directory ? "" : "NOT "));
2578 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2580 TALLOC_FREE(cli);
2582 TALLOC_FREE(mem_ctx);
2584 domain->initialized = True;
2587 /**********************************************************************
2588 Set the domain_flags (trust attributes, domain operating modes, etc...
2589 ***********************************************************************/
2591 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2593 if (IS_DC) {
2595 * On a DC we loaded all trusts
2596 * from configuration and never learn
2597 * new domains.
2599 return;
2602 /* we always have to contact our primary domain */
2604 if ( domain->primary || domain->internal) {
2605 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2606 "primary or internal domain\n"));
2607 set_dc_type_and_flags_connect( domain );
2608 return;
2611 /* Use our DC to get the information if possible */
2613 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2614 /* Otherwise, fallback to contacting the
2615 domain directly */
2616 set_dc_type_and_flags_connect( domain );
2619 return;
2624 /**********************************************************************
2625 ***********************************************************************/
2627 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2628 struct netlogon_creds_cli_context **ppdc)
2630 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2631 struct rpc_pipe_client *netlogon_pipe;
2633 *ppdc = NULL;
2635 if ((!IS_DC) && (!domain->primary)) {
2636 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2639 if (domain->conn.netlogon_creds_ctx != NULL) {
2640 *ppdc = domain->conn.netlogon_creds_ctx;
2641 return NT_STATUS_OK;
2644 result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2645 if (!NT_STATUS_IS_OK(result)) {
2646 return result;
2649 return NT_STATUS_OK;
2652 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2653 bool need_rw_dc,
2654 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2656 struct winbindd_cm_conn *conn;
2657 NTSTATUS status, result;
2658 struct netlogon_creds_cli_context *p_creds;
2659 struct cli_credentials *creds = NULL;
2660 bool retry = false; /* allow one retry attempt for expired session */
2662 if (sid_check_is_our_sam(&domain->sid)) {
2663 if (domain->rodc == false || need_rw_dc == false) {
2664 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2668 if (IS_AD_DC) {
2670 * In theory we should not use SAMR within
2671 * winbindd at all, but that's a larger task to
2672 * remove this and avoid breaking existing
2673 * setups.
2675 * At least as AD DC we have the restriction
2676 * to avoid SAMR against trusted domains,
2677 * as there're no existing setups.
2679 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2682 retry:
2683 status = init_dc_connection_rpc(domain, need_rw_dc);
2684 if (!NT_STATUS_IS_OK(status)) {
2685 return status;
2688 conn = &domain->conn;
2690 if (rpccli_is_connected(conn->samr_pipe)) {
2691 goto done;
2694 TALLOC_FREE(conn->samr_pipe);
2697 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2698 * sign and sealed pipe using the machine account password by
2699 * preference. If we can't - try schannel, if that fails, try
2700 * anonymous.
2703 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2704 if (!NT_STATUS_IS_OK(result)) {
2705 DEBUG(10, ("cm_connect_sam: No user available for "
2706 "domain %s, trying schannel\n", domain->name));
2707 goto schannel;
2710 if (cli_credentials_is_anonymous(creds)) {
2711 goto anonymous;
2715 * We have an authenticated connection. Use a SPNEGO
2716 * authenticated SAMR pipe with sign & seal.
2718 status = cli_rpc_pipe_open_with_creds(conn->cli,
2719 &ndr_table_samr,
2720 NCACN_NP,
2721 DCERPC_AUTH_TYPE_SPNEGO,
2722 conn->auth_level,
2723 smbXcli_conn_remote_name(conn->cli->conn),
2724 creds,
2725 &conn->samr_pipe);
2727 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2728 && !retry) {
2729 invalidate_cm_connection(domain);
2730 retry = true;
2731 goto retry;
2734 if (!NT_STATUS_IS_OK(status)) {
2735 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2736 "pipe for domain %s using NTLMSSP "
2737 "authenticated pipe: user %s. Error was "
2738 "%s\n", domain->name,
2739 cli_credentials_get_unparsed_name(creds, talloc_tos()),
2740 nt_errstr(status)));
2741 goto schannel;
2744 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2745 "domain %s using NTLMSSP authenticated "
2746 "pipe: user %s\n", domain->name,
2747 cli_credentials_get_unparsed_name(creds, talloc_tos())));
2749 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2750 conn->samr_pipe->desthost,
2751 SEC_FLAG_MAXIMUM_ALLOWED,
2752 &conn->sam_connect_handle,
2753 &result);
2755 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2756 invalidate_cm_connection(domain);
2757 TALLOC_FREE(conn->samr_pipe);
2758 retry = true;
2759 goto retry;
2762 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2763 goto open_domain;
2765 if (NT_STATUS_IS_OK(status)) {
2766 status = result;
2769 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2770 "failed for domain %s, error was %s. Trying schannel\n",
2771 domain->name, nt_errstr(status) ));
2772 TALLOC_FREE(conn->samr_pipe);
2774 schannel:
2776 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2778 status = cm_get_schannel_creds(domain, &p_creds);
2779 if (!NT_STATUS_IS_OK(status)) {
2780 /* If this call fails - conn->cli can now be NULL ! */
2781 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2782 "for domain %s (error %s), trying anon\n",
2783 domain->name,
2784 nt_errstr(status) ));
2785 goto anonymous;
2787 TALLOC_FREE(creds);
2788 status = cli_rpc_pipe_open_schannel_with_creds(
2789 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2790 &conn->samr_pipe);
2792 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2793 && !retry) {
2794 invalidate_cm_connection(domain);
2795 retry = true;
2796 goto retry;
2799 if (!NT_STATUS_IS_OK(status)) {
2800 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2801 "domain %s using schannel. Error was %s\n",
2802 domain->name, nt_errstr(status) ));
2803 goto anonymous;
2805 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2806 "schannel.\n", domain->name ));
2808 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2809 conn->samr_pipe->desthost,
2810 SEC_FLAG_MAXIMUM_ALLOWED,
2811 &conn->sam_connect_handle,
2812 &result);
2814 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2815 invalidate_cm_connection(domain);
2816 TALLOC_FREE(conn->samr_pipe);
2817 retry = true;
2818 goto retry;
2821 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2822 goto open_domain;
2824 if (NT_STATUS_IS_OK(status)) {
2825 status = result;
2827 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2828 "for domain %s, error was %s. Trying anonymous\n",
2829 domain->name, nt_errstr(status) ));
2830 TALLOC_FREE(conn->samr_pipe);
2832 anonymous:
2834 /* Finally fall back to anonymous. */
2835 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2836 status = NT_STATUS_DOWNGRADE_DETECTED;
2837 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2838 "without connection level security, "
2839 "must set 'winbind sealed pipes = false' and "
2840 "'require strong key = false' to proceed: %s\n",
2841 domain->name, nt_errstr(status)));
2842 goto done;
2844 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2845 &conn->samr_pipe);
2847 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2848 && !retry) {
2849 invalidate_cm_connection(domain);
2850 retry = true;
2851 goto retry;
2854 if (!NT_STATUS_IS_OK(status)) {
2855 goto done;
2858 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2859 conn->samr_pipe->desthost,
2860 SEC_FLAG_MAXIMUM_ALLOWED,
2861 &conn->sam_connect_handle,
2862 &result);
2864 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2865 invalidate_cm_connection(domain);
2866 TALLOC_FREE(conn->samr_pipe);
2867 retry = true;
2868 goto retry;
2871 if (!NT_STATUS_IS_OK(status)) {
2872 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2873 "for domain %s Error was %s\n",
2874 domain->name, nt_errstr(status) ));
2875 goto done;
2877 if (!NT_STATUS_IS_OK(result)) {
2878 status = result;
2879 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2880 "for domain %s Error was %s\n",
2881 domain->name, nt_errstr(result)));
2882 goto done;
2885 open_domain:
2886 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2887 mem_ctx,
2888 &conn->sam_connect_handle,
2889 SEC_FLAG_MAXIMUM_ALLOWED,
2890 &domain->sid,
2891 &conn->sam_domain_handle,
2892 &result);
2893 if (!NT_STATUS_IS_OK(status)) {
2894 goto done;
2897 status = result;
2898 done:
2900 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2902 * if we got access denied, we might just have no access rights
2903 * to talk to the remote samr server server (e.g. when we are a
2904 * PDC and we are connecting a w2k8 pdc via an interdomain
2905 * trust). In that case do not invalidate the whole connection
2906 * stack
2908 TALLOC_FREE(conn->samr_pipe);
2909 ZERO_STRUCT(conn->sam_domain_handle);
2910 return status;
2911 } else if (!NT_STATUS_IS_OK(status)) {
2912 invalidate_cm_connection(domain);
2913 return status;
2916 *cli = conn->samr_pipe;
2917 *sam_handle = conn->sam_domain_handle;
2918 return status;
2921 /**********************************************************************
2922 open an schanneld ncacn_ip_tcp connection to LSA
2923 ***********************************************************************/
2925 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2926 TALLOC_CTX *mem_ctx,
2927 struct rpc_pipe_client **cli)
2929 struct winbindd_cm_conn *conn;
2930 struct netlogon_creds_cli_context *p_creds = NULL;
2931 NTSTATUS status;
2933 DEBUG(10,("cm_connect_lsa_tcp\n"));
2935 status = init_dc_connection_rpc(domain, false);
2936 if (!NT_STATUS_IS_OK(status)) {
2937 return status;
2940 conn = &domain->conn;
2943 * rpccli_is_connected handles more error cases
2945 if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2946 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2947 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2948 goto done;
2951 TALLOC_FREE(conn->lsa_pipe_tcp);
2953 status = cm_get_schannel_creds(domain, &p_creds);
2954 if (!NT_STATUS_IS_OK(status)) {
2955 goto done;
2958 status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
2959 &ndr_table_lsarpc,
2960 NCACN_IP_TCP,
2961 p_creds,
2962 &conn->lsa_pipe_tcp);
2963 if (!NT_STATUS_IS_OK(status)) {
2964 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2965 nt_errstr(status)));
2966 goto done;
2969 done:
2970 if (!NT_STATUS_IS_OK(status)) {
2971 TALLOC_FREE(conn->lsa_pipe_tcp);
2972 return status;
2975 *cli = conn->lsa_pipe_tcp;
2977 return status;
2980 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2981 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2983 struct winbindd_cm_conn *conn;
2984 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2985 struct netlogon_creds_cli_context *p_creds;
2986 struct cli_credentials *creds = NULL;
2987 bool retry = false; /* allow one retry attempt for expired session */
2989 retry:
2990 result = init_dc_connection_rpc(domain, false);
2991 if (!NT_STATUS_IS_OK(result))
2992 return result;
2994 conn = &domain->conn;
2996 if (rpccli_is_connected(conn->lsa_pipe)) {
2997 goto done;
3000 TALLOC_FREE(conn->lsa_pipe);
3002 if (IS_AD_DC) {
3004 * Make sure we only use schannel as AD DC.
3006 goto schannel;
3009 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
3010 if (!NT_STATUS_IS_OK(result)) {
3011 DEBUG(10, ("cm_connect_lsa: No user available for "
3012 "domain %s, trying schannel\n", domain->name));
3013 goto schannel;
3016 if (cli_credentials_is_anonymous(creds)) {
3017 goto anonymous;
3021 * We have an authenticated connection. Use a SPNEGO
3022 * authenticated LSA pipe with sign & seal.
3024 result = cli_rpc_pipe_open_with_creds
3025 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
3026 DCERPC_AUTH_TYPE_SPNEGO,
3027 conn->auth_level,
3028 smbXcli_conn_remote_name(conn->cli->conn),
3029 creds,
3030 &conn->lsa_pipe);
3032 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3033 && !retry) {
3034 invalidate_cm_connection(domain);
3035 retry = true;
3036 goto retry;
3039 if (!NT_STATUS_IS_OK(result)) {
3040 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3041 "domain %s using NTLMSSP authenticated pipe: user "
3042 "%s. Error was %s. Trying schannel.\n",
3043 domain->name,
3044 cli_credentials_get_unparsed_name(creds, talloc_tos()),
3045 nt_errstr(result)));
3046 goto schannel;
3049 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3050 "NTLMSSP authenticated pipe: user %s\n",
3051 domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3053 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3054 SEC_FLAG_MAXIMUM_ALLOWED,
3055 &conn->lsa_policy);
3056 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3057 invalidate_cm_connection(domain);
3058 TALLOC_FREE(conn->lsa_pipe);
3059 retry = true;
3060 goto retry;
3063 if (NT_STATUS_IS_OK(result)) {
3064 goto done;
3067 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3068 "schannel\n"));
3070 TALLOC_FREE(conn->lsa_pipe);
3072 schannel:
3074 /* Fall back to schannel if it's a W2K pre-SP1 box. */
3076 result = cm_get_schannel_creds(domain, &p_creds);
3077 if (!NT_STATUS_IS_OK(result)) {
3078 /* If this call fails - conn->cli can now be NULL ! */
3079 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3080 "for domain %s (error %s), trying anon\n",
3081 domain->name,
3082 nt_errstr(result) ));
3083 goto anonymous;
3086 TALLOC_FREE(creds);
3087 result = cli_rpc_pipe_open_schannel_with_creds(
3088 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3089 &conn->lsa_pipe);
3091 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3092 && !retry) {
3093 invalidate_cm_connection(domain);
3094 retry = true;
3095 goto retry;
3098 if (!NT_STATUS_IS_OK(result)) {
3099 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3100 "domain %s using schannel. Error was %s\n",
3101 domain->name, nt_errstr(result) ));
3102 goto anonymous;
3104 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3105 "schannel.\n", domain->name ));
3107 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3108 SEC_FLAG_MAXIMUM_ALLOWED,
3109 &conn->lsa_policy);
3111 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3112 invalidate_cm_connection(domain);
3113 TALLOC_FREE(conn->lsa_pipe);
3114 retry = true;
3115 goto retry;
3118 if (NT_STATUS_IS_OK(result)) {
3119 goto done;
3122 if (IS_AD_DC) {
3124 * Make sure we only use schannel as AD DC.
3126 goto done;
3129 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3130 "anonymous\n"));
3132 TALLOC_FREE(conn->lsa_pipe);
3134 anonymous:
3136 if (IS_AD_DC) {
3138 * Make sure we only use schannel as AD DC.
3140 goto done;
3143 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3144 result = NT_STATUS_DOWNGRADE_DETECTED;
3145 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3146 "without connection level security, "
3147 "must set 'winbind sealed pipes = false' and "
3148 "'require strong key = false' to proceed: %s\n",
3149 domain->name, nt_errstr(result)));
3150 goto done;
3153 result = cli_rpc_pipe_open_noauth(conn->cli,
3154 &ndr_table_lsarpc,
3155 &conn->lsa_pipe);
3157 if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3158 && !retry) {
3159 invalidate_cm_connection(domain);
3160 retry = true;
3161 goto retry;
3164 if (!NT_STATUS_IS_OK(result)) {
3165 goto done;
3168 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3169 SEC_FLAG_MAXIMUM_ALLOWED,
3170 &conn->lsa_policy);
3172 if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3173 invalidate_cm_connection(domain);
3174 TALLOC_FREE(conn->lsa_pipe);
3175 retry = true;
3176 goto retry;
3179 done:
3180 if (!NT_STATUS_IS_OK(result)) {
3181 invalidate_cm_connection(domain);
3182 return result;
3185 *cli = conn->lsa_pipe;
3186 *lsa_policy = conn->lsa_policy;
3187 return result;
3190 /****************************************************************************
3191 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3192 ****************************************************************************/
3194 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3195 TALLOC_CTX *mem_ctx,
3196 struct rpc_pipe_client **cli,
3197 struct policy_handle *lsa_policy)
3199 NTSTATUS status;
3201 if (domain->can_do_ncacn_ip_tcp) {
3202 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3203 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3204 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3205 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3206 invalidate_cm_connection(domain);
3207 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3209 if (NT_STATUS_IS_OK(status)) {
3210 return status;
3214 * we tried twice to connect via ncan_ip_tcp and schannel and
3215 * failed - maybe it is a trusted domain we can't connect to ?
3216 * do not try tcp next time - gd
3218 * This also prevents NETLOGON over TCP
3220 domain->can_do_ncacn_ip_tcp = false;
3223 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3225 return status;
3228 /****************************************************************************
3229 Open the netlogon pipe to this DC.
3230 ****************************************************************************/
3232 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3233 enum dcerpc_transport_t transport,
3234 struct rpc_pipe_client **cli)
3236 struct messaging_context *msg_ctx = server_messaging_context();
3237 struct winbindd_cm_conn *conn;
3238 NTSTATUS result;
3239 enum netr_SchannelType sec_chan_type;
3240 struct cli_credentials *creds = NULL;
3242 *cli = NULL;
3244 if (IS_AD_DC) {
3245 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3247 * Make sure we don't even try to
3248 * connect to a foreign domain
3249 * without a direct outbound trust.
3251 return NT_STATUS_NO_TRUST_LSA_SECRET;
3255 result = init_dc_connection_rpc(domain, domain->rodc);
3256 if (!NT_STATUS_IS_OK(result)) {
3257 return result;
3260 conn = &domain->conn;
3262 if (rpccli_is_connected(conn->netlogon_pipe)) {
3263 *cli = conn->netlogon_pipe;
3264 return NT_STATUS_OK;
3267 TALLOC_FREE(conn->netlogon_pipe);
3268 TALLOC_FREE(conn->netlogon_creds_ctx);
3270 result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3271 if (!NT_STATUS_IS_OK(result)) {
3272 DBG_DEBUG("No user available for domain %s when trying "
3273 "schannel\n", domain->name);
3274 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3277 if (cli_credentials_is_anonymous(creds)) {
3278 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3279 "unable to make get NETLOGON credentials\n",
3280 domain->name);
3281 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3284 sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3285 if (sec_chan_type == SEC_CHAN_NULL) {
3286 if (transport == NCACN_IP_TCP) {
3287 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3288 "for %s, deny NCACN_IP_TCP and let the "
3289 "caller fallback to NCACN_NP.\n",
3290 domain->name);
3291 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3294 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3295 "fallback to noauth on NCACN_NP.\n",
3296 domain->name);
3298 result = cli_rpc_pipe_open_noauth_transport(
3299 conn->cli,
3300 transport,
3301 &ndr_table_netlogon,
3302 &conn->netlogon_pipe);
3303 if (!NT_STATUS_IS_OK(result)) {
3304 invalidate_cm_connection(domain);
3305 return result;
3308 *cli = conn->netlogon_pipe;
3309 return NT_STATUS_OK;
3312 result = rpccli_create_netlogon_creds_ctx(creds,
3313 domain->dcname,
3314 msg_ctx,
3315 domain,
3316 &conn->netlogon_creds_ctx);
3317 if (!NT_STATUS_IS_OK(result)) {
3318 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3319 "unable to create NETLOGON credentials: %s\n",
3320 domain->name, nt_errstr(result)));
3321 return result;
3324 result = rpccli_connect_netlogon(
3325 conn->cli, transport,
3326 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3327 &conn->netlogon_pipe);
3328 if (!NT_STATUS_IS_OK(result)) {
3329 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3330 nt_errstr(result));
3331 return result;
3334 *cli = conn->netlogon_pipe;
3335 return NT_STATUS_OK;
3338 /****************************************************************************
3339 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3340 ****************************************************************************/
3342 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3343 struct rpc_pipe_client **cli)
3345 NTSTATUS status;
3347 status = init_dc_connection_rpc(domain, domain->rodc);
3348 if (!NT_STATUS_IS_OK(status)) {
3349 return status;
3352 if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3353 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3354 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3355 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3356 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3357 invalidate_cm_connection(domain);
3358 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3360 if (NT_STATUS_IS_OK(status)) {
3361 return status;
3365 * we tried twice to connect via ncan_ip_tcp and schannel and
3366 * failed - maybe it is a trusted domain we can't connect to ?
3367 * do not try tcp next time - gd
3369 * This also prevents LSA over TCP
3371 domain->can_do_ncacn_ip_tcp = false;
3374 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3375 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3377 * SMB2 session expired, needs reauthentication. Drop
3378 * connection and retry.
3380 invalidate_cm_connection(domain);
3381 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3384 return status;
3387 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3388 struct rpc_pipe_client **cli,
3389 struct netlogon_creds_cli_context **ppdc)
3391 NTSTATUS status;
3393 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3394 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3397 status = cm_connect_netlogon(domain, cli);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 return status;
3402 if (domain->conn.netlogon_creds_ctx == NULL) {
3403 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3406 *ppdc = domain->conn.netlogon_creds_ctx;
3407 return NT_STATUS_OK;
3410 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3411 void *private_data,
3412 uint32_t msg_type,
3413 struct server_id server_id,
3414 DATA_BLOB *data)
3416 struct winbindd_domain *domain;
3417 char *freeit = NULL;
3418 char *addr;
3420 if ((data == NULL)
3421 || (data->data == NULL)
3422 || (data->length == 0)
3423 || (data->data[data->length-1] != '\0')) {
3424 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3425 "string\n"));
3426 return;
3429 addr = (char *)data->data;
3430 DEBUG(10, ("IP %s dropped\n", addr));
3432 if (!is_ipaddress(addr)) {
3433 char *slash;
3435 * Some code sends us ip addresses with the /netmask
3436 * suffix
3438 slash = strchr(addr, '/');
3439 if (slash == NULL) {
3440 DEBUG(1, ("invalid msg_ip_dropped message: %s",
3441 addr));
3442 return;
3444 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3445 if (freeit == NULL) {
3446 DEBUG(1, ("talloc failed\n"));
3447 return;
3449 addr = freeit;
3450 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3453 for (domain = domain_list(); domain != NULL; domain = domain->next) {
3454 char sockaddr[INET6_ADDRSTRLEN];
3456 if (!cli_state_is_connected(domain->conn.cli)) {
3457 continue;
3460 print_sockaddr(sockaddr, sizeof(sockaddr),
3461 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3463 if (strequal(sockaddr, addr)) {
3464 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3467 TALLOC_FREE(freeit);