locking: use correct conversion specifier for printing variables
[Samba.git] / source3 / winbindd / winbindd_cm.c
bloba8ace52472edc17903f25d56de7a5d82f7eeb325
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 "lib/param/loadparm.h"
82 #include "libcli/auth/netlogon_creds_cli.h"
83 #include "auth.h"
84 #include "rpc_server/rpc_ncacn_np.h"
86 #undef DBGC_CLASS
87 #define DBGC_CLASS DBGC_WINBIND
89 struct dc_name_ip {
90 fstring name;
91 struct sockaddr_storage ss;
94 extern struct winbindd_methods reconnect_methods;
95 extern bool override_logfile;
97 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
98 static void set_dc_type_and_flags( struct winbindd_domain *domain );
99 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
100 struct dc_name_ip **dcs, int *num_dcs);
102 /****************************************************************
103 Child failed to find DC's. Reschedule check.
104 ****************************************************************/
106 static void msg_failed_to_go_online(struct messaging_context *msg,
107 void *private_data,
108 uint32_t msg_type,
109 struct server_id server_id,
110 DATA_BLOB *data)
112 struct winbindd_domain *domain;
113 const char *domainname = (const char *)data->data;
115 if (data->data == NULL || data->length == 0) {
116 return;
119 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
121 for (domain = domain_list(); domain; domain = domain->next) {
122 if (domain->internal) {
123 continue;
126 if (strequal(domain->name, domainname)) {
127 if (domain->online) {
128 /* We're already online, ignore. */
129 DEBUG(5,("msg_fail_to_go_online: domain %s "
130 "already online.\n", domainname));
131 continue;
134 /* Reschedule the online check. */
135 set_domain_offline(domain);
136 break;
141 /****************************************************************
142 Actually cause a reconnect from a message.
143 ****************************************************************/
145 static void msg_try_to_go_online(struct messaging_context *msg,
146 void *private_data,
147 uint32_t msg_type,
148 struct server_id server_id,
149 DATA_BLOB *data)
151 struct winbindd_domain *domain;
152 const char *domainname = (const char *)data->data;
154 if (data->data == NULL || data->length == 0) {
155 return;
158 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
160 for (domain = domain_list(); domain; domain = domain->next) {
161 if (domain->internal) {
162 continue;
165 if (strequal(domain->name, domainname)) {
167 if (domain->online) {
168 /* We're already online, ignore. */
169 DEBUG(5,("msg_try_to_go_online: domain %s "
170 "already online.\n", domainname));
171 continue;
174 /* This call takes care of setting the online
175 flag to true if we connected, or re-adding
176 the offline handler if false. Bypasses online
177 check so always does network calls. */
179 init_dc_connection_network(domain);
180 break;
185 /****************************************************************
186 Fork a child to try and contact a DC. Do this as contacting a
187 DC requires blocking lookups and we don't want to block our
188 parent.
189 ****************************************************************/
191 static bool fork_child_dc_connect(struct winbindd_domain *domain)
193 struct dc_name_ip *dcs = NULL;
194 int num_dcs = 0;
195 TALLOC_CTX *mem_ctx = NULL;
196 pid_t parent_pid = getpid();
197 char *lfile = NULL;
198 NTSTATUS status;
200 if (domain->dc_probe_pid != (pid_t)-1) {
202 * We might already have a DC probe
203 * child working, check.
205 if (process_exists_by_pid(domain->dc_probe_pid)) {
206 DEBUG(10,("fork_child_dc_connect: pid %u already "
207 "checking for DC's.\n",
208 (unsigned int)domain->dc_probe_pid));
209 return true;
211 domain->dc_probe_pid = (pid_t)-1;
214 domain->dc_probe_pid = fork();
216 if (domain->dc_probe_pid == (pid_t)-1) {
217 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
218 return False;
221 if (domain->dc_probe_pid != (pid_t)0) {
222 /* Parent */
223 messaging_register(winbind_messaging_context(), NULL,
224 MSG_WINBIND_TRY_TO_GO_ONLINE,
225 msg_try_to_go_online);
226 messaging_register(winbind_messaging_context(), NULL,
227 MSG_WINBIND_FAILED_TO_GO_ONLINE,
228 msg_failed_to_go_online);
229 return True;
232 /* Child. */
234 /* Leave messages blocked - we will never process one. */
236 if (!override_logfile) {
237 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
238 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
239 _exit(1);
243 status = winbindd_reinit_after_fork(NULL, lfile);
244 if (!NT_STATUS_IS_OK(status)) {
245 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
246 nt_errstr(status)));
247 messaging_send_buf(winbind_messaging_context(),
248 pid_to_procid(parent_pid),
249 MSG_WINBIND_FAILED_TO_GO_ONLINE,
250 (const uint8_t *)domain->name,
251 strlen(domain->name)+1);
252 _exit(1);
254 SAFE_FREE(lfile);
256 mem_ctx = talloc_init("fork_child_dc_connect");
257 if (!mem_ctx) {
258 DEBUG(0,("talloc_init failed.\n"));
259 messaging_send_buf(winbind_messaging_context(),
260 pid_to_procid(parent_pid),
261 MSG_WINBIND_FAILED_TO_GO_ONLINE,
262 (const uint8_t *)domain->name,
263 strlen(domain->name)+1);
264 _exit(1);
267 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
268 /* Still offline ? Can't find DC's. */
269 messaging_send_buf(winbind_messaging_context(),
270 pid_to_procid(parent_pid),
271 MSG_WINBIND_FAILED_TO_GO_ONLINE,
272 (const uint8_t *)domain->name,
273 strlen(domain->name)+1);
274 _exit(0);
277 /* We got a DC. Send a message to our parent to get it to
278 try and do the same. */
280 messaging_send_buf(winbind_messaging_context(),
281 pid_to_procid(parent_pid),
282 MSG_WINBIND_TRY_TO_GO_ONLINE,
283 (const uint8_t *)domain->name,
284 strlen(domain->name)+1);
285 _exit(0);
288 /****************************************************************
289 Handler triggered if we're offline to try and detect a DC.
290 ****************************************************************/
292 static void check_domain_online_handler(struct tevent_context *ctx,
293 struct tevent_timer *te,
294 struct timeval now,
295 void *private_data)
297 struct winbindd_domain *domain =
298 (struct winbindd_domain *)private_data;
300 DEBUG(10,("check_domain_online_handler: called for domain "
301 "%s (online = %s)\n", domain->name,
302 domain->online ? "True" : "False" ));
304 TALLOC_FREE(domain->check_online_event);
306 /* Are we still in "startup" mode ? */
308 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
309 /* No longer in "startup" mode. */
310 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
311 domain->name ));
312 domain->startup = False;
315 /* We've been told to stay offline, so stay
316 that way. */
318 if (get_global_winbindd_state_offline()) {
319 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
320 domain->name ));
321 return;
324 /* Fork a child to test if it can contact a DC.
325 If it can then send ourselves a message to
326 cause a reconnect. */
328 fork_child_dc_connect(domain);
331 /****************************************************************
332 If we're still offline setup the timeout check.
333 ****************************************************************/
335 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
337 int wbr = lp_winbind_reconnect_delay();
339 if (domain->startup) {
340 domain->check_online_timeout = 10;
341 } else if (domain->check_online_timeout < wbr) {
342 domain->check_online_timeout = wbr;
346 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
347 void *private_data,
348 uint32_t msg_type,
349 struct server_id server_id,
350 DATA_BLOB *data)
352 const char *domain_name = (const char *)data->data;
353 struct winbindd_domain *domain;
355 domain = find_domain_from_name_noinit(domain_name);
356 if (domain == NULL) {
357 return;
360 domain->online = false;
362 DEBUG(10, ("Domain %s is marked as offline now.\n",
363 domain_name));
366 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
367 void *private_data,
368 uint32_t msg_type,
369 struct server_id server_id,
370 DATA_BLOB *data)
372 const char *domain_name = (const char *)data->data;
373 struct winbindd_domain *domain;
375 domain = find_domain_from_name_noinit(domain_name);
376 if (domain == NULL) {
377 return;
380 domain->online = true;
382 DEBUG(10, ("Domain %s is marked as online now.\n",
383 domain_name));
386 /****************************************************************
387 Set domain offline and also add handler to put us back online
388 if we detect a DC.
389 ****************************************************************/
391 void set_domain_offline(struct winbindd_domain *domain)
393 pid_t parent_pid = getppid();
395 DEBUG(10,("set_domain_offline: called for domain %s\n",
396 domain->name ));
398 TALLOC_FREE(domain->check_online_event);
400 if (domain->internal) {
401 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
402 domain->name ));
403 return;
406 domain->online = False;
408 /* Offline domains are always initialized. They're
409 re-initialized when they go back online. */
411 domain->initialized = True;
413 /* We only add the timeout handler that checks and
414 allows us to go back online when we've not
415 been told to remain offline. */
417 if (get_global_winbindd_state_offline()) {
418 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
419 domain->name ));
420 return;
423 /* If we're in startup mode, check again in 10 seconds, not in
424 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
426 calc_new_online_timeout_check(domain);
428 domain->check_online_event = tevent_add_timer(winbind_event_context(),
429 NULL,
430 timeval_current_ofs(domain->check_online_timeout,0),
431 check_domain_online_handler,
432 domain);
434 /* The above *has* to succeed for winbindd to work. */
435 if (!domain->check_online_event) {
436 smb_panic("set_domain_offline: failed to add online handler");
439 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
440 domain->name ));
442 /* Send a message to the parent that the domain is offline. */
443 if (parent_pid > 1 && !domain->internal) {
444 messaging_send_buf(winbind_messaging_context(),
445 pid_to_procid(parent_pid),
446 MSG_WINBIND_DOMAIN_OFFLINE,
447 (uint8 *)domain->name,
448 strlen(domain->name) + 1);
451 /* Send an offline message to the idmap child when our
452 primary domain goes offline */
454 if ( domain->primary ) {
455 struct winbindd_child *idmap = idmap_child();
457 if ( idmap->pid != 0 ) {
458 messaging_send_buf(winbind_messaging_context(),
459 pid_to_procid(idmap->pid),
460 MSG_WINBIND_OFFLINE,
461 (const uint8_t *)domain->name,
462 strlen(domain->name)+1);
466 return;
469 /****************************************************************
470 Set domain online - if allowed.
471 ****************************************************************/
473 static void set_domain_online(struct winbindd_domain *domain)
475 pid_t parent_pid = getppid();
477 DEBUG(10,("set_domain_online: called for domain %s\n",
478 domain->name ));
480 if (domain->internal) {
481 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
482 domain->name ));
483 return;
486 if (get_global_winbindd_state_offline()) {
487 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
488 domain->name ));
489 return;
492 winbindd_set_locator_kdc_envs(domain);
494 /* If we are waiting to get a krb5 ticket, trigger immediately. */
495 ccache_regain_all_now();
497 /* Ok, we're out of any startup mode now... */
498 domain->startup = False;
500 if (domain->online == False) {
501 /* We were offline - now we're online. We default to
502 using the MS-RPC backend if we started offline,
503 and if we're going online for the first time we
504 should really re-initialize the backends and the
505 checks to see if we're talking to an AD or NT domain.
508 domain->initialized = False;
510 /* 'reconnect_methods' is the MS-RPC backend. */
511 if (domain->backend == &reconnect_methods) {
512 domain->backend = NULL;
516 /* Ensure we have no online timeout checks. */
517 domain->check_online_timeout = 0;
518 TALLOC_FREE(domain->check_online_event);
520 /* Ensure we ignore any pending child messages. */
521 messaging_deregister(winbind_messaging_context(),
522 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
523 messaging_deregister(winbind_messaging_context(),
524 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
526 domain->online = True;
528 /* Send a message to the parent that the domain is online. */
529 if (parent_pid > 1 && !domain->internal) {
530 messaging_send_buf(winbind_messaging_context(),
531 pid_to_procid(parent_pid),
532 MSG_WINBIND_DOMAIN_ONLINE,
533 (uint8 *)domain->name,
534 strlen(domain->name) + 1);
537 /* Send an online message to the idmap child when our
538 primary domain comes online */
540 if ( domain->primary ) {
541 struct winbindd_child *idmap = idmap_child();
543 if ( idmap->pid != 0 ) {
544 messaging_send_buf(winbind_messaging_context(),
545 pid_to_procid(idmap->pid),
546 MSG_WINBIND_ONLINE,
547 (const uint8_t *)domain->name,
548 strlen(domain->name)+1);
552 return;
555 /****************************************************************
556 Requested to set a domain online.
557 ****************************************************************/
559 void set_domain_online_request(struct winbindd_domain *domain)
561 struct timeval tev;
563 DEBUG(10,("set_domain_online_request: called for domain %s\n",
564 domain->name ));
566 if (get_global_winbindd_state_offline()) {
567 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
568 domain->name ));
569 return;
572 if (domain->internal) {
573 DEBUG(10, ("set_domain_online_request: Internal domains are "
574 "always online\n"));
575 return;
578 /* We've been told it's safe to go online and
579 try and connect to a DC. But I don't believe it
580 because network manager seems to lie.
581 Wait at least 5 seconds. Heuristics suck... */
584 GetTimeOfDay(&tev);
586 /* Go into "startup" mode again. */
587 domain->startup_time = time_mono(NULL);
588 domain->startup = True;
590 tev.tv_sec += 5;
592 if (!domain->check_online_event) {
593 /* If we've come from being globally offline we
594 don't have a check online event handler set.
595 We need to add one now we're trying to go
596 back online. */
598 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
599 domain->name ));
602 TALLOC_FREE(domain->check_online_event);
604 domain->check_online_event = tevent_add_timer(winbind_event_context(),
605 NULL,
606 tev,
607 check_domain_online_handler,
608 domain);
610 /* The above *has* to succeed for winbindd to work. */
611 if (!domain->check_online_event) {
612 smb_panic("set_domain_online_request: failed to add online handler");
616 /****************************************************************
617 Add -ve connection cache entries for domain and realm.
618 ****************************************************************/
620 static void winbind_add_failed_connection_entry(
621 const struct winbindd_domain *domain,
622 const char *server,
623 NTSTATUS result)
625 add_failed_connection_entry(domain->name, server, result);
626 /* If this was the saf name for the last thing we talked to,
627 remove it. */
628 saf_delete(domain->name);
629 if (domain->alt_name != NULL) {
630 add_failed_connection_entry(domain->alt_name, server, result);
631 saf_delete(domain->alt_name);
633 winbindd_unset_locator_kdc_env(domain);
636 /* Choose between anonymous or authenticated connections. We need to use
637 an authenticated connection if DCs have the RestrictAnonymous registry
638 entry set > 0, or the "Additional restrictions for anonymous
639 connections" set in the win2k Local Security Policy.
641 Caller to free() result in domain, username, password
644 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
646 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
647 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
648 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
650 if (*username && **username) {
652 if (!*domain || !**domain)
653 *domain = smb_xstrdup(lp_workgroup());
655 if (!*password || !**password)
656 *password = smb_xstrdup("");
658 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
659 *domain, *username));
661 } else {
662 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
663 *username = smb_xstrdup("");
664 *domain = smb_xstrdup("");
665 *password = smb_xstrdup("");
669 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
670 fstring dcname,
671 struct sockaddr_storage *dc_ss)
673 struct winbindd_domain *our_domain = NULL;
674 struct rpc_pipe_client *netlogon_pipe = NULL;
675 NTSTATUS result;
676 WERROR werr;
677 TALLOC_CTX *mem_ctx;
678 unsigned int orig_timeout;
679 const char *tmp = NULL;
680 const char *p;
681 struct dcerpc_binding_handle *b;
683 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
684 * moment.... */
686 if (IS_DC) {
687 return False;
690 if (domain->primary) {
691 return False;
694 our_domain = find_our_domain();
696 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
697 return False;
700 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
701 if (!NT_STATUS_IS_OK(result)) {
702 talloc_destroy(mem_ctx);
703 return False;
706 b = netlogon_pipe->binding_handle;
708 /* This call can take a long time - allow the server to time out.
709 35 seconds should do it. */
711 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
713 if (our_domain->active_directory) {
714 struct netr_DsRGetDCNameInfo *domain_info = NULL;
716 result = dcerpc_netr_DsRGetDCName(b,
717 mem_ctx,
718 our_domain->dcname,
719 domain->name,
720 NULL,
721 NULL,
722 DS_RETURN_DNS_NAME,
723 &domain_info,
724 &werr);
725 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
726 tmp = talloc_strdup(
727 mem_ctx, domain_info->dc_unc);
728 if (tmp == NULL) {
729 DEBUG(0, ("talloc_strdup failed\n"));
730 talloc_destroy(mem_ctx);
731 return false;
733 if (domain->alt_name == NULL) {
734 domain->alt_name = talloc_strdup(domain,
735 domain_info->domain_name);
736 if (domain->alt_name == NULL) {
737 DEBUG(0, ("talloc_strdup failed\n"));
738 talloc_destroy(mem_ctx);
739 return false;
742 if (domain->forest_name == NULL) {
743 domain->forest_name = talloc_strdup(domain,
744 domain_info->forest_name);
745 if (domain->forest_name == NULL) {
746 DEBUG(0, ("talloc_strdup failed\n"));
747 talloc_destroy(mem_ctx);
748 return false;
752 } else {
753 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
754 our_domain->dcname,
755 domain->name,
756 &tmp,
757 &werr);
760 /* And restore our original timeout. */
761 rpccli_set_timeout(netlogon_pipe, orig_timeout);
763 if (!NT_STATUS_IS_OK(result)) {
764 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
765 nt_errstr(result)));
766 talloc_destroy(mem_ctx);
767 return false;
770 if (!W_ERROR_IS_OK(werr)) {
771 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
772 win_errstr(werr)));
773 talloc_destroy(mem_ctx);
774 return false;
777 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
778 p = strip_hostname(tmp);
780 fstrcpy(dcname, p);
782 talloc_destroy(mem_ctx);
784 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
786 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
787 return False;
790 return True;
794 * Helper function to assemble trust password and account name
796 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
797 char **machine_password,
798 char **machine_account,
799 char **machine_krb5_principal)
801 const char *account_name;
802 const char *name = NULL;
804 /* If we are a DC and this is not our own domain */
806 if (IS_DC) {
807 name = domain->name;
808 } else {
809 struct winbindd_domain *our_domain = find_our_domain();
811 if (!our_domain)
812 return NT_STATUS_INVALID_SERVER_STATE;
814 name = our_domain->name;
817 if (!get_trust_pw_clear(name, machine_password,
818 &account_name, NULL))
820 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
823 if ((machine_account != NULL) &&
824 (asprintf(machine_account, "%s$", account_name) == -1))
826 return NT_STATUS_NO_MEMORY;
829 /* For now assume our machine account only exists in our domain */
831 if (machine_krb5_principal != NULL)
833 struct winbindd_domain *our_domain = find_our_domain();
835 if (!our_domain) {
836 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
839 if (asprintf(machine_krb5_principal, "%s$@%s",
840 account_name, our_domain->alt_name) == -1)
842 return NT_STATUS_NO_MEMORY;
845 if (!strupper_m(*machine_krb5_principal)) {
846 SAFE_FREE(*machine_krb5_principal);
847 return NT_STATUS_INVALID_PARAMETER;
851 return NT_STATUS_OK;
854 /************************************************************************
855 Given a fd with a just-connected TCP connection to a DC, open a connection
856 to the pipe.
857 ************************************************************************/
859 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
860 const int sockfd,
861 const char *controller,
862 struct cli_state **cli,
863 bool *retry)
865 bool try_spnego = false;
866 bool try_ipc_auth = false;
867 char *machine_password = NULL;
868 char *machine_krb5_principal = NULL;
869 char *machine_account = NULL;
870 char *ipc_username = NULL;
871 char *ipc_domain = NULL;
872 char *ipc_password = NULL;
873 int flags = 0;
874 uint16_t sec_mode = 0;
876 struct named_mutex *mutex;
878 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
880 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
881 controller, domain->name ));
883 *retry = True;
885 mutex = grab_named_mutex(talloc_tos(), controller,
886 WINBIND_SERVER_MUTEX_WAIT_TIME);
887 if (mutex == NULL) {
888 close(sockfd);
889 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
890 controller));
891 result = NT_STATUS_POSSIBLE_DEADLOCK;
892 goto done;
895 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
897 *cli = cli_state_create(NULL, sockfd,
898 controller, domain->alt_name,
899 SMB_SIGNING_DEFAULT, flags);
900 if (*cli == NULL) {
901 close(sockfd);
902 DEBUG(1, ("Could not cli_initialize\n"));
903 result = NT_STATUS_NO_MEMORY;
904 goto done;
907 cli_set_timeout(*cli, 10000); /* 10 seconds */
909 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
910 lp_client_min_protocol(),
911 lp_client_max_protocol());
913 if (!NT_STATUS_IS_OK(result)) {
914 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
915 goto done;
918 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
919 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
920 try_spnego = true;
921 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
922 try_spnego = true;
925 if (!is_dc_trusted_domain_situation(domain->name) && try_spnego) {
926 result = get_trust_creds(domain, &machine_password,
927 &machine_account,
928 &machine_krb5_principal);
929 if (!NT_STATUS_IS_OK(result)) {
930 goto anon_fallback;
933 if (lp_security() == SEC_ADS) {
935 /* Try a krb5 session */
937 (*cli)->use_kerberos = True;
938 DEBUG(5, ("connecting to %s from %s with kerberos principal "
939 "[%s] and realm [%s]\n", controller, lp_netbios_name(),
940 machine_krb5_principal, domain->alt_name));
942 winbindd_set_locator_kdc_envs(domain);
944 result = cli_session_setup(*cli,
945 machine_krb5_principal,
946 machine_password,
947 strlen(machine_password)+1,
948 machine_password,
949 strlen(machine_password)+1,
950 lp_workgroup());
952 if (!NT_STATUS_IS_OK(result)) {
953 DEBUG(4,("failed kerberos session setup with %s\n",
954 nt_errstr(result)));
957 if (NT_STATUS_IS_OK(result)) {
958 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
959 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
960 if (!NT_STATUS_IS_OK(result)) {
961 goto done;
963 goto session_setup_done;
967 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
968 (*cli)->use_kerberos = False;
970 DEBUG(5, ("connecting to %s from %s with username "
971 "[%s]\\[%s]\n", controller, lp_netbios_name(),
972 lp_workgroup(), machine_account));
974 result = cli_session_setup(*cli,
975 machine_account,
976 machine_password,
977 strlen(machine_password)+1,
978 machine_password,
979 strlen(machine_password)+1,
980 lp_workgroup());
981 if (!NT_STATUS_IS_OK(result)) {
982 DEBUG(4, ("authenticated session setup failed with %s\n",
983 nt_errstr(result)));
986 if (NT_STATUS_IS_OK(result)) {
987 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
988 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
989 if (!NT_STATUS_IS_OK(result)) {
990 goto done;
992 goto session_setup_done;
996 /* Fall back to non-kerberos session setup with auth_user */
998 (*cli)->use_kerberos = False;
1000 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
1002 sec_mode = smb1cli_conn_server_security_mode((*cli)->conn);
1004 try_ipc_auth = false;
1005 if (try_spnego) {
1006 try_ipc_auth = true;
1007 } else if (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
1008 try_ipc_auth = true;
1011 if (try_ipc_auth && (strlen(ipc_username) > 0)) {
1013 /* Only try authenticated if we have a username */
1015 DEBUG(5, ("connecting to %s from %s with username "
1016 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1017 ipc_domain, ipc_username));
1019 if (NT_STATUS_IS_OK(cli_session_setup(
1020 *cli, ipc_username,
1021 ipc_password, strlen(ipc_password)+1,
1022 ipc_password, strlen(ipc_password)+1,
1023 ipc_domain))) {
1024 /* Successful logon with given username. */
1025 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
1026 if (!NT_STATUS_IS_OK(result)) {
1027 goto done;
1029 goto session_setup_done;
1030 } else {
1031 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
1032 ipc_domain, ipc_username ));
1036 anon_fallback:
1038 /* Fall back to anonymous connection, this might fail later */
1039 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
1040 "connection for DC %s\n",
1041 controller ));
1043 result = cli_session_setup(*cli, "", NULL, 0, NULL, 0, "");
1044 if (NT_STATUS_IS_OK(result)) {
1045 DEBUG(5, ("Connected anonymously\n"));
1046 result = cli_init_creds(*cli, "", "", "");
1047 if (!NT_STATUS_IS_OK(result)) {
1048 goto done;
1050 goto session_setup_done;
1053 /* We can't session setup */
1054 goto done;
1056 session_setup_done:
1059 * This should be a short term hack until
1060 * dynamic re-authentication is implemented.
1062 * See Bug 9175 - winbindd doesn't recover from
1063 * NT_STATUS_NETWORK_SESSION_EXPIRED
1065 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1066 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1069 /* cache the server name for later connections */
1071 saf_store(domain->name, controller);
1072 if (domain->alt_name && (*cli)->use_kerberos) {
1073 saf_store(domain->alt_name, controller);
1076 winbindd_set_locator_kdc_envs(domain);
1078 result = cli_tree_connect(*cli, "IPC$", "IPC", "", 0);
1080 if (!NT_STATUS_IS_OK(result)) {
1081 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1082 goto done;
1085 TALLOC_FREE(mutex);
1086 *retry = False;
1088 /* set the domain if empty; needed for schannel connections */
1089 if ( !(*cli)->domain[0] ) {
1090 result = cli_set_domain((*cli), domain->name);
1091 if (!NT_STATUS_IS_OK(result)) {
1092 SAFE_FREE(ipc_username);
1093 SAFE_FREE(ipc_domain);
1094 SAFE_FREE(ipc_password);
1095 return result;
1099 result = NT_STATUS_OK;
1101 done:
1102 TALLOC_FREE(mutex);
1103 SAFE_FREE(machine_account);
1104 SAFE_FREE(machine_password);
1105 SAFE_FREE(machine_krb5_principal);
1106 SAFE_FREE(ipc_username);
1107 SAFE_FREE(ipc_domain);
1108 SAFE_FREE(ipc_password);
1110 if (!NT_STATUS_IS_OK(result)) {
1111 winbind_add_failed_connection_entry(domain, controller, result);
1112 if ((*cli) != NULL) {
1113 cli_shutdown(*cli);
1114 *cli = NULL;
1118 return result;
1121 /*******************************************************************
1122 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1123 array.
1125 Keeps the list unique by not adding duplicate entries.
1127 @param[in] mem_ctx talloc memory context to allocate from
1128 @param[in] domain_name domain of the DC
1129 @param[in] dcname name of the DC to add to the list
1130 @param[in] pss Internet address and port pair to add to the list
1131 @param[in,out] dcs array of dc_name_ip structures to add to
1132 @param[in,out] num_dcs number of dcs returned in the dcs array
1133 @return true if the list was added to, false otherwise
1134 *******************************************************************/
1136 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1137 const char *dcname, struct sockaddr_storage *pss,
1138 struct dc_name_ip **dcs, int *num)
1140 int i = 0;
1142 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1143 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1144 return False;
1147 /* Make sure there's no duplicates in the list */
1148 for (i=0; i<*num; i++)
1149 if (sockaddr_equal(
1150 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1151 (struct sockaddr *)(void *)pss))
1152 return False;
1154 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1156 if (*dcs == NULL)
1157 return False;
1159 fstrcpy((*dcs)[*num].name, dcname);
1160 (*dcs)[*num].ss = *pss;
1161 *num += 1;
1162 return True;
1165 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1166 struct sockaddr_storage *pss, uint16 port,
1167 struct sockaddr_storage **addrs, int *num)
1169 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1171 if (*addrs == NULL) {
1172 *num = 0;
1173 return False;
1176 (*addrs)[*num] = *pss;
1177 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1179 *num += 1;
1180 return True;
1183 /*******************************************************************
1184 convert an ip to a name
1185 *******************************************************************/
1187 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1188 const struct winbindd_domain *domain,
1189 struct sockaddr_storage *pss,
1190 char **name)
1192 struct ip_service ip_list;
1193 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1194 NTSTATUS status;
1195 const char *dc_name;
1196 fstring nbtname;
1198 ip_list.ss = *pss;
1199 ip_list.port = 0;
1201 #ifdef HAVE_ADS
1202 /* For active directory servers, try to get the ldap server name.
1203 None of these failures should be considered critical for now */
1205 if (lp_security() == SEC_ADS) {
1206 ADS_STRUCT *ads;
1207 ADS_STATUS ads_status;
1208 char addr[INET6_ADDRSTRLEN];
1210 print_sockaddr(addr, sizeof(addr), pss);
1212 ads = ads_init(domain->alt_name, domain->name, addr);
1213 ads->auth.flags |= ADS_AUTH_NO_BIND;
1215 ads_status = ads_connect(ads);
1216 if (ADS_ERR_OK(ads_status)) {
1217 /* We got a cldap packet. */
1218 *name = talloc_strdup(mem_ctx,
1219 ads->config.ldap_server_name);
1220 if (*name == NULL) {
1221 return false;
1223 namecache_store(*name, 0x20, 1, &ip_list);
1225 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1227 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1228 if (ads_closest_dc(ads)) {
1229 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1231 /* We're going to use this KDC for this realm/domain.
1232 If we are using sites, then force the krb5 libs
1233 to use this KDC. */
1235 create_local_private_krb5_conf_for_domain(domain->alt_name,
1236 domain->name,
1237 sitename,
1238 pss);
1240 TALLOC_FREE(sitename);
1241 } else {
1242 /* use an off site KDC */
1243 create_local_private_krb5_conf_for_domain(domain->alt_name,
1244 domain->name,
1245 NULL,
1246 pss);
1248 winbindd_set_locator_kdc_envs(domain);
1250 /* Ensure we contact this DC also. */
1251 saf_store(domain->name, *name);
1252 saf_store(domain->alt_name, *name);
1255 ads_destroy( &ads );
1256 return True;
1259 ads_destroy( &ads );
1260 return false;
1262 #endif
1264 status = nbt_getdc(winbind_messaging_context(), 10, pss, domain->name,
1265 &domain->sid, nt_version, mem_ctx, &nt_version,
1266 &dc_name, NULL);
1267 if (NT_STATUS_IS_OK(status)) {
1268 *name = talloc_strdup(mem_ctx, dc_name);
1269 if (*name == NULL) {
1270 return false;
1272 namecache_store(*name, 0x20, 1, &ip_list);
1273 return True;
1276 /* try node status request */
1278 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1279 namecache_store(nbtname, 0x20, 1, &ip_list);
1281 if (name != NULL) {
1282 *name = talloc_strdup(mem_ctx, nbtname);
1283 if (*name == NULL) {
1284 return false;
1288 return true;
1290 return False;
1293 /*******************************************************************
1294 Retrieve a list of IP addresses for domain controllers.
1296 The array is sorted in the preferred connection order.
1298 @param[in] mem_ctx talloc memory context to allocate from
1299 @param[in] domain domain to retrieve DCs for
1300 @param[out] dcs array of dcs that will be returned
1301 @param[out] num_dcs number of dcs returned in the dcs array
1302 @return always true
1303 *******************************************************************/
1305 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1306 struct dc_name_ip **dcs, int *num_dcs)
1308 fstring dcname;
1309 struct sockaddr_storage ss;
1310 struct ip_service *ip_list = NULL;
1311 int iplist_size = 0;
1312 int i;
1313 bool is_our_domain;
1314 enum security_types sec = (enum security_types)lp_security();
1316 is_our_domain = strequal(domain->name, lp_workgroup());
1318 /* If not our domain, get the preferred DC, by asking our primary DC */
1319 if ( !is_our_domain
1320 && get_dc_name_via_netlogon(domain, dcname, &ss)
1321 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1322 num_dcs) )
1324 char addr[INET6_ADDRSTRLEN];
1325 print_sockaddr(addr, sizeof(addr), &ss);
1326 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1327 dcname, addr));
1328 return True;
1331 if (sec == SEC_ADS) {
1332 char *sitename = NULL;
1334 /* We need to make sure we know the local site before
1335 doing any DNS queries, as this will restrict the
1336 get_sorted_dc_list() call below to only fetching
1337 DNS records for the correct site. */
1339 /* Find any DC to get the site record.
1340 We deliberately don't care about the
1341 return here. */
1343 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1345 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1346 if (sitename) {
1348 /* Do the site-specific AD dns lookup first. */
1349 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1350 &iplist_size, True);
1352 /* Add ips to the DC array. We don't look up the name
1353 of the DC in this function, but we fill in the char*
1354 of the ip now to make the failed connection cache
1355 work */
1356 for ( i=0; i<iplist_size; i++ ) {
1357 char addr[INET6_ADDRSTRLEN];
1358 print_sockaddr(addr, sizeof(addr),
1359 &ip_list[i].ss);
1360 add_one_dc_unique(mem_ctx,
1361 domain->name,
1362 addr,
1363 &ip_list[i].ss,
1364 dcs,
1365 num_dcs);
1368 SAFE_FREE(ip_list);
1369 TALLOC_FREE(sitename);
1370 iplist_size = 0;
1373 /* Now we add DCs from the main AD DNS lookup. */
1374 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1375 &iplist_size, True);
1377 for ( i=0; i<iplist_size; i++ ) {
1378 char addr[INET6_ADDRSTRLEN];
1379 print_sockaddr(addr, sizeof(addr),
1380 &ip_list[i].ss);
1381 add_one_dc_unique(mem_ctx,
1382 domain->name,
1383 addr,
1384 &ip_list[i].ss,
1385 dcs,
1386 num_dcs);
1389 SAFE_FREE(ip_list);
1390 iplist_size = 0;
1393 /* Try standard netbios queries if no ADS and fall back to DNS queries
1394 * if alt_name is available */
1395 if (*num_dcs == 0) {
1396 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1397 false);
1398 if (iplist_size == 0) {
1399 if (domain->alt_name != NULL) {
1400 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1401 &iplist_size, true);
1405 for ( i=0; i<iplist_size; i++ ) {
1406 char addr[INET6_ADDRSTRLEN];
1407 print_sockaddr(addr, sizeof(addr),
1408 &ip_list[i].ss);
1409 add_one_dc_unique(mem_ctx,
1410 domain->name,
1411 addr,
1412 &ip_list[i].ss,
1413 dcs,
1414 num_dcs);
1417 SAFE_FREE(ip_list);
1418 iplist_size = 0;
1421 return True;
1424 /*******************************************************************
1425 Find and make a connection to a DC in the given domain.
1427 @param[in] mem_ctx talloc memory context to allocate from
1428 @param[in] domain domain to find a dc in
1429 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1430 @param[out] pss DC Internet address and port
1431 @param[out] fd fd of the open socket connected to the newly found dc
1432 @return true when a DC connection is made, false otherwise
1433 *******************************************************************/
1435 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1436 struct winbindd_domain *domain,
1437 char **dcname, struct sockaddr_storage *pss, int *fd)
1439 struct dc_name_ip *dcs = NULL;
1440 int num_dcs = 0;
1442 const char **dcnames = NULL;
1443 int num_dcnames = 0;
1445 struct sockaddr_storage *addrs = NULL;
1446 int num_addrs = 0;
1448 int i;
1449 size_t fd_index;
1451 NTSTATUS status;
1453 *fd = -1;
1455 again:
1456 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1457 return False;
1459 for (i=0; i<num_dcs; i++) {
1461 if (!add_string_to_array(mem_ctx, dcs[i].name,
1462 &dcnames, &num_dcnames)) {
1463 return False;
1465 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1466 &addrs, &num_addrs)) {
1467 return False;
1471 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1472 return False;
1474 if ((addrs == NULL) || (dcnames == NULL))
1475 return False;
1477 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1478 num_addrs, 0, 10, fd, &fd_index, NULL);
1479 if (!NT_STATUS_IS_OK(status)) {
1480 for (i=0; i<num_dcs; i++) {
1481 char ab[INET6_ADDRSTRLEN];
1482 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1483 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1484 "domain %s address %s. Error was %s\n",
1485 domain->name, ab, nt_errstr(status) ));
1486 winbind_add_failed_connection_entry(domain,
1487 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1489 return False;
1492 *pss = addrs[fd_index];
1494 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1495 /* Ok, we've got a name for the DC */
1496 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1497 if (*dcname == NULL) {
1498 return false;
1500 return true;
1503 /* Try to figure out the name */
1504 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1505 return True;
1508 /* We can not continue without the DC's name */
1509 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1510 NT_STATUS_UNSUCCESSFUL);
1512 /* Throw away all arrays as we're doing this again. */
1513 TALLOC_FREE(dcs);
1514 num_dcs = 0;
1516 TALLOC_FREE(dcnames);
1517 num_dcnames = 0;
1519 TALLOC_FREE(addrs);
1520 num_addrs = 0;
1522 close(*fd);
1523 *fd = -1;
1525 goto again;
1528 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1530 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1531 domain_name);
1534 static void store_current_dc_in_gencache(const char *domain_name,
1535 const char *dc_name,
1536 struct cli_state *cli)
1538 char addr[INET6_ADDRSTRLEN];
1539 char *key = NULL;
1540 char *value = NULL;
1542 if (!cli_state_is_connected(cli)) {
1543 return;
1546 print_sockaddr(addr, sizeof(addr),
1547 smbXcli_conn_remote_sockaddr(cli->conn));
1549 key = current_dc_key(talloc_tos(), domain_name);
1550 if (key == NULL) {
1551 goto done;
1554 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1555 if (value == NULL) {
1556 goto done;
1559 gencache_set(key, value, 0x7fffffff);
1560 done:
1561 TALLOC_FREE(value);
1562 TALLOC_FREE(key);
1565 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1566 const char *domain_name,
1567 char **p_dc_name, char **p_dc_ip)
1569 char *key, *p;
1570 char *value = NULL;
1571 bool ret = false;
1572 char *dc_name = NULL;
1573 char *dc_ip = NULL;
1575 key = current_dc_key(talloc_tos(), domain_name);
1576 if (key == NULL) {
1577 goto done;
1579 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1580 goto done;
1582 p = strchr(value, ' ');
1583 if (p == NULL) {
1584 goto done;
1586 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1587 if (dc_ip == NULL) {
1588 goto done;
1590 dc_name = talloc_strdup(mem_ctx, p+1);
1591 if (dc_name == NULL) {
1592 goto done;
1595 if (p_dc_ip != NULL) {
1596 *p_dc_ip = dc_ip;
1597 dc_ip = NULL;
1599 if (p_dc_name != NULL) {
1600 *p_dc_name = dc_name;
1601 dc_name = NULL;
1603 ret = true;
1604 done:
1605 TALLOC_FREE(dc_name);
1606 TALLOC_FREE(dc_ip);
1607 TALLOC_FREE(key);
1608 TALLOC_FREE(value);
1609 return ret;
1612 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1613 const struct ndr_interface_table *table,
1614 struct rpc_pipe_client **ret_pipe)
1616 struct rpc_pipe_client *cli = NULL;
1617 const struct auth_session_info *session_info;
1618 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1621 session_info = get_session_info_system();
1622 SMB_ASSERT(session_info != NULL);
1624 /* create a connection to the specified pipe */
1625 if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1626 status = rpc_pipe_open_interface(mem_ctx,
1627 table,
1628 session_info,
1629 NULL,
1630 winbind_messaging_context(),
1631 &cli);
1632 } else {
1633 status = rpc_pipe_open_internal(mem_ctx,
1634 &table->syntax_id,
1635 session_info,
1636 NULL,
1637 winbind_messaging_context(),
1638 &cli);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1642 table->name, nt_errstr(status)));
1643 return status;
1646 if (ret_pipe) {
1647 *ret_pipe = cli;
1650 return NT_STATUS_OK;
1653 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1654 struct winbindd_cm_conn *new_conn)
1656 TALLOC_CTX *mem_ctx;
1657 NTSTATUS result;
1658 char *saf_servername;
1659 int retries;
1661 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1662 set_domain_offline(domain);
1663 return NT_STATUS_NO_MEMORY;
1666 saf_servername = saf_fetch(mem_ctx, domain->name );
1668 /* we have to check the server affinity cache here since
1669 later we select a DC based on response time and not preference */
1671 /* Check the negative connection cache
1672 before talking to it. It going down may have
1673 triggered the reconnection. */
1675 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1677 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1678 saf_servername, domain->name ));
1680 /* convert an ip address to a name */
1681 if (is_ipaddress( saf_servername ) ) {
1682 char *dcname = NULL;
1683 struct sockaddr_storage ss;
1685 if (!interpret_string_addr(&ss, saf_servername,
1686 AI_NUMERICHOST)) {
1687 TALLOC_FREE(mem_ctx);
1688 return NT_STATUS_UNSUCCESSFUL;
1690 if (dcip_to_name(mem_ctx, domain, &ss, &dcname)) {
1691 domain->dcname = talloc_strdup(domain,
1692 dcname);
1693 if (domain->dcname == NULL) {
1694 TALLOC_FREE(mem_ctx);
1695 return NT_STATUS_NO_MEMORY;
1697 } else {
1698 winbind_add_failed_connection_entry(
1699 domain, saf_servername,
1700 NT_STATUS_UNSUCCESSFUL);
1702 } else {
1703 domain->dcname = talloc_strdup(domain, saf_servername);
1704 if (domain->dcname == NULL) {
1705 TALLOC_FREE(mem_ctx);
1706 return NT_STATUS_NO_MEMORY;
1711 for (retries = 0; retries < 3; retries++) {
1712 int fd = -1;
1713 bool retry = False;
1714 char *dcname = NULL;
1716 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1718 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1719 domain->dcname ? domain->dcname : "", domain->name ));
1721 if (domain->dcname != NULL
1722 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1723 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1725 NTSTATUS status;
1727 status = smbsock_connect(&domain->dcaddr, 0,
1728 NULL, -1, NULL, -1,
1729 &fd, NULL, 10);
1730 if (!NT_STATUS_IS_OK(status)) {
1731 fd = -1;
1735 if ((fd == -1) &&
1736 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd))
1738 /* This is the one place where we will
1739 set the global winbindd offline state
1740 to true, if a "WINBINDD_OFFLINE" entry
1741 is found in the winbindd cache. */
1742 set_global_winbindd_state_offline();
1743 break;
1745 if (dcname != NULL) {
1746 talloc_free(domain->dcname);
1748 domain->dcname = talloc_move(domain, &dcname);
1749 if (domain->dcname == NULL) {
1750 result = NT_STATUS_NO_MEMORY;
1751 break;
1755 new_conn->cli = NULL;
1757 result = cm_prepare_connection(domain, fd, domain->dcname,
1758 &new_conn->cli, &retry);
1759 if (!NT_STATUS_IS_OK(result)) {
1760 /* Don't leak the smb connection socket */
1761 close(fd);
1764 if (!retry)
1765 break;
1768 if (NT_STATUS_IS_OK(result)) {
1769 bool seal_pipes = true;
1771 winbindd_set_locator_kdc_envs(domain);
1773 if (domain->online == False) {
1774 /* We're changing state from offline to online. */
1775 set_global_winbindd_state_online();
1777 set_domain_online(domain);
1780 * Much as I hate global state, this seems to be the point
1781 * where we can be certain that we have a proper connection to
1782 * a DC. wbinfo --dc-info needs that information, store it in
1783 * gencache with a looong timeout. This will need revisiting
1784 * once we start to connect to multiple DCs, wbcDcInfo is
1785 * already prepared for that.
1787 store_current_dc_in_gencache(domain->name, domain->dcname,
1788 new_conn->cli);
1790 seal_pipes = lp_winbind_sealed_pipes();
1791 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1792 domain->name,
1793 seal_pipes);
1795 if (seal_pipes) {
1796 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1797 } else {
1798 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1800 } else {
1801 /* Ensure we setup the retry handler. */
1802 set_domain_offline(domain);
1805 talloc_destroy(mem_ctx);
1806 return result;
1809 /* Close down all open pipes on a connection. */
1811 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1813 NTSTATUS result;
1815 /* We're closing down a possibly dead
1816 connection. Don't have impossibly long (10s) timeouts. */
1818 if (conn->cli) {
1819 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1822 if (conn->samr_pipe != NULL) {
1823 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1824 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1825 talloc_tos(),
1826 &conn->sam_connect_handle,
1827 &result);
1829 TALLOC_FREE(conn->samr_pipe);
1830 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1831 if (conn->cli) {
1832 cli_set_timeout(conn->cli, 500);
1836 if (conn->lsa_pipe != NULL) {
1837 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1838 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1839 talloc_tos(),
1840 &conn->lsa_policy,
1841 &result);
1843 TALLOC_FREE(conn->lsa_pipe);
1844 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1845 if (conn->cli) {
1846 cli_set_timeout(conn->cli, 500);
1850 if (conn->lsa_pipe_tcp != NULL) {
1851 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1852 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1853 talloc_tos(),
1854 &conn->lsa_policy,
1855 &result);
1857 TALLOC_FREE(conn->lsa_pipe_tcp);
1858 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1859 if (conn->cli) {
1860 cli_set_timeout(conn->cli, 500);
1864 if (conn->netlogon_pipe != NULL) {
1865 TALLOC_FREE(conn->netlogon_pipe);
1866 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1867 if (conn->cli) {
1868 cli_set_timeout(conn->cli, 500);
1872 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1873 conn->netlogon_force_reauth = false;
1874 conn->netlogon_flags = 0;
1875 TALLOC_FREE(conn->netlogon_creds);
1877 if (conn->cli) {
1878 cli_shutdown(conn->cli);
1881 conn->cli = NULL;
1884 void close_conns_after_fork(void)
1886 struct winbindd_domain *domain;
1887 struct winbindd_cli_state *cli_state;
1889 for (domain = domain_list(); domain; domain = domain->next) {
1891 * first close the low level SMB TCP connection
1892 * so that we don't generate any SMBclose
1893 * requests in invalidate_cm_connection()
1895 if (cli_state_is_connected(domain->conn.cli)) {
1896 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1899 invalidate_cm_connection(&domain->conn);
1902 for (cli_state = winbindd_client_list();
1903 cli_state != NULL;
1904 cli_state = cli_state->next) {
1905 if (cli_state->sock >= 0) {
1906 close(cli_state->sock);
1907 cli_state->sock = -1;
1912 static bool connection_ok(struct winbindd_domain *domain)
1914 bool ok;
1916 ok = cli_state_is_connected(domain->conn.cli);
1917 if (!ok) {
1918 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1919 domain->dcname, domain->name));
1920 return False;
1923 if (domain->online == False) {
1924 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1925 return False;
1928 return True;
1931 /* Initialize a new connection up to the RPC BIND.
1932 Bypass online status check so always does network calls. */
1934 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1936 NTSTATUS result;
1938 /* Internal connections never use the network. */
1939 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
1940 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1943 /* Still ask the internal LSA and SAMR server about the local domain */
1944 if (domain->internal || connection_ok(domain)) {
1945 if (!domain->initialized) {
1946 set_dc_type_and_flags(domain);
1948 return NT_STATUS_OK;
1951 invalidate_cm_connection(&domain->conn);
1953 result = cm_open_connection(domain, &domain->conn);
1955 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1956 set_dc_type_and_flags(domain);
1959 return result;
1962 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1964 if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
1965 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1968 if (domain->initialized && !domain->online) {
1969 /* We check for online status elsewhere. */
1970 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1973 return init_dc_connection_network(domain);
1976 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1978 NTSTATUS status;
1980 status = init_dc_connection(domain);
1981 if (!NT_STATUS_IS_OK(status)) {
1982 return status;
1985 if (!domain->internal && domain->conn.cli == NULL) {
1986 /* happens for trusted domains without inbound trust */
1987 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1990 return NT_STATUS_OK;
1993 /******************************************************************************
1994 Set the trust flags (direction and forest location) for a domain
1995 ******************************************************************************/
1997 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1999 struct winbindd_domain *our_domain;
2000 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2001 WERROR werr;
2002 struct netr_DomainTrustList trusts;
2003 int i;
2004 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
2005 NETR_TRUST_FLAG_OUTBOUND |
2006 NETR_TRUST_FLAG_INBOUND);
2007 struct rpc_pipe_client *cli;
2008 TALLOC_CTX *mem_ctx = NULL;
2009 struct dcerpc_binding_handle *b;
2011 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2013 /* Our primary domain doesn't need to worry about trust flags.
2014 Force it to go through the network setup */
2015 if ( domain->primary ) {
2016 return False;
2019 our_domain = find_our_domain();
2021 if ( !connection_ok(our_domain) ) {
2022 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
2023 return False;
2026 /* This won't work unless our domain is AD */
2028 if ( !our_domain->active_directory ) {
2029 return False;
2032 /* Use DsEnumerateDomainTrusts to get us the trust direction
2033 and type */
2035 result = cm_connect_netlogon(our_domain, &cli);
2037 if (!NT_STATUS_IS_OK(result)) {
2038 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2039 "a connection to %s for PIPE_NETLOGON (%s)\n",
2040 domain->name, nt_errstr(result)));
2041 return False;
2044 b = cli->binding_handle;
2046 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
2047 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
2048 return False;
2051 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2052 cli->desthost,
2053 flags,
2054 &trusts,
2055 &werr);
2056 if (!NT_STATUS_IS_OK(result)) {
2057 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2058 "failed to query trusted domain list: %s\n",
2059 nt_errstr(result)));
2060 talloc_destroy(mem_ctx);
2061 return false;
2063 if (!W_ERROR_IS_OK(werr)) {
2064 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2065 "failed to query trusted domain list: %s\n",
2066 win_errstr(werr)));
2067 talloc_destroy(mem_ctx);
2068 return false;
2071 /* Now find the domain name and get the flags */
2073 for ( i=0; i<trusts.count; i++ ) {
2074 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2075 domain->domain_flags = trusts.array[i].trust_flags;
2076 domain->domain_type = trusts.array[i].trust_type;
2077 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2079 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
2080 domain->active_directory = True;
2082 /* This flag is only set if the domain is *our*
2083 primary domain and the primary domain is in
2084 native mode */
2086 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2088 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2089 "native mode.\n", domain->name,
2090 domain->native_mode ? "" : "NOT "));
2092 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2093 "running active directory.\n", domain->name,
2094 domain->active_directory ? "" : "NOT "));
2096 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2098 domain->initialized = True;
2100 break;
2104 talloc_destroy( mem_ctx );
2106 return domain->initialized;
2109 /******************************************************************************
2110 We can 'sense' certain things about the DC by it's replies to certain
2111 questions.
2113 This tells us if this particular remote server is Active Directory, and if it
2114 is native mode.
2115 ******************************************************************************/
2117 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2119 NTSTATUS status, result;
2120 WERROR werr;
2121 TALLOC_CTX *mem_ctx = NULL;
2122 struct rpc_pipe_client *cli = NULL;
2123 struct policy_handle pol;
2124 union dssetup_DsRoleInfo info;
2125 union lsa_PolicyInformation *lsa_info = NULL;
2127 if (!domain->internal && !connection_ok(domain)) {
2128 return;
2131 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2132 domain->name);
2133 if (!mem_ctx) {
2134 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2135 return;
2138 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2140 if (domain->internal) {
2141 status = wb_open_internal_pipe(mem_ctx,
2142 &ndr_table_dssetup,
2143 &cli);
2144 } else {
2145 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2146 &ndr_table_dssetup,
2147 &cli);
2150 if (!NT_STATUS_IS_OK(status)) {
2151 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2152 "PI_DSSETUP on domain %s: (%s)\n",
2153 domain->name, nt_errstr(status)));
2155 /* if this is just a non-AD domain we need to continue
2156 * identifying so that we can in the end return with
2157 * domain->initialized = True - gd */
2159 goto no_dssetup;
2162 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2163 DS_ROLE_BASIC_INFORMATION,
2164 &info,
2165 &werr);
2166 TALLOC_FREE(cli);
2168 if (NT_STATUS_IS_OK(status)) {
2169 result = werror_to_ntstatus(werr);
2171 if (!NT_STATUS_IS_OK(status)) {
2172 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2173 "on domain %s failed: (%s)\n",
2174 domain->name, nt_errstr(status)));
2176 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2177 * every opcode on the DSSETUP pipe, continue with
2178 * no_dssetup mode here as well to get domain->initialized
2179 * set - gd */
2181 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2182 goto no_dssetup;
2185 TALLOC_FREE(mem_ctx);
2186 return;
2189 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2190 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2191 domain->native_mode = True;
2192 } else {
2193 domain->native_mode = False;
2196 no_dssetup:
2197 if (domain->internal) {
2198 status = wb_open_internal_pipe(mem_ctx,
2199 &ndr_table_lsarpc,
2200 &cli);
2201 } else {
2202 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2203 &ndr_table_lsarpc, &cli);
2205 if (!NT_STATUS_IS_OK(status)) {
2206 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2207 "PI_LSARPC on domain %s: (%s)\n",
2208 domain->name, nt_errstr(status)));
2209 TALLOC_FREE(cli);
2210 TALLOC_FREE(mem_ctx);
2211 return;
2214 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2215 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2217 if (NT_STATUS_IS_OK(status)) {
2218 /* This particular query is exactly what Win2k clients use
2219 to determine that the DC is active directory */
2220 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2221 &pol,
2222 LSA_POLICY_INFO_DNS,
2223 &lsa_info,
2224 &result);
2227 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2228 domain->active_directory = True;
2230 if (lsa_info->dns.name.string) {
2231 talloc_free(domain->name);
2232 domain->name = talloc_strdup(domain,
2233 lsa_info->dns.name.string);
2234 if (domain->name == NULL) {
2235 goto done;
2239 if (lsa_info->dns.dns_domain.string) {
2240 talloc_free(domain->alt_name);
2241 domain->alt_name =
2242 talloc_strdup(domain,
2243 lsa_info->dns.dns_domain.string);
2244 if (domain->alt_name == NULL) {
2245 goto done;
2249 /* See if we can set some domain trust flags about
2250 ourself */
2252 if (lsa_info->dns.dns_forest.string) {
2253 talloc_free(domain->forest_name);
2254 domain->forest_name =
2255 talloc_strdup(domain,
2256 lsa_info->dns.dns_forest.string);
2257 if (domain->forest_name == NULL) {
2258 goto done;
2261 if (strequal(domain->forest_name, domain->alt_name)) {
2262 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2266 if (lsa_info->dns.sid) {
2267 sid_copy(&domain->sid, lsa_info->dns.sid);
2269 } else {
2270 domain->active_directory = False;
2272 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2273 SEC_FLAG_MAXIMUM_ALLOWED,
2274 &pol);
2276 if (!NT_STATUS_IS_OK(status)) {
2277 goto done;
2280 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2281 &pol,
2282 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2283 &lsa_info,
2284 &result);
2285 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2287 if (lsa_info->account_domain.name.string) {
2288 talloc_free(domain->name);
2289 domain->name =
2290 talloc_strdup(domain,
2291 lsa_info->account_domain.name.string);
2294 if (lsa_info->account_domain.sid) {
2295 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2299 done:
2301 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2302 domain->name, domain->native_mode ? "" : "NOT "));
2304 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2305 domain->name, domain->active_directory ? "" : "NOT "));
2307 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2309 TALLOC_FREE(cli);
2311 TALLOC_FREE(mem_ctx);
2313 domain->initialized = True;
2316 /**********************************************************************
2317 Set the domain_flags (trust attributes, domain operating modes, etc...
2318 ***********************************************************************/
2320 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2322 /* we always have to contact our primary domain */
2324 if ( domain->primary || domain->internal) {
2325 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2326 "primary or internal domain\n"));
2327 set_dc_type_and_flags_connect( domain );
2328 return;
2331 /* Use our DC to get the information if possible */
2333 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2334 /* Otherwise, fallback to contacting the
2335 domain directly */
2336 set_dc_type_and_flags_connect( domain );
2339 return;
2344 /**********************************************************************
2345 ***********************************************************************/
2347 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2348 struct netlogon_creds_cli_context **ppdc)
2350 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2351 struct rpc_pipe_client *netlogon_pipe;
2353 *ppdc = NULL;
2355 if ((!IS_DC) && (!domain->primary)) {
2356 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2359 if (domain->conn.netlogon_creds != NULL) {
2360 if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2361 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2363 *ppdc = domain->conn.netlogon_creds;
2364 return NT_STATUS_OK;
2367 result = cm_connect_netlogon(domain, &netlogon_pipe);
2368 if (!NT_STATUS_IS_OK(result)) {
2369 return result;
2372 if (domain->conn.netlogon_creds == NULL) {
2373 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2376 if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2377 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2380 *ppdc = domain->conn.netlogon_creds;
2381 return NT_STATUS_OK;
2384 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2385 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2387 struct winbindd_cm_conn *conn;
2388 NTSTATUS status, result;
2389 struct netlogon_creds_cli_context *p_creds;
2390 char *machine_password = NULL;
2391 char *machine_account = NULL;
2392 const char *domain_name = NULL;
2394 if (sid_check_is_our_sam(&domain->sid)) {
2395 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2398 status = init_dc_connection_rpc(domain);
2399 if (!NT_STATUS_IS_OK(status)) {
2400 return status;
2403 conn = &domain->conn;
2405 if (rpccli_is_connected(conn->samr_pipe)) {
2406 goto done;
2409 TALLOC_FREE(conn->samr_pipe);
2412 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2413 * sign and sealed pipe using the machine account password by
2414 * preference. If we can't - try schannel, if that fails, try
2415 * anonymous.
2418 if ((conn->cli->user_name[0] == '\0') ||
2419 (conn->cli->domain[0] == '\0') ||
2420 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2422 status = get_trust_creds(domain, &machine_password,
2423 &machine_account, NULL);
2424 if (!NT_STATUS_IS_OK(status)) {
2425 DEBUG(10, ("cm_connect_sam: No no user available for "
2426 "domain %s, trying schannel\n", conn->cli->domain));
2427 goto schannel;
2429 domain_name = domain->name;
2430 } else {
2431 machine_password = SMB_STRDUP(conn->cli->password);
2432 machine_account = SMB_STRDUP(conn->cli->user_name);
2433 domain_name = conn->cli->domain;
2436 if (!machine_password || !machine_account) {
2437 status = NT_STATUS_NO_MEMORY;
2438 goto done;
2441 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2442 authenticated SAMR pipe with sign & seal. */
2443 status = cli_rpc_pipe_open_spnego(conn->cli,
2444 &ndr_table_samr,
2445 NCACN_NP,
2446 GENSEC_OID_NTLMSSP,
2447 conn->auth_level,
2448 smbXcli_conn_remote_name(conn->cli->conn),
2449 domain_name,
2450 machine_account,
2451 machine_password,
2452 &conn->samr_pipe);
2454 if (!NT_STATUS_IS_OK(status)) {
2455 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2456 "pipe for domain %s using NTLMSSP "
2457 "authenticated pipe: user %s\\%s. Error was "
2458 "%s\n", domain->name, domain_name,
2459 machine_account, nt_errstr(status)));
2460 goto schannel;
2463 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2464 "domain %s using NTLMSSP authenticated "
2465 "pipe: user %s\\%s\n", domain->name,
2466 domain_name, machine_account));
2468 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2469 conn->samr_pipe->desthost,
2470 SEC_FLAG_MAXIMUM_ALLOWED,
2471 &conn->sam_connect_handle,
2472 &result);
2473 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2474 goto open_domain;
2476 if (NT_STATUS_IS_OK(status)) {
2477 status = result;
2480 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2481 "failed for domain %s, error was %s. Trying schannel\n",
2482 domain->name, nt_errstr(status) ));
2483 TALLOC_FREE(conn->samr_pipe);
2485 schannel:
2487 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2489 status = cm_get_schannel_creds(domain, &p_creds);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 /* If this call fails - conn->cli can now be NULL ! */
2492 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2493 "for domain %s (error %s), trying anon\n",
2494 domain->name,
2495 nt_errstr(status) ));
2496 goto anonymous;
2498 status = cli_rpc_pipe_open_schannel_with_key
2499 (conn->cli, &ndr_table_samr, NCACN_NP,
2500 domain->name, p_creds, &conn->samr_pipe);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2504 "domain %s using schannel. Error was %s\n",
2505 domain->name, nt_errstr(status) ));
2506 goto anonymous;
2508 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2509 "schannel.\n", domain->name ));
2511 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2512 conn->samr_pipe->desthost,
2513 SEC_FLAG_MAXIMUM_ALLOWED,
2514 &conn->sam_connect_handle,
2515 &result);
2516 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2517 goto open_domain;
2519 if (NT_STATUS_IS_OK(status)) {
2520 status = result;
2522 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2523 "for domain %s, error was %s. Trying anonymous\n",
2524 domain->name, nt_errstr(status) ));
2525 TALLOC_FREE(conn->samr_pipe);
2527 anonymous:
2529 /* Finally fall back to anonymous. */
2530 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2531 &conn->samr_pipe);
2533 if (!NT_STATUS_IS_OK(status)) {
2534 goto done;
2537 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2538 conn->samr_pipe->desthost,
2539 SEC_FLAG_MAXIMUM_ALLOWED,
2540 &conn->sam_connect_handle,
2541 &result);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2544 "for domain %s Error was %s\n",
2545 domain->name, nt_errstr(status) ));
2546 goto done;
2548 if (!NT_STATUS_IS_OK(result)) {
2549 status = result;
2550 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2551 "for domain %s Error was %s\n",
2552 domain->name, nt_errstr(result)));
2553 goto done;
2556 open_domain:
2557 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2558 mem_ctx,
2559 &conn->sam_connect_handle,
2560 SEC_FLAG_MAXIMUM_ALLOWED,
2561 &domain->sid,
2562 &conn->sam_domain_handle,
2563 &result);
2564 if (!NT_STATUS_IS_OK(status)) {
2565 goto done;
2568 status = result;
2569 done:
2571 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2573 * if we got access denied, we might just have no access rights
2574 * to talk to the remote samr server server (e.g. when we are a
2575 * PDC and we are connecting a w2k8 pdc via an interdomain
2576 * trust). In that case do not invalidate the whole connection
2577 * stack
2579 TALLOC_FREE(conn->samr_pipe);
2580 ZERO_STRUCT(conn->sam_domain_handle);
2581 return status;
2582 } else if (!NT_STATUS_IS_OK(status)) {
2583 invalidate_cm_connection(conn);
2584 return status;
2587 *cli = conn->samr_pipe;
2588 *sam_handle = conn->sam_domain_handle;
2589 SAFE_FREE(machine_password);
2590 SAFE_FREE(machine_account);
2591 return status;
2594 /**********************************************************************
2595 open an schanneld ncacn_ip_tcp connection to LSA
2596 ***********************************************************************/
2598 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2599 TALLOC_CTX *mem_ctx,
2600 struct rpc_pipe_client **cli)
2602 struct winbindd_cm_conn *conn;
2603 struct netlogon_creds_cli_context *creds;
2604 NTSTATUS status;
2606 DEBUG(10,("cm_connect_lsa_tcp\n"));
2608 status = init_dc_connection_rpc(domain);
2609 if (!NT_STATUS_IS_OK(status)) {
2610 return status;
2613 conn = &domain->conn;
2615 if (conn->lsa_pipe_tcp &&
2616 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2617 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY &&
2618 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2619 goto done;
2622 TALLOC_FREE(conn->lsa_pipe_tcp);
2624 status = cm_get_schannel_creds(domain, &creds);
2625 if (!NT_STATUS_IS_OK(status)) {
2626 goto done;
2629 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2630 &ndr_table_lsarpc,
2631 NCACN_IP_TCP,
2632 domain->name,
2633 creds,
2634 &conn->lsa_pipe_tcp);
2635 if (!NT_STATUS_IS_OK(status)) {
2636 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2637 nt_errstr(status)));
2638 goto done;
2641 done:
2642 if (!NT_STATUS_IS_OK(status)) {
2643 TALLOC_FREE(conn->lsa_pipe_tcp);
2644 return status;
2647 *cli = conn->lsa_pipe_tcp;
2649 return status;
2652 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2653 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2655 struct winbindd_cm_conn *conn;
2656 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2657 struct netlogon_creds_cli_context *p_creds;
2659 result = init_dc_connection_rpc(domain);
2660 if (!NT_STATUS_IS_OK(result))
2661 return result;
2663 conn = &domain->conn;
2665 if (rpccli_is_connected(conn->lsa_pipe)) {
2666 goto done;
2669 TALLOC_FREE(conn->lsa_pipe);
2671 if ((conn->cli->user_name[0] == '\0') ||
2672 (conn->cli->domain[0] == '\0') ||
2673 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2674 DEBUG(10, ("cm_connect_lsa: No no user available for "
2675 "domain %s, trying schannel\n", conn->cli->domain));
2676 goto schannel;
2679 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2680 * authenticated LSA pipe with sign & seal. */
2681 result = cli_rpc_pipe_open_spnego
2682 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2683 GENSEC_OID_NTLMSSP,
2684 conn->auth_level,
2685 smbXcli_conn_remote_name(conn->cli->conn),
2686 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2687 &conn->lsa_pipe);
2689 if (!NT_STATUS_IS_OK(result)) {
2690 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2691 "domain %s using NTLMSSP authenticated pipe: user "
2692 "%s\\%s. Error was %s. Trying schannel.\n",
2693 domain->name, conn->cli->domain,
2694 conn->cli->user_name, nt_errstr(result)));
2695 goto schannel;
2698 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2699 "NTLMSSP authenticated pipe: user %s\\%s\n",
2700 domain->name, conn->cli->domain, conn->cli->user_name ));
2702 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2703 SEC_FLAG_MAXIMUM_ALLOWED,
2704 &conn->lsa_policy);
2705 if (NT_STATUS_IS_OK(result)) {
2706 goto done;
2709 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2710 "schannel\n"));
2712 TALLOC_FREE(conn->lsa_pipe);
2714 schannel:
2716 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2718 result = cm_get_schannel_creds(domain, &p_creds);
2719 if (!NT_STATUS_IS_OK(result)) {
2720 /* If this call fails - conn->cli can now be NULL ! */
2721 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2722 "for domain %s (error %s), trying anon\n",
2723 domain->name,
2724 nt_errstr(result) ));
2725 goto anonymous;
2727 result = cli_rpc_pipe_open_schannel_with_key
2728 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2729 domain->name, p_creds, &conn->lsa_pipe);
2731 if (!NT_STATUS_IS_OK(result)) {
2732 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2733 "domain %s using schannel. Error was %s\n",
2734 domain->name, nt_errstr(result) ));
2735 goto anonymous;
2737 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2738 "schannel.\n", domain->name ));
2740 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2741 SEC_FLAG_MAXIMUM_ALLOWED,
2742 &conn->lsa_policy);
2743 if (NT_STATUS_IS_OK(result)) {
2744 goto done;
2747 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2748 "anonymous\n"));
2750 TALLOC_FREE(conn->lsa_pipe);
2752 anonymous:
2754 result = cli_rpc_pipe_open_noauth(conn->cli,
2755 &ndr_table_lsarpc,
2756 &conn->lsa_pipe);
2757 if (!NT_STATUS_IS_OK(result)) {
2758 goto done;
2761 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2762 SEC_FLAG_MAXIMUM_ALLOWED,
2763 &conn->lsa_policy);
2764 done:
2765 if (!NT_STATUS_IS_OK(result)) {
2766 invalidate_cm_connection(conn);
2767 return result;
2770 *cli = conn->lsa_pipe;
2771 *lsa_policy = conn->lsa_policy;
2772 return result;
2775 /****************************************************************************
2776 Open a LSA connection to a DC, suiteable for LSA lookup calls.
2777 ****************************************************************************/
2779 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
2780 TALLOC_CTX *mem_ctx,
2781 struct rpc_pipe_client **cli,
2782 struct policy_handle *lsa_policy)
2784 NTSTATUS status;
2786 if (domain->can_do_ncacn_ip_tcp) {
2787 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2788 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
2789 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
2790 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
2791 invalidate_cm_connection(&domain->conn);
2792 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2794 if (NT_STATUS_IS_OK(status)) {
2795 return status;
2799 * we tried twice to connect via ncan_ip_tcp and schannel and
2800 * failed - maybe it is a trusted domain we can't connect to ?
2801 * do not try tcp next time - gd
2803 domain->can_do_ncacn_ip_tcp = false;
2806 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
2808 return status;
2811 /****************************************************************************
2812 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2813 session key stored in conn->netlogon_pipe->dc->sess_key.
2814 ****************************************************************************/
2816 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2817 struct rpc_pipe_client **cli)
2819 struct messaging_context *msg_ctx = winbind_messaging_context();
2820 struct winbindd_cm_conn *conn;
2821 NTSTATUS result;
2822 enum netr_SchannelType sec_chan_type;
2823 const char *_account_name;
2824 const char *account_name;
2825 struct samr_Password current_nt_hash;
2826 struct samr_Password *previous_nt_hash = NULL;
2827 struct netlogon_creds_CredentialState *creds = NULL;
2828 bool ok;
2830 *cli = NULL;
2832 result = init_dc_connection_rpc(domain);
2833 if (!NT_STATUS_IS_OK(result)) {
2834 return result;
2837 conn = &domain->conn;
2839 if (rpccli_is_connected(conn->netlogon_pipe)) {
2840 *cli = conn->netlogon_pipe;
2841 return NT_STATUS_OK;
2844 TALLOC_FREE(conn->netlogon_pipe);
2845 conn->netlogon_flags = 0;
2846 TALLOC_FREE(conn->netlogon_creds);
2848 if ((!IS_DC) && (!domain->primary)) {
2849 goto no_schannel;
2852 ok = get_trust_pw_hash(domain->name,
2853 current_nt_hash.hash,
2854 &_account_name,
2855 &sec_chan_type);
2856 if (!ok) {
2857 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2860 account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name);
2861 if (account_name == NULL) {
2862 return NT_STATUS_NO_MEMORY;
2865 result = rpccli_create_netlogon_creds(domain->dcname,
2866 domain->name,
2867 account_name,
2868 sec_chan_type,
2869 msg_ctx,
2870 domain,
2871 &conn->netlogon_creds);
2872 if (!NT_STATUS_IS_OK(result)) {
2873 SAFE_FREE(previous_nt_hash);
2874 return result;
2877 result = rpccli_setup_netlogon_creds(conn->cli,
2878 conn->netlogon_creds,
2879 conn->netlogon_force_reauth,
2880 current_nt_hash,
2881 previous_nt_hash);
2882 conn->netlogon_force_reauth = false;
2883 SAFE_FREE(previous_nt_hash);
2884 if (!NT_STATUS_IS_OK(result)) {
2885 return result;
2888 result = netlogon_creds_cli_get(conn->netlogon_creds,
2889 talloc_tos(),
2890 &creds);
2891 if (!NT_STATUS_IS_OK(result)) {
2892 return result;
2894 conn->netlogon_flags = creds->negotiate_flags;
2895 TALLOC_FREE(creds);
2897 no_schannel:
2898 if (!(conn->netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2899 result = cli_rpc_pipe_open_noauth(conn->cli,
2900 &ndr_table_netlogon,
2901 &conn->netlogon_pipe);
2902 if (!NT_STATUS_IS_OK(result)) {
2903 invalidate_cm_connection(conn);
2904 return result;
2907 *cli = conn->netlogon_pipe;
2908 return NT_STATUS_OK;
2911 /* Using the credentials from the first pipe, open a signed and sealed
2912 second netlogon pipe. The session key is stored in the schannel
2913 part of the new pipe auth struct.
2916 result = cli_rpc_pipe_open_schannel_with_key(
2917 conn->cli, &ndr_table_netlogon, NCACN_NP,
2918 domain->name,
2919 conn->netlogon_creds,
2920 &conn->netlogon_pipe);
2921 if (!NT_STATUS_IS_OK(result)) {
2922 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2923 "was %s\n", nt_errstr(result)));
2925 invalidate_cm_connection(conn);
2926 return result;
2929 *cli = conn->netlogon_pipe;
2930 return NT_STATUS_OK;
2933 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2934 void *private_data,
2935 uint32_t msg_type,
2936 struct server_id server_id,
2937 DATA_BLOB *data)
2939 struct winbindd_domain *domain;
2940 char *freeit = NULL;
2941 char *addr;
2943 if ((data == NULL)
2944 || (data->data == NULL)
2945 || (data->length == 0)
2946 || (data->data[data->length-1] != '\0')) {
2947 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2948 "string\n"));
2949 return;
2952 addr = (char *)data->data;
2953 DEBUG(10, ("IP %s dropped\n", addr));
2955 if (!is_ipaddress(addr)) {
2956 char *slash;
2958 * Some code sends us ip addresses with the /netmask
2959 * suffix
2961 slash = strchr(addr, '/');
2962 if (slash == NULL) {
2963 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2964 addr));
2965 return;
2967 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2968 if (freeit == NULL) {
2969 DEBUG(1, ("talloc failed\n"));
2970 return;
2972 addr = freeit;
2973 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2976 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2977 char sockaddr[INET6_ADDRSTRLEN];
2979 if (!cli_state_is_connected(domain->conn.cli)) {
2980 continue;
2983 print_sockaddr(sockaddr, sizeof(sockaddr),
2984 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
2986 if (strequal(sockaddr, addr)) {
2987 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2990 TALLOC_FREE(freeit);