param: Rename variable used for lp_winbind_offline_logon bWinbindOfflineLogon
[Samba.git] / source3 / winbindd / winbindd_cm.c
blobfcca94ab1219bb693dc2726ccdd2cb36218a2876
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"
84 #undef DBGC_CLASS
85 #define DBGC_CLASS DBGC_WINBIND
87 struct dc_name_ip {
88 fstring name;
89 struct sockaddr_storage ss;
92 extern struct winbindd_methods reconnect_methods;
93 extern bool override_logfile;
95 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
96 static void set_dc_type_and_flags( struct winbindd_domain *domain );
97 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
98 struct dc_name_ip **dcs, int *num_dcs);
100 /****************************************************************
101 Child failed to find DC's. Reschedule check.
102 ****************************************************************/
104 static void msg_failed_to_go_online(struct messaging_context *msg,
105 void *private_data,
106 uint32_t msg_type,
107 struct server_id server_id,
108 DATA_BLOB *data)
110 struct winbindd_domain *domain;
111 const char *domainname = (const char *)data->data;
113 if (data->data == NULL || data->length == 0) {
114 return;
117 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
119 for (domain = domain_list(); domain; domain = domain->next) {
120 if (domain->internal) {
121 continue;
124 if (strequal(domain->name, domainname)) {
125 if (domain->online) {
126 /* We're already online, ignore. */
127 DEBUG(5,("msg_fail_to_go_online: domain %s "
128 "already online.\n", domainname));
129 continue;
132 /* Reschedule the online check. */
133 set_domain_offline(domain);
134 break;
139 /****************************************************************
140 Actually cause a reconnect from a message.
141 ****************************************************************/
143 static void msg_try_to_go_online(struct messaging_context *msg,
144 void *private_data,
145 uint32_t msg_type,
146 struct server_id server_id,
147 DATA_BLOB *data)
149 struct winbindd_domain *domain;
150 const char *domainname = (const char *)data->data;
152 if (data->data == NULL || data->length == 0) {
153 return;
156 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
158 for (domain = domain_list(); domain; domain = domain->next) {
159 if (domain->internal) {
160 continue;
163 if (strequal(domain->name, domainname)) {
165 if (domain->online) {
166 /* We're already online, ignore. */
167 DEBUG(5,("msg_try_to_go_online: domain %s "
168 "already online.\n", domainname));
169 continue;
172 /* This call takes care of setting the online
173 flag to true if we connected, or re-adding
174 the offline handler if false. Bypasses online
175 check so always does network calls. */
177 init_dc_connection_network(domain);
178 break;
183 /****************************************************************
184 Fork a child to try and contact a DC. Do this as contacting a
185 DC requires blocking lookups and we don't want to block our
186 parent.
187 ****************************************************************/
189 static bool fork_child_dc_connect(struct winbindd_domain *domain)
191 struct dc_name_ip *dcs = NULL;
192 int num_dcs = 0;
193 TALLOC_CTX *mem_ctx = NULL;
194 pid_t parent_pid = getpid();
195 char *lfile = NULL;
196 NTSTATUS status;
198 if (domain->dc_probe_pid != (pid_t)-1) {
200 * We might already have a DC probe
201 * child working, check.
203 if (process_exists_by_pid(domain->dc_probe_pid)) {
204 DEBUG(10,("fork_child_dc_connect: pid %u already "
205 "checking for DC's.\n",
206 (unsigned int)domain->dc_probe_pid));
207 return true;
209 domain->dc_probe_pid = (pid_t)-1;
212 domain->dc_probe_pid = fork();
214 if (domain->dc_probe_pid == (pid_t)-1) {
215 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
216 return False;
219 if (domain->dc_probe_pid != (pid_t)0) {
220 /* Parent */
221 messaging_register(winbind_messaging_context(), NULL,
222 MSG_WINBIND_TRY_TO_GO_ONLINE,
223 msg_try_to_go_online);
224 messaging_register(winbind_messaging_context(), NULL,
225 MSG_WINBIND_FAILED_TO_GO_ONLINE,
226 msg_failed_to_go_online);
227 return True;
230 /* Child. */
232 /* Leave messages blocked - we will never process one. */
234 if (!override_logfile) {
235 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
236 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
237 _exit(1);
241 status = winbindd_reinit_after_fork(NULL, lfile);
242 if (!NT_STATUS_IS_OK(status)) {
243 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
244 nt_errstr(status)));
245 messaging_send_buf(winbind_messaging_context(),
246 pid_to_procid(parent_pid),
247 MSG_WINBIND_FAILED_TO_GO_ONLINE,
248 (const uint8_t *)domain->name,
249 strlen(domain->name)+1);
250 _exit(1);
252 SAFE_FREE(lfile);
254 mem_ctx = talloc_init("fork_child_dc_connect");
255 if (!mem_ctx) {
256 DEBUG(0,("talloc_init failed.\n"));
257 messaging_send_buf(winbind_messaging_context(),
258 pid_to_procid(parent_pid),
259 MSG_WINBIND_FAILED_TO_GO_ONLINE,
260 (const uint8_t *)domain->name,
261 strlen(domain->name)+1);
262 _exit(1);
265 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
266 /* Still offline ? Can't find DC's. */
267 messaging_send_buf(winbind_messaging_context(),
268 pid_to_procid(parent_pid),
269 MSG_WINBIND_FAILED_TO_GO_ONLINE,
270 (const uint8_t *)domain->name,
271 strlen(domain->name)+1);
272 _exit(0);
275 /* We got a DC. Send a message to our parent to get it to
276 try and do the same. */
278 messaging_send_buf(winbind_messaging_context(),
279 pid_to_procid(parent_pid),
280 MSG_WINBIND_TRY_TO_GO_ONLINE,
281 (const uint8_t *)domain->name,
282 strlen(domain->name)+1);
283 _exit(0);
286 /****************************************************************
287 Handler triggered if we're offline to try and detect a DC.
288 ****************************************************************/
290 static void check_domain_online_handler(struct tevent_context *ctx,
291 struct tevent_timer *te,
292 struct timeval now,
293 void *private_data)
295 struct winbindd_domain *domain =
296 (struct winbindd_domain *)private_data;
298 DEBUG(10,("check_domain_online_handler: called for domain "
299 "%s (online = %s)\n", domain->name,
300 domain->online ? "True" : "False" ));
302 TALLOC_FREE(domain->check_online_event);
304 /* Are we still in "startup" mode ? */
306 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
307 /* No longer in "startup" mode. */
308 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
309 domain->name ));
310 domain->startup = False;
313 /* We've been told to stay offline, so stay
314 that way. */
316 if (get_global_winbindd_state_offline()) {
317 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
318 domain->name ));
319 return;
322 /* Fork a child to test if it can contact a DC.
323 If it can then send ourselves a message to
324 cause a reconnect. */
326 fork_child_dc_connect(domain);
329 /****************************************************************
330 If we're still offline setup the timeout check.
331 ****************************************************************/
333 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
335 int wbr = lp_winbind_reconnect_delay();
337 if (domain->startup) {
338 domain->check_online_timeout = 10;
339 } else if (domain->check_online_timeout < wbr) {
340 domain->check_online_timeout = wbr;
344 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
345 void *private_data,
346 uint32_t msg_type,
347 struct server_id server_id,
348 DATA_BLOB *data)
350 const char *domain_name = (const char *)data->data;
351 struct winbindd_domain *domain;
353 domain = find_domain_from_name_noinit(domain_name);
354 if (domain == NULL) {
355 return;
358 domain->online = false;
360 DEBUG(10, ("Domain %s is marked as offline now.\n",
361 domain_name));
364 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
365 void *private_data,
366 uint32_t msg_type,
367 struct server_id server_id,
368 DATA_BLOB *data)
370 const char *domain_name = (const char *)data->data;
371 struct winbindd_domain *domain;
373 domain = find_domain_from_name_noinit(domain_name);
374 if (domain == NULL) {
375 return;
378 domain->online = true;
380 DEBUG(10, ("Domain %s is marked as online now.\n",
381 domain_name));
384 /****************************************************************
385 Set domain offline and also add handler to put us back online
386 if we detect a DC.
387 ****************************************************************/
389 void set_domain_offline(struct winbindd_domain *domain)
391 pid_t parent_pid = getppid();
393 DEBUG(10,("set_domain_offline: called for domain %s\n",
394 domain->name ));
396 TALLOC_FREE(domain->check_online_event);
398 if (domain->internal) {
399 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
400 domain->name ));
401 return;
404 domain->online = False;
406 /* Offline domains are always initialized. They're
407 re-initialized when they go back online. */
409 domain->initialized = True;
411 /* We only add the timeout handler that checks and
412 allows us to go back online when we've not
413 been told to remain offline. */
415 if (get_global_winbindd_state_offline()) {
416 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
417 domain->name ));
418 return;
421 /* If we're in startup mode, check again in 10 seconds, not in
422 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
424 calc_new_online_timeout_check(domain);
426 domain->check_online_event = tevent_add_timer(winbind_event_context(),
427 NULL,
428 timeval_current_ofs(domain->check_online_timeout,0),
429 check_domain_online_handler,
430 domain);
432 /* The above *has* to succeed for winbindd to work. */
433 if (!domain->check_online_event) {
434 smb_panic("set_domain_offline: failed to add online handler");
437 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
438 domain->name ));
440 /* Send a message to the parent that the domain is offline. */
441 if (parent_pid > 1 && !domain->internal) {
442 messaging_send_buf(winbind_messaging_context(),
443 pid_to_procid(parent_pid),
444 MSG_WINBIND_DOMAIN_OFFLINE,
445 (uint8 *)domain->name,
446 strlen(domain->name) + 1);
449 /* Send an offline message to the idmap child when our
450 primary domain goes offline */
452 if ( domain->primary ) {
453 struct winbindd_child *idmap = idmap_child();
455 if ( idmap->pid != 0 ) {
456 messaging_send_buf(winbind_messaging_context(),
457 pid_to_procid(idmap->pid),
458 MSG_WINBIND_OFFLINE,
459 (const uint8_t *)domain->name,
460 strlen(domain->name)+1);
464 return;
467 /****************************************************************
468 Set domain online - if allowed.
469 ****************************************************************/
471 static void set_domain_online(struct winbindd_domain *domain)
473 pid_t parent_pid = getppid();
475 DEBUG(10,("set_domain_online: called for domain %s\n",
476 domain->name ));
478 if (domain->internal) {
479 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
480 domain->name ));
481 return;
484 if (get_global_winbindd_state_offline()) {
485 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
486 domain->name ));
487 return;
490 winbindd_set_locator_kdc_envs(domain);
492 /* If we are waiting to get a krb5 ticket, trigger immediately. */
493 ccache_regain_all_now();
495 /* Ok, we're out of any startup mode now... */
496 domain->startup = False;
498 if (domain->online == False) {
499 /* We were offline - now we're online. We default to
500 using the MS-RPC backend if we started offline,
501 and if we're going online for the first time we
502 should really re-initialize the backends and the
503 checks to see if we're talking to an AD or NT domain.
506 domain->initialized = False;
508 /* 'reconnect_methods' is the MS-RPC backend. */
509 if (domain->backend == &reconnect_methods) {
510 domain->backend = NULL;
514 /* Ensure we have no online timeout checks. */
515 domain->check_online_timeout = 0;
516 TALLOC_FREE(domain->check_online_event);
518 /* Ensure we ignore any pending child messages. */
519 messaging_deregister(winbind_messaging_context(),
520 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
521 messaging_deregister(winbind_messaging_context(),
522 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
524 domain->online = True;
526 /* Send a message to the parent that the domain is online. */
527 if (parent_pid > 1 && !domain->internal) {
528 messaging_send_buf(winbind_messaging_context(),
529 pid_to_procid(parent_pid),
530 MSG_WINBIND_DOMAIN_ONLINE,
531 (uint8 *)domain->name,
532 strlen(domain->name) + 1);
535 /* Send an online message to the idmap child when our
536 primary domain comes online */
538 if ( domain->primary ) {
539 struct winbindd_child *idmap = idmap_child();
541 if ( idmap->pid != 0 ) {
542 messaging_send_buf(winbind_messaging_context(),
543 pid_to_procid(idmap->pid),
544 MSG_WINBIND_ONLINE,
545 (const uint8_t *)domain->name,
546 strlen(domain->name)+1);
550 return;
553 /****************************************************************
554 Requested to set a domain online.
555 ****************************************************************/
557 void set_domain_online_request(struct winbindd_domain *domain)
559 struct timeval tev;
561 DEBUG(10,("set_domain_online_request: called for domain %s\n",
562 domain->name ));
564 if (get_global_winbindd_state_offline()) {
565 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
566 domain->name ));
567 return;
570 if (domain->internal) {
571 DEBUG(10, ("set_domain_online_request: Internal domains are "
572 "always online\n"));
573 return;
576 /* We've been told it's safe to go online and
577 try and connect to a DC. But I don't believe it
578 because network manager seems to lie.
579 Wait at least 5 seconds. Heuristics suck... */
582 GetTimeOfDay(&tev);
584 /* Go into "startup" mode again. */
585 domain->startup_time = time_mono(NULL);
586 domain->startup = True;
588 tev.tv_sec += 5;
590 if (!domain->check_online_event) {
591 /* If we've come from being globally offline we
592 don't have a check online event handler set.
593 We need to add one now we're trying to go
594 back online. */
596 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
597 domain->name ));
600 TALLOC_FREE(domain->check_online_event);
602 domain->check_online_event = tevent_add_timer(winbind_event_context(),
603 NULL,
604 tev,
605 check_domain_online_handler,
606 domain);
608 /* The above *has* to succeed for winbindd to work. */
609 if (!domain->check_online_event) {
610 smb_panic("set_domain_online_request: failed to add online handler");
614 /****************************************************************
615 Add -ve connection cache entries for domain and realm.
616 ****************************************************************/
618 static void winbind_add_failed_connection_entry(
619 const struct winbindd_domain *domain,
620 const char *server,
621 NTSTATUS result)
623 add_failed_connection_entry(domain->name, server, result);
624 /* If this was the saf name for the last thing we talked to,
625 remove it. */
626 saf_delete(domain->name);
627 if (domain->alt_name != NULL) {
628 add_failed_connection_entry(domain->alt_name, server, result);
629 saf_delete(domain->alt_name);
631 winbindd_unset_locator_kdc_env(domain);
634 /* Choose between anonymous or authenticated connections. We need to use
635 an authenticated connection if DCs have the RestrictAnonymous registry
636 entry set > 0, or the "Additional restrictions for anonymous
637 connections" set in the win2k Local Security Policy.
639 Caller to free() result in domain, username, password
642 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
644 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
645 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
646 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
648 if (*username && **username) {
650 if (!*domain || !**domain)
651 *domain = smb_xstrdup(lp_workgroup());
653 if (!*password || !**password)
654 *password = smb_xstrdup("");
656 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
657 *domain, *username));
659 } else {
660 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
661 *username = smb_xstrdup("");
662 *domain = smb_xstrdup("");
663 *password = smb_xstrdup("");
667 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
668 fstring dcname,
669 struct sockaddr_storage *dc_ss)
671 struct winbindd_domain *our_domain = NULL;
672 struct rpc_pipe_client *netlogon_pipe = NULL;
673 NTSTATUS result;
674 WERROR werr;
675 TALLOC_CTX *mem_ctx;
676 unsigned int orig_timeout;
677 const char *tmp = NULL;
678 const char *p;
679 struct dcerpc_binding_handle *b;
681 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
682 * moment.... */
684 if (IS_DC) {
685 return False;
688 if (domain->primary) {
689 return False;
692 our_domain = find_our_domain();
694 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
695 return False;
698 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
699 if (!NT_STATUS_IS_OK(result)) {
700 talloc_destroy(mem_ctx);
701 return False;
704 b = netlogon_pipe->binding_handle;
706 /* This call can take a long time - allow the server to time out.
707 35 seconds should do it. */
709 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
711 if (our_domain->active_directory) {
712 struct netr_DsRGetDCNameInfo *domain_info = NULL;
714 result = dcerpc_netr_DsRGetDCName(b,
715 mem_ctx,
716 our_domain->dcname,
717 domain->name,
718 NULL,
719 NULL,
720 DS_RETURN_DNS_NAME,
721 &domain_info,
722 &werr);
723 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
724 tmp = talloc_strdup(
725 mem_ctx, domain_info->dc_unc);
726 if (tmp == NULL) {
727 DEBUG(0, ("talloc_strdup failed\n"));
728 talloc_destroy(mem_ctx);
729 return false;
731 if (domain->alt_name == NULL) {
732 domain->alt_name = talloc_strdup(domain,
733 domain_info->domain_name);
734 if (domain->alt_name == NULL) {
735 DEBUG(0, ("talloc_strdup failed\n"));
736 talloc_destroy(mem_ctx);
737 return false;
740 if (domain->forest_name == NULL) {
741 domain->forest_name = talloc_strdup(domain,
742 domain_info->forest_name);
743 if (domain->forest_name == NULL) {
744 DEBUG(0, ("talloc_strdup failed\n"));
745 talloc_destroy(mem_ctx);
746 return false;
750 } else {
751 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
752 our_domain->dcname,
753 domain->name,
754 &tmp,
755 &werr);
758 /* And restore our original timeout. */
759 rpccli_set_timeout(netlogon_pipe, orig_timeout);
761 if (!NT_STATUS_IS_OK(result)) {
762 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
763 nt_errstr(result)));
764 talloc_destroy(mem_ctx);
765 return false;
768 if (!W_ERROR_IS_OK(werr)) {
769 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
770 win_errstr(werr)));
771 talloc_destroy(mem_ctx);
772 return false;
775 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
776 p = strip_hostname(tmp);
778 fstrcpy(dcname, p);
780 talloc_destroy(mem_ctx);
782 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
784 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
785 return False;
788 return True;
792 * Helper function to assemble trust password and account name
794 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
795 char **machine_password,
796 char **machine_account,
797 char **machine_krb5_principal)
799 const char *account_name;
800 const char *name = NULL;
802 /* If we are a DC and this is not our own domain */
804 if (IS_DC) {
805 name = domain->name;
806 } else {
807 struct winbindd_domain *our_domain = find_our_domain();
809 if (!our_domain)
810 return NT_STATUS_INVALID_SERVER_STATE;
812 name = our_domain->name;
815 if (!get_trust_pw_clear(name, machine_password,
816 &account_name, NULL))
818 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
821 if ((machine_account != NULL) &&
822 (asprintf(machine_account, "%s$", account_name) == -1))
824 return NT_STATUS_NO_MEMORY;
827 /* For now assume our machine account only exists in our domain */
829 if (machine_krb5_principal != NULL)
831 struct winbindd_domain *our_domain = find_our_domain();
833 if (!our_domain) {
834 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
837 if (asprintf(machine_krb5_principal, "%s$@%s",
838 account_name, our_domain->alt_name) == -1)
840 return NT_STATUS_NO_MEMORY;
843 if (!strupper_m(*machine_krb5_principal)) {
844 SAFE_FREE(*machine_krb5_principal);
845 return NT_STATUS_INVALID_PARAMETER;
849 return NT_STATUS_OK;
852 /************************************************************************
853 Given a fd with a just-connected TCP connection to a DC, open a connection
854 to the pipe.
855 ************************************************************************/
857 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
858 const int sockfd,
859 const char *controller,
860 struct cli_state **cli,
861 bool *retry)
863 bool try_spnego = false;
864 bool try_ipc_auth = false;
865 char *machine_password = NULL;
866 char *machine_krb5_principal = NULL;
867 char *machine_account = NULL;
868 char *ipc_username = NULL;
869 char *ipc_domain = NULL;
870 char *ipc_password = NULL;
871 int flags = 0;
872 uint16_t sec_mode = 0;
874 struct named_mutex *mutex;
876 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
878 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
879 controller, domain->name ));
881 *retry = True;
883 mutex = grab_named_mutex(talloc_tos(), controller,
884 WINBIND_SERVER_MUTEX_WAIT_TIME);
885 if (mutex == NULL) {
886 close(sockfd);
887 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
888 controller));
889 result = NT_STATUS_POSSIBLE_DEADLOCK;
890 goto done;
893 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
895 *cli = cli_state_create(NULL, sockfd,
896 controller, domain->alt_name,
897 SMB_SIGNING_DEFAULT, flags);
898 if (*cli == NULL) {
899 close(sockfd);
900 DEBUG(1, ("Could not cli_initialize\n"));
901 result = NT_STATUS_NO_MEMORY;
902 goto done;
905 cli_set_timeout(*cli, 10000); /* 10 seconds */
907 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
908 lp_cli_minprotocol(),
909 lp_cli_maxprotocol());
911 if (!NT_STATUS_IS_OK(result)) {
912 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
913 goto done;
916 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
917 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
918 try_spnego = true;
919 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
920 try_spnego = true;
923 if (!is_dc_trusted_domain_situation(domain->name) && try_spnego) {
924 result = get_trust_creds(domain, &machine_password,
925 &machine_account,
926 &machine_krb5_principal);
927 if (!NT_STATUS_IS_OK(result)) {
928 goto anon_fallback;
931 if (lp_security() == SEC_ADS) {
933 /* Try a krb5 session */
935 (*cli)->use_kerberos = True;
936 DEBUG(5, ("connecting to %s from %s with kerberos principal "
937 "[%s] and realm [%s]\n", controller, lp_netbios_name(),
938 machine_krb5_principal, domain->alt_name));
940 winbindd_set_locator_kdc_envs(domain);
942 result = cli_session_setup(*cli,
943 machine_krb5_principal,
944 machine_password,
945 strlen(machine_password)+1,
946 machine_password,
947 strlen(machine_password)+1,
948 lp_workgroup());
950 if (!NT_STATUS_IS_OK(result)) {
951 DEBUG(4,("failed kerberos session setup with %s\n",
952 nt_errstr(result)));
955 if (NT_STATUS_IS_OK(result)) {
956 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
957 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
958 if (!NT_STATUS_IS_OK(result)) {
959 goto done;
961 goto session_setup_done;
965 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
966 (*cli)->use_kerberos = False;
968 DEBUG(5, ("connecting to %s from %s with username "
969 "[%s]\\[%s]\n", controller, lp_netbios_name(),
970 lp_workgroup(), machine_account));
972 result = cli_session_setup(*cli,
973 machine_account,
974 machine_password,
975 strlen(machine_password)+1,
976 machine_password,
977 strlen(machine_password)+1,
978 lp_workgroup());
979 if (!NT_STATUS_IS_OK(result)) {
980 DEBUG(4, ("authenticated session setup failed with %s\n",
981 nt_errstr(result)));
984 if (NT_STATUS_IS_OK(result)) {
985 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
986 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
987 if (!NT_STATUS_IS_OK(result)) {
988 goto done;
990 goto session_setup_done;
994 /* Fall back to non-kerberos session setup with auth_user */
996 (*cli)->use_kerberos = False;
998 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
1000 sec_mode = smb1cli_conn_server_security_mode((*cli)->conn);
1002 try_ipc_auth = false;
1003 if (try_spnego) {
1004 try_ipc_auth = true;
1005 } else if (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
1006 try_ipc_auth = true;
1009 if (try_ipc_auth && (strlen(ipc_username) > 0)) {
1011 /* Only try authenticated if we have a username */
1013 DEBUG(5, ("connecting to %s from %s with username "
1014 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1015 ipc_domain, ipc_username));
1017 if (NT_STATUS_IS_OK(cli_session_setup(
1018 *cli, ipc_username,
1019 ipc_password, strlen(ipc_password)+1,
1020 ipc_password, strlen(ipc_password)+1,
1021 ipc_domain))) {
1022 /* Successful logon with given username. */
1023 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
1024 if (!NT_STATUS_IS_OK(result)) {
1025 goto done;
1027 goto session_setup_done;
1028 } else {
1029 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
1030 ipc_domain, ipc_username ));
1034 anon_fallback:
1036 /* Fall back to anonymous connection, this might fail later */
1037 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
1038 "connection for DC %s\n",
1039 controller ));
1041 result = cli_session_setup(*cli, "", NULL, 0, NULL, 0, "");
1042 if (NT_STATUS_IS_OK(result)) {
1043 DEBUG(5, ("Connected anonymously\n"));
1044 result = cli_init_creds(*cli, "", "", "");
1045 if (!NT_STATUS_IS_OK(result)) {
1046 goto done;
1048 goto session_setup_done;
1051 /* We can't session setup */
1052 goto done;
1054 session_setup_done:
1057 * This should be a short term hack until
1058 * dynamic re-authentication is implemented.
1060 * See Bug 9175 - winbindd doesn't recover from
1061 * NT_STATUS_NETWORK_SESSION_EXPIRED
1063 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1064 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1067 /* cache the server name for later connections */
1069 saf_store(domain->name, controller);
1070 if (domain->alt_name && (*cli)->use_kerberos) {
1071 saf_store(domain->alt_name, controller);
1074 winbindd_set_locator_kdc_envs(domain);
1076 result = cli_tree_connect(*cli, "IPC$", "IPC", "", 0);
1078 if (!NT_STATUS_IS_OK(result)) {
1079 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1080 goto done;
1083 TALLOC_FREE(mutex);
1084 *retry = False;
1086 /* set the domain if empty; needed for schannel connections */
1087 if ( !(*cli)->domain[0] ) {
1088 result = cli_set_domain((*cli), domain->name);
1089 if (!NT_STATUS_IS_OK(result)) {
1090 SAFE_FREE(ipc_username);
1091 SAFE_FREE(ipc_domain);
1092 SAFE_FREE(ipc_password);
1093 return result;
1097 result = NT_STATUS_OK;
1099 done:
1100 TALLOC_FREE(mutex);
1101 SAFE_FREE(machine_account);
1102 SAFE_FREE(machine_password);
1103 SAFE_FREE(machine_krb5_principal);
1104 SAFE_FREE(ipc_username);
1105 SAFE_FREE(ipc_domain);
1106 SAFE_FREE(ipc_password);
1108 if (!NT_STATUS_IS_OK(result)) {
1109 winbind_add_failed_connection_entry(domain, controller, result);
1110 if ((*cli) != NULL) {
1111 cli_shutdown(*cli);
1112 *cli = NULL;
1116 return result;
1119 /*******************************************************************
1120 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1121 array.
1123 Keeps the list unique by not adding duplicate entries.
1125 @param[in] mem_ctx talloc memory context to allocate from
1126 @param[in] domain_name domain of the DC
1127 @param[in] dcname name of the DC to add to the list
1128 @param[in] pss Internet address and port pair to add to the list
1129 @param[in,out] dcs array of dc_name_ip structures to add to
1130 @param[in,out] num_dcs number of dcs returned in the dcs array
1131 @return true if the list was added to, false otherwise
1132 *******************************************************************/
1134 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1135 const char *dcname, struct sockaddr_storage *pss,
1136 struct dc_name_ip **dcs, int *num)
1138 int i = 0;
1140 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1141 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1142 return False;
1145 /* Make sure there's no duplicates in the list */
1146 for (i=0; i<*num; i++)
1147 if (sockaddr_equal(
1148 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1149 (struct sockaddr *)(void *)pss))
1150 return False;
1152 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1154 if (*dcs == NULL)
1155 return False;
1157 fstrcpy((*dcs)[*num].name, dcname);
1158 (*dcs)[*num].ss = *pss;
1159 *num += 1;
1160 return True;
1163 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1164 struct sockaddr_storage *pss, uint16 port,
1165 struct sockaddr_storage **addrs, int *num)
1167 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1169 if (*addrs == NULL) {
1170 *num = 0;
1171 return False;
1174 (*addrs)[*num] = *pss;
1175 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1177 *num += 1;
1178 return True;
1181 /*******************************************************************
1182 convert an ip to a name
1183 *******************************************************************/
1185 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1186 const struct winbindd_domain *domain,
1187 struct sockaddr_storage *pss,
1188 char **name)
1190 struct ip_service ip_list;
1191 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1192 NTSTATUS status;
1193 const char *dc_name;
1194 fstring nbtname;
1196 ip_list.ss = *pss;
1197 ip_list.port = 0;
1199 #ifdef HAVE_ADS
1200 /* For active directory servers, try to get the ldap server name.
1201 None of these failures should be considered critical for now */
1203 if (lp_security() == SEC_ADS) {
1204 ADS_STRUCT *ads;
1205 ADS_STATUS ads_status;
1206 char addr[INET6_ADDRSTRLEN];
1208 print_sockaddr(addr, sizeof(addr), pss);
1210 ads = ads_init(domain->alt_name, domain->name, addr);
1211 ads->auth.flags |= ADS_AUTH_NO_BIND;
1213 ads_status = ads_connect(ads);
1214 if (ADS_ERR_OK(ads_status)) {
1215 /* We got a cldap packet. */
1216 *name = talloc_strdup(mem_ctx,
1217 ads->config.ldap_server_name);
1218 if (*name == NULL) {
1219 return false;
1221 namecache_store(*name, 0x20, 1, &ip_list);
1223 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1225 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1226 if (ads_closest_dc(ads)) {
1227 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1229 /* We're going to use this KDC for this realm/domain.
1230 If we are using sites, then force the krb5 libs
1231 to use this KDC. */
1233 create_local_private_krb5_conf_for_domain(domain->alt_name,
1234 domain->name,
1235 sitename,
1236 pss,
1237 *name);
1239 TALLOC_FREE(sitename);
1240 } else {
1241 /* use an off site KDC */
1242 create_local_private_krb5_conf_for_domain(domain->alt_name,
1243 domain->name,
1244 NULL,
1245 pss,
1246 *name);
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 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1613 struct winbindd_cm_conn *new_conn)
1615 TALLOC_CTX *mem_ctx;
1616 NTSTATUS result;
1617 char *saf_servername;
1618 int retries;
1620 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1621 set_domain_offline(domain);
1622 return NT_STATUS_NO_MEMORY;
1625 saf_servername = saf_fetch(mem_ctx, domain->name );
1627 /* we have to check the server affinity cache here since
1628 later we select a DC based on response time and not preference */
1630 /* Check the negative connection cache
1631 before talking to it. It going down may have
1632 triggered the reconnection. */
1634 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1636 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1637 saf_servername, domain->name ));
1639 /* convert an ip address to a name */
1640 if (is_ipaddress( saf_servername ) ) {
1641 char *dcname = NULL;
1642 struct sockaddr_storage ss;
1644 if (!interpret_string_addr(&ss, saf_servername,
1645 AI_NUMERICHOST)) {
1646 TALLOC_FREE(mem_ctx);
1647 return NT_STATUS_UNSUCCESSFUL;
1649 if (dcip_to_name(mem_ctx, domain, &ss, &dcname)) {
1650 domain->dcname = talloc_strdup(domain,
1651 dcname);
1652 if (domain->dcname == NULL) {
1653 TALLOC_FREE(mem_ctx);
1654 return NT_STATUS_NO_MEMORY;
1656 } else {
1657 winbind_add_failed_connection_entry(
1658 domain, saf_servername,
1659 NT_STATUS_UNSUCCESSFUL);
1661 } else {
1662 domain->dcname = talloc_strdup(domain, saf_servername);
1663 if (domain->dcname == NULL) {
1664 TALLOC_FREE(mem_ctx);
1665 return NT_STATUS_NO_MEMORY;
1670 for (retries = 0; retries < 3; retries++) {
1671 int fd = -1;
1672 bool retry = False;
1673 char *dcname = NULL;
1675 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1677 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1678 domain->dcname ? domain->dcname : "", domain->name ));
1680 if (domain->dcname != NULL
1681 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1682 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1684 NTSTATUS status;
1686 status = smbsock_connect(&domain->dcaddr, 0,
1687 NULL, -1, NULL, -1,
1688 &fd, NULL, 10);
1689 if (!NT_STATUS_IS_OK(status)) {
1690 fd = -1;
1694 if ((fd == -1) &&
1695 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd))
1697 /* This is the one place where we will
1698 set the global winbindd offline state
1699 to true, if a "WINBINDD_OFFLINE" entry
1700 is found in the winbindd cache. */
1701 set_global_winbindd_state_offline();
1702 break;
1704 if (dcname != NULL) {
1705 talloc_free(domain->dcname);
1707 domain->dcname = talloc_move(domain, &dcname);
1708 if (domain->dcname == NULL) {
1709 result = NT_STATUS_NO_MEMORY;
1710 break;
1714 new_conn->cli = NULL;
1716 result = cm_prepare_connection(domain, fd, domain->dcname,
1717 &new_conn->cli, &retry);
1718 if (!NT_STATUS_IS_OK(result)) {
1719 /* Don't leak the smb connection socket */
1720 close(fd);
1723 if (!retry)
1724 break;
1727 if (NT_STATUS_IS_OK(result)) {
1728 bool seal_pipes = true;
1730 winbindd_set_locator_kdc_envs(domain);
1732 if (domain->online == False) {
1733 /* We're changing state from offline to online. */
1734 set_global_winbindd_state_online();
1736 set_domain_online(domain);
1739 * Much as I hate global state, this seems to be the point
1740 * where we can be certain that we have a proper connection to
1741 * a DC. wbinfo --dc-info needs that information, store it in
1742 * gencache with a looong timeout. This will need revisiting
1743 * once we start to connect to multiple DCs, wbcDcInfo is
1744 * already prepared for that.
1746 store_current_dc_in_gencache(domain->name, domain->dcname,
1747 new_conn->cli);
1749 seal_pipes = lp_winbind_sealed_pipes();
1750 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1751 domain->name,
1752 seal_pipes);
1754 if (seal_pipes) {
1755 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1756 } else {
1757 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1759 } else {
1760 /* Ensure we setup the retry handler. */
1761 set_domain_offline(domain);
1764 talloc_destroy(mem_ctx);
1765 return result;
1768 /* Close down all open pipes on a connection. */
1770 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1772 NTSTATUS result;
1774 /* We're closing down a possibly dead
1775 connection. Don't have impossibly long (10s) timeouts. */
1777 if (conn->cli) {
1778 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1781 if (conn->samr_pipe != NULL) {
1782 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1783 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1784 talloc_tos(),
1785 &conn->sam_connect_handle,
1786 &result);
1788 TALLOC_FREE(conn->samr_pipe);
1789 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1790 if (conn->cli) {
1791 cli_set_timeout(conn->cli, 500);
1795 if (conn->lsa_pipe != NULL) {
1796 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1797 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1798 talloc_tos(),
1799 &conn->lsa_policy,
1800 &result);
1802 TALLOC_FREE(conn->lsa_pipe);
1803 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1804 if (conn->cli) {
1805 cli_set_timeout(conn->cli, 500);
1809 if (conn->lsa_pipe_tcp != NULL) {
1810 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1811 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1812 talloc_tos(),
1813 &conn->lsa_policy,
1814 &result);
1816 TALLOC_FREE(conn->lsa_pipe_tcp);
1817 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1818 if (conn->cli) {
1819 cli_set_timeout(conn->cli, 500);
1823 if (conn->netlogon_pipe != NULL) {
1824 TALLOC_FREE(conn->netlogon_pipe);
1825 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1826 if (conn->cli) {
1827 cli_set_timeout(conn->cli, 500);
1831 conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1832 conn->netlogon_force_reauth = false;
1833 conn->netlogon_flags = 0;
1834 TALLOC_FREE(conn->netlogon_creds);
1836 if (conn->cli) {
1837 cli_shutdown(conn->cli);
1840 conn->cli = NULL;
1843 void close_conns_after_fork(void)
1845 struct winbindd_domain *domain;
1846 struct winbindd_cli_state *cli_state;
1848 for (domain = domain_list(); domain; domain = domain->next) {
1850 * first close the low level SMB TCP connection
1851 * so that we don't generate any SMBclose
1852 * requests in invalidate_cm_connection()
1854 if (cli_state_is_connected(domain->conn.cli)) {
1855 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1858 invalidate_cm_connection(&domain->conn);
1861 for (cli_state = winbindd_client_list();
1862 cli_state != NULL;
1863 cli_state = cli_state->next) {
1864 if (cli_state->sock >= 0) {
1865 close(cli_state->sock);
1866 cli_state->sock = -1;
1871 static bool connection_ok(struct winbindd_domain *domain)
1873 bool ok;
1875 ok = cli_state_is_connected(domain->conn.cli);
1876 if (!ok) {
1877 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1878 domain->dcname, domain->name));
1879 return False;
1882 if (domain->online == False) {
1883 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1884 return False;
1887 return True;
1890 /* Initialize a new connection up to the RPC BIND.
1891 Bypass online status check so always does network calls. */
1893 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1895 NTSTATUS result;
1897 /* Internal connections never use the network. */
1898 if (domain->internal) {
1899 domain->initialized = True;
1900 return NT_STATUS_OK;
1903 if (connection_ok(domain)) {
1904 if (!domain->initialized) {
1905 set_dc_type_and_flags(domain);
1907 return NT_STATUS_OK;
1910 invalidate_cm_connection(&domain->conn);
1912 result = cm_open_connection(domain, &domain->conn);
1914 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1915 set_dc_type_and_flags(domain);
1918 return result;
1921 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1923 if (domain->internal) {
1924 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1927 if (domain->initialized && !domain->online) {
1928 /* We check for online status elsewhere. */
1929 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1932 return init_dc_connection_network(domain);
1935 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1937 NTSTATUS status;
1939 status = init_dc_connection(domain);
1940 if (!NT_STATUS_IS_OK(status)) {
1941 return status;
1944 if (!domain->internal && domain->conn.cli == NULL) {
1945 /* happens for trusted domains without inbound trust */
1946 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1949 return NT_STATUS_OK;
1952 /******************************************************************************
1953 Set the trust flags (direction and forest location) for a domain
1954 ******************************************************************************/
1956 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1958 struct winbindd_domain *our_domain;
1959 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1960 WERROR werr;
1961 struct netr_DomainTrustList trusts;
1962 int i;
1963 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1964 NETR_TRUST_FLAG_OUTBOUND |
1965 NETR_TRUST_FLAG_INBOUND);
1966 struct rpc_pipe_client *cli;
1967 TALLOC_CTX *mem_ctx = NULL;
1968 struct dcerpc_binding_handle *b;
1970 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1972 /* Our primary domain doesn't need to worry about trust flags.
1973 Force it to go through the network setup */
1974 if ( domain->primary ) {
1975 return False;
1978 our_domain = find_our_domain();
1980 if ( !connection_ok(our_domain) ) {
1981 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1982 return False;
1985 /* This won't work unless our domain is AD */
1987 if ( !our_domain->active_directory ) {
1988 return False;
1991 /* Use DsEnumerateDomainTrusts to get us the trust direction
1992 and type */
1994 result = cm_connect_netlogon(our_domain, &cli);
1996 if (!NT_STATUS_IS_OK(result)) {
1997 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1998 "a connection to %s for PIPE_NETLOGON (%s)\n",
1999 domain->name, nt_errstr(result)));
2000 return False;
2003 b = cli->binding_handle;
2005 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
2006 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
2007 return False;
2010 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2011 cli->desthost,
2012 flags,
2013 &trusts,
2014 &werr);
2015 if (!NT_STATUS_IS_OK(result)) {
2016 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2017 "failed to query trusted domain list: %s\n",
2018 nt_errstr(result)));
2019 talloc_destroy(mem_ctx);
2020 return false;
2022 if (!W_ERROR_IS_OK(werr)) {
2023 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2024 "failed to query trusted domain list: %s\n",
2025 win_errstr(werr)));
2026 talloc_destroy(mem_ctx);
2027 return false;
2030 /* Now find the domain name and get the flags */
2032 for ( i=0; i<trusts.count; i++ ) {
2033 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2034 domain->domain_flags = trusts.array[i].trust_flags;
2035 domain->domain_type = trusts.array[i].trust_type;
2036 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
2038 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
2039 domain->active_directory = True;
2041 /* This flag is only set if the domain is *our*
2042 primary domain and the primary domain is in
2043 native mode */
2045 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2047 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2048 "native mode.\n", domain->name,
2049 domain->native_mode ? "" : "NOT "));
2051 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2052 "running active directory.\n", domain->name,
2053 domain->active_directory ? "" : "NOT "));
2055 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2057 domain->initialized = True;
2059 break;
2063 talloc_destroy( mem_ctx );
2065 return domain->initialized;
2068 /******************************************************************************
2069 We can 'sense' certain things about the DC by it's replies to certain
2070 questions.
2072 This tells us if this particular remote server is Active Directory, and if it
2073 is native mode.
2074 ******************************************************************************/
2076 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2078 NTSTATUS status, result;
2079 WERROR werr;
2080 TALLOC_CTX *mem_ctx = NULL;
2081 struct rpc_pipe_client *cli = NULL;
2082 struct policy_handle pol;
2083 union dssetup_DsRoleInfo info;
2084 union lsa_PolicyInformation *lsa_info = NULL;
2086 if (!connection_ok(domain)) {
2087 return;
2090 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2091 domain->name);
2092 if (!mem_ctx) {
2093 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2094 return;
2097 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2099 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2100 &ndr_table_dssetup,
2101 &cli);
2103 if (!NT_STATUS_IS_OK(status)) {
2104 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2105 "PI_DSSETUP on domain %s: (%s)\n",
2106 domain->name, nt_errstr(status)));
2108 /* if this is just a non-AD domain we need to continue
2109 * identifying so that we can in the end return with
2110 * domain->initialized = True - gd */
2112 goto no_dssetup;
2115 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2116 DS_ROLE_BASIC_INFORMATION,
2117 &info,
2118 &werr);
2119 TALLOC_FREE(cli);
2121 if (NT_STATUS_IS_OK(status)) {
2122 result = werror_to_ntstatus(werr);
2124 if (!NT_STATUS_IS_OK(status)) {
2125 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2126 "on domain %s failed: (%s)\n",
2127 domain->name, nt_errstr(status)));
2129 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2130 * every opcode on the DSSETUP pipe, continue with
2131 * no_dssetup mode here as well to get domain->initialized
2132 * set - gd */
2134 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2135 goto no_dssetup;
2138 TALLOC_FREE(mem_ctx);
2139 return;
2142 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2143 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2144 domain->native_mode = True;
2145 } else {
2146 domain->native_mode = False;
2149 no_dssetup:
2150 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2151 &ndr_table_lsarpc, &cli);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2155 "PI_LSARPC on domain %s: (%s)\n",
2156 domain->name, nt_errstr(status)));
2157 TALLOC_FREE(cli);
2158 TALLOC_FREE(mem_ctx);
2159 return;
2162 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2163 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2165 if (NT_STATUS_IS_OK(status)) {
2166 /* This particular query is exactly what Win2k clients use
2167 to determine that the DC is active directory */
2168 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2169 &pol,
2170 LSA_POLICY_INFO_DNS,
2171 &lsa_info,
2172 &result);
2175 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2176 domain->active_directory = True;
2178 if (lsa_info->dns.name.string) {
2179 talloc_free(domain->name);
2180 domain->name = talloc_strdup(domain,
2181 lsa_info->dns.name.string);
2182 if (domain->name == NULL) {
2183 goto done;
2187 if (lsa_info->dns.dns_domain.string) {
2188 talloc_free(domain->alt_name);
2189 domain->alt_name =
2190 talloc_strdup(domain,
2191 lsa_info->dns.dns_domain.string);
2192 if (domain->alt_name == NULL) {
2193 goto done;
2197 /* See if we can set some domain trust flags about
2198 ourself */
2200 if (lsa_info->dns.dns_forest.string) {
2201 talloc_free(domain->forest_name);
2202 domain->forest_name =
2203 talloc_strdup(domain,
2204 lsa_info->dns.dns_forest.string);
2205 if (domain->forest_name == NULL) {
2206 goto done;
2209 if (strequal(domain->forest_name, domain->alt_name)) {
2210 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2214 if (lsa_info->dns.sid) {
2215 sid_copy(&domain->sid, lsa_info->dns.sid);
2217 } else {
2218 domain->active_directory = False;
2220 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2221 SEC_FLAG_MAXIMUM_ALLOWED,
2222 &pol);
2224 if (!NT_STATUS_IS_OK(status)) {
2225 goto done;
2228 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2229 &pol,
2230 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2231 &lsa_info,
2232 &result);
2233 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2235 if (lsa_info->account_domain.name.string) {
2236 talloc_free(domain->name);
2237 domain->name =
2238 talloc_strdup(domain,
2239 lsa_info->account_domain.name.string);
2242 if (lsa_info->account_domain.sid) {
2243 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2247 done:
2249 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2250 domain->name, domain->native_mode ? "" : "NOT "));
2252 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2253 domain->name, domain->active_directory ? "" : "NOT "));
2255 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2257 TALLOC_FREE(cli);
2259 TALLOC_FREE(mem_ctx);
2261 domain->initialized = True;
2264 /**********************************************************************
2265 Set the domain_flags (trust attributes, domain operating modes, etc...
2266 ***********************************************************************/
2268 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2270 /* we always have to contact our primary domain */
2272 if ( domain->primary ) {
2273 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2274 "primary domain\n"));
2275 set_dc_type_and_flags_connect( domain );
2276 return;
2279 /* Use our DC to get the information if possible */
2281 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2282 /* Otherwise, fallback to contacting the
2283 domain directly */
2284 set_dc_type_and_flags_connect( domain );
2287 return;
2292 /**********************************************************************
2293 ***********************************************************************/
2295 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2296 struct netlogon_creds_cli_context **ppdc)
2298 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2299 struct rpc_pipe_client *netlogon_pipe;
2301 *ppdc = NULL;
2303 if ((!IS_DC) && (!domain->primary)) {
2304 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2307 if (domain->conn.netlogon_creds != NULL) {
2308 if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2309 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2311 *ppdc = domain->conn.netlogon_creds;
2312 return NT_STATUS_OK;
2315 result = cm_connect_netlogon(domain, &netlogon_pipe);
2316 if (!NT_STATUS_IS_OK(result)) {
2317 return result;
2320 if (domain->conn.netlogon_creds == NULL) {
2321 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2324 if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2325 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2328 *ppdc = domain->conn.netlogon_creds;
2329 return NT_STATUS_OK;
2332 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2333 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2335 struct winbindd_cm_conn *conn;
2336 NTSTATUS status, result;
2337 struct netlogon_creds_cli_context *p_creds;
2338 char *machine_password = NULL;
2339 char *machine_account = NULL;
2340 const char *domain_name = NULL;
2342 if (sid_check_is_our_sam(&domain->sid)) {
2343 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2346 status = init_dc_connection_rpc(domain);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 return status;
2351 conn = &domain->conn;
2353 if (rpccli_is_connected(conn->samr_pipe)) {
2354 goto done;
2357 TALLOC_FREE(conn->samr_pipe);
2360 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2361 * sign and sealed pipe using the machine account password by
2362 * preference. If we can't - try schannel, if that fails, try
2363 * anonymous.
2366 if ((conn->cli->user_name[0] == '\0') ||
2367 (conn->cli->domain[0] == '\0') ||
2368 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2370 status = get_trust_creds(domain, &machine_password,
2371 &machine_account, NULL);
2372 if (!NT_STATUS_IS_OK(status)) {
2373 DEBUG(10, ("cm_connect_sam: No no user available for "
2374 "domain %s, trying schannel\n", conn->cli->domain));
2375 goto schannel;
2377 domain_name = domain->name;
2378 } else {
2379 machine_password = SMB_STRDUP(conn->cli->password);
2380 machine_account = SMB_STRDUP(conn->cli->user_name);
2381 domain_name = conn->cli->domain;
2384 if (!machine_password || !machine_account) {
2385 status = NT_STATUS_NO_MEMORY;
2386 goto done;
2389 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2390 authenticated SAMR pipe with sign & seal. */
2391 status = cli_rpc_pipe_open_spnego(conn->cli,
2392 &ndr_table_samr,
2393 NCACN_NP,
2394 GENSEC_OID_NTLMSSP,
2395 conn->auth_level,
2396 smbXcli_conn_remote_name(conn->cli->conn),
2397 domain_name,
2398 machine_account,
2399 machine_password,
2400 &conn->samr_pipe);
2402 if (!NT_STATUS_IS_OK(status)) {
2403 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2404 "pipe for domain %s using NTLMSSP "
2405 "authenticated pipe: user %s\\%s. Error was "
2406 "%s\n", domain->name, domain_name,
2407 machine_account, nt_errstr(status)));
2408 goto schannel;
2411 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2412 "domain %s using NTLMSSP authenticated "
2413 "pipe: user %s\\%s\n", domain->name,
2414 domain_name, machine_account));
2416 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2417 conn->samr_pipe->desthost,
2418 SEC_FLAG_MAXIMUM_ALLOWED,
2419 &conn->sam_connect_handle,
2420 &result);
2421 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2422 goto open_domain;
2424 if (NT_STATUS_IS_OK(status)) {
2425 status = result;
2428 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2429 "failed for domain %s, error was %s. Trying schannel\n",
2430 domain->name, nt_errstr(status) ));
2431 TALLOC_FREE(conn->samr_pipe);
2433 schannel:
2435 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2437 status = cm_get_schannel_creds(domain, &p_creds);
2438 if (!NT_STATUS_IS_OK(status)) {
2439 /* If this call fails - conn->cli can now be NULL ! */
2440 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2441 "for domain %s (error %s), trying anon\n",
2442 domain->name,
2443 nt_errstr(status) ));
2444 goto anonymous;
2446 status = cli_rpc_pipe_open_schannel_with_key
2447 (conn->cli, &ndr_table_samr, NCACN_NP,
2448 domain->name, p_creds, &conn->samr_pipe);
2450 if (!NT_STATUS_IS_OK(status)) {
2451 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2452 "domain %s using schannel. Error was %s\n",
2453 domain->name, nt_errstr(status) ));
2454 goto anonymous;
2456 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2457 "schannel.\n", domain->name ));
2459 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2460 conn->samr_pipe->desthost,
2461 SEC_FLAG_MAXIMUM_ALLOWED,
2462 &conn->sam_connect_handle,
2463 &result);
2464 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2465 goto open_domain;
2467 if (NT_STATUS_IS_OK(status)) {
2468 status = result;
2470 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2471 "for domain %s, error was %s. Trying anonymous\n",
2472 domain->name, nt_errstr(status) ));
2473 TALLOC_FREE(conn->samr_pipe);
2475 anonymous:
2477 /* Finally fall back to anonymous. */
2478 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2479 &conn->samr_pipe);
2481 if (!NT_STATUS_IS_OK(status)) {
2482 goto done;
2485 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2486 conn->samr_pipe->desthost,
2487 SEC_FLAG_MAXIMUM_ALLOWED,
2488 &conn->sam_connect_handle,
2489 &result);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2492 "for domain %s Error was %s\n",
2493 domain->name, nt_errstr(status) ));
2494 goto done;
2496 if (!NT_STATUS_IS_OK(result)) {
2497 status = result;
2498 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2499 "for domain %s Error was %s\n",
2500 domain->name, nt_errstr(result)));
2501 goto done;
2504 open_domain:
2505 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2506 mem_ctx,
2507 &conn->sam_connect_handle,
2508 SEC_FLAG_MAXIMUM_ALLOWED,
2509 &domain->sid,
2510 &conn->sam_domain_handle,
2511 &result);
2512 if (!NT_STATUS_IS_OK(status)) {
2513 goto done;
2516 status = result;
2517 done:
2519 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2521 * if we got access denied, we might just have no access rights
2522 * to talk to the remote samr server server (e.g. when we are a
2523 * PDC and we are connecting a w2k8 pdc via an interdomain
2524 * trust). In that case do not invalidate the whole connection
2525 * stack
2527 TALLOC_FREE(conn->samr_pipe);
2528 ZERO_STRUCT(conn->sam_domain_handle);
2529 return status;
2530 } else if (!NT_STATUS_IS_OK(status)) {
2531 invalidate_cm_connection(conn);
2532 return status;
2535 *cli = conn->samr_pipe;
2536 *sam_handle = conn->sam_domain_handle;
2537 SAFE_FREE(machine_password);
2538 SAFE_FREE(machine_account);
2539 return status;
2542 /**********************************************************************
2543 open an schanneld ncacn_ip_tcp connection to LSA
2544 ***********************************************************************/
2546 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2547 TALLOC_CTX *mem_ctx,
2548 struct rpc_pipe_client **cli)
2550 struct winbindd_cm_conn *conn;
2551 struct netlogon_creds_cli_context *creds;
2552 NTSTATUS status;
2554 DEBUG(10,("cm_connect_lsa_tcp\n"));
2556 status = init_dc_connection_rpc(domain);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 return status;
2561 conn = &domain->conn;
2563 if (conn->lsa_pipe_tcp &&
2564 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2565 conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY &&
2566 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2567 goto done;
2570 TALLOC_FREE(conn->lsa_pipe_tcp);
2572 status = cm_get_schannel_creds(domain, &creds);
2573 if (!NT_STATUS_IS_OK(status)) {
2574 goto done;
2577 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2578 &ndr_table_lsarpc,
2579 NCACN_IP_TCP,
2580 domain->name,
2581 creds,
2582 &conn->lsa_pipe_tcp);
2583 if (!NT_STATUS_IS_OK(status)) {
2584 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2585 nt_errstr(status)));
2586 goto done;
2589 done:
2590 if (!NT_STATUS_IS_OK(status)) {
2591 TALLOC_FREE(conn->lsa_pipe_tcp);
2592 return status;
2595 *cli = conn->lsa_pipe_tcp;
2597 return status;
2600 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2601 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2603 struct winbindd_cm_conn *conn;
2604 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2605 struct netlogon_creds_cli_context *p_creds;
2607 result = init_dc_connection_rpc(domain);
2608 if (!NT_STATUS_IS_OK(result))
2609 return result;
2611 conn = &domain->conn;
2613 if (rpccli_is_connected(conn->lsa_pipe)) {
2614 goto done;
2617 TALLOC_FREE(conn->lsa_pipe);
2619 if ((conn->cli->user_name[0] == '\0') ||
2620 (conn->cli->domain[0] == '\0') ||
2621 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2622 DEBUG(10, ("cm_connect_lsa: No no user available for "
2623 "domain %s, trying schannel\n", conn->cli->domain));
2624 goto schannel;
2627 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2628 * authenticated LSA pipe with sign & seal. */
2629 result = cli_rpc_pipe_open_spnego
2630 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2631 GENSEC_OID_NTLMSSP,
2632 conn->auth_level,
2633 smbXcli_conn_remote_name(conn->cli->conn),
2634 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2635 &conn->lsa_pipe);
2637 if (!NT_STATUS_IS_OK(result)) {
2638 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2639 "domain %s using NTLMSSP authenticated pipe: user "
2640 "%s\\%s. Error was %s. Trying schannel.\n",
2641 domain->name, conn->cli->domain,
2642 conn->cli->user_name, nt_errstr(result)));
2643 goto schannel;
2646 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2647 "NTLMSSP authenticated pipe: user %s\\%s\n",
2648 domain->name, conn->cli->domain, conn->cli->user_name ));
2650 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2651 SEC_FLAG_MAXIMUM_ALLOWED,
2652 &conn->lsa_policy);
2653 if (NT_STATUS_IS_OK(result)) {
2654 goto done;
2657 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2658 "schannel\n"));
2660 TALLOC_FREE(conn->lsa_pipe);
2662 schannel:
2664 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2666 result = cm_get_schannel_creds(domain, &p_creds);
2667 if (!NT_STATUS_IS_OK(result)) {
2668 /* If this call fails - conn->cli can now be NULL ! */
2669 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2670 "for domain %s (error %s), trying anon\n",
2671 domain->name,
2672 nt_errstr(result) ));
2673 goto anonymous;
2675 result = cli_rpc_pipe_open_schannel_with_key
2676 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2677 domain->name, p_creds, &conn->lsa_pipe);
2679 if (!NT_STATUS_IS_OK(result)) {
2680 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2681 "domain %s using schannel. Error was %s\n",
2682 domain->name, nt_errstr(result) ));
2683 goto anonymous;
2685 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2686 "schannel.\n", domain->name ));
2688 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2689 SEC_FLAG_MAXIMUM_ALLOWED,
2690 &conn->lsa_policy);
2691 if (NT_STATUS_IS_OK(result)) {
2692 goto done;
2695 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2696 "anonymous\n"));
2698 TALLOC_FREE(conn->lsa_pipe);
2700 anonymous:
2702 result = cli_rpc_pipe_open_noauth(conn->cli,
2703 &ndr_table_lsarpc,
2704 &conn->lsa_pipe);
2705 if (!NT_STATUS_IS_OK(result)) {
2706 goto done;
2709 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2710 SEC_FLAG_MAXIMUM_ALLOWED,
2711 &conn->lsa_policy);
2712 done:
2713 if (!NT_STATUS_IS_OK(result)) {
2714 invalidate_cm_connection(conn);
2715 return result;
2718 *cli = conn->lsa_pipe;
2719 *lsa_policy = conn->lsa_policy;
2720 return result;
2723 /****************************************************************************
2724 Open a LSA connection to a DC, suiteable for LSA lookup calls.
2725 ****************************************************************************/
2727 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
2728 TALLOC_CTX *mem_ctx,
2729 struct rpc_pipe_client **cli,
2730 struct policy_handle *lsa_policy)
2732 NTSTATUS status;
2734 if (domain->can_do_ncacn_ip_tcp) {
2735 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2736 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
2737 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
2738 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
2739 invalidate_cm_connection(&domain->conn);
2740 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2742 if (NT_STATUS_IS_OK(status)) {
2743 return status;
2747 * we tried twice to connect via ncan_ip_tcp and schannel and
2748 * failed - maybe it is a trusted domain we can't connect to ?
2749 * do not try tcp next time - gd
2751 domain->can_do_ncacn_ip_tcp = false;
2754 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
2756 return status;
2759 /****************************************************************************
2760 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2761 session key stored in conn->netlogon_pipe->dc->sess_key.
2762 ****************************************************************************/
2764 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2765 struct rpc_pipe_client **cli)
2767 struct messaging_context *msg_ctx = winbind_messaging_context();
2768 struct winbindd_cm_conn *conn;
2769 NTSTATUS result;
2770 enum netr_SchannelType sec_chan_type;
2771 const char *_account_name;
2772 const char *account_name;
2773 struct samr_Password current_nt_hash;
2774 struct samr_Password *previous_nt_hash = NULL;
2775 struct netlogon_creds_CredentialState *creds = NULL;
2776 bool ok;
2778 *cli = NULL;
2780 result = init_dc_connection_rpc(domain);
2781 if (!NT_STATUS_IS_OK(result)) {
2782 return result;
2785 conn = &domain->conn;
2787 if (rpccli_is_connected(conn->netlogon_pipe)) {
2788 *cli = conn->netlogon_pipe;
2789 return NT_STATUS_OK;
2792 TALLOC_FREE(conn->netlogon_pipe);
2793 conn->netlogon_flags = 0;
2794 TALLOC_FREE(conn->netlogon_creds);
2796 if ((!IS_DC) && (!domain->primary)) {
2797 goto no_schannel;
2800 ok = get_trust_pw_hash(domain->name,
2801 current_nt_hash.hash,
2802 &_account_name,
2803 &sec_chan_type);
2804 if (!ok) {
2805 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2808 account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name);
2809 if (account_name == NULL) {
2810 return NT_STATUS_NO_MEMORY;
2813 result = rpccli_create_netlogon_creds(domain->dcname,
2814 domain->name,
2815 account_name,
2816 sec_chan_type,
2817 msg_ctx,
2818 domain,
2819 &conn->netlogon_creds);
2820 if (!NT_STATUS_IS_OK(result)) {
2821 SAFE_FREE(previous_nt_hash);
2822 return result;
2825 result = rpccli_setup_netlogon_creds(conn->cli,
2826 conn->netlogon_creds,
2827 conn->netlogon_force_reauth,
2828 current_nt_hash,
2829 previous_nt_hash);
2830 conn->netlogon_force_reauth = false;
2831 SAFE_FREE(previous_nt_hash);
2832 if (!NT_STATUS_IS_OK(result)) {
2833 return result;
2836 result = netlogon_creds_cli_get(conn->netlogon_creds,
2837 talloc_tos(),
2838 &creds);
2839 if (!NT_STATUS_IS_OK(result)) {
2840 return result;
2842 conn->netlogon_flags = creds->negotiate_flags;
2843 TALLOC_FREE(creds);
2845 no_schannel:
2846 if (!(conn->netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2847 result = cli_rpc_pipe_open_noauth(conn->cli,
2848 &ndr_table_netlogon,
2849 &conn->netlogon_pipe);
2850 if (!NT_STATUS_IS_OK(result)) {
2851 invalidate_cm_connection(conn);
2852 return result;
2855 *cli = conn->netlogon_pipe;
2856 return NT_STATUS_OK;
2859 /* Using the credentials from the first pipe, open a signed and sealed
2860 second netlogon pipe. The session key is stored in the schannel
2861 part of the new pipe auth struct.
2864 result = cli_rpc_pipe_open_schannel_with_key(
2865 conn->cli, &ndr_table_netlogon, NCACN_NP,
2866 domain->name,
2867 conn->netlogon_creds,
2868 &conn->netlogon_pipe);
2869 if (!NT_STATUS_IS_OK(result)) {
2870 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2871 "was %s\n", nt_errstr(result)));
2873 invalidate_cm_connection(conn);
2874 return result;
2877 *cli = conn->netlogon_pipe;
2878 return NT_STATUS_OK;
2881 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2882 void *private_data,
2883 uint32_t msg_type,
2884 struct server_id server_id,
2885 DATA_BLOB *data)
2887 struct winbindd_domain *domain;
2888 char *freeit = NULL;
2889 char *addr;
2891 if ((data == NULL)
2892 || (data->data == NULL)
2893 || (data->length == 0)
2894 || (data->data[data->length-1] != '\0')) {
2895 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2896 "string\n"));
2897 return;
2900 addr = (char *)data->data;
2901 DEBUG(10, ("IP %s dropped\n", addr));
2903 if (!is_ipaddress(addr)) {
2904 char *slash;
2906 * Some code sends us ip addresses with the /netmask
2907 * suffix
2909 slash = strchr(addr, '/');
2910 if (slash == NULL) {
2911 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2912 addr));
2913 return;
2915 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2916 if (freeit == NULL) {
2917 DEBUG(1, ("talloc failed\n"));
2918 return;
2920 addr = freeit;
2921 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2924 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2925 char sockaddr[INET6_ADDRSTRLEN];
2927 if (!cli_state_is_connected(domain->conn.cli)) {
2928 continue;
2931 print_sockaddr(sockaddr, sizeof(sockaddr),
2932 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
2934 if (strequal(sockaddr, addr)) {
2935 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2938 TALLOC_FREE(freeit);