s3-winbind: Send online/offline message of the domain to the parent.
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob1883ddcc75e43426b23e90a8a9cd4c45121d8311
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"
83 #undef DBGC_CLASS
84 #define DBGC_CLASS DBGC_WINBIND
86 struct dc_name_ip {
87 fstring name;
88 struct sockaddr_storage ss;
91 extern struct winbindd_methods reconnect_methods;
92 extern bool override_logfile;
94 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
95 static void set_dc_type_and_flags( struct winbindd_domain *domain );
96 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
97 struct dc_name_ip **dcs, int *num_dcs);
99 /****************************************************************
100 Child failed to find DC's. Reschedule check.
101 ****************************************************************/
103 static void msg_failed_to_go_online(struct messaging_context *msg,
104 void *private_data,
105 uint32_t msg_type,
106 struct server_id server_id,
107 DATA_BLOB *data)
109 struct winbindd_domain *domain;
110 const char *domainname = (const char *)data->data;
112 if (data->data == NULL || data->length == 0) {
113 return;
116 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
118 for (domain = domain_list(); domain; domain = domain->next) {
119 if (domain->internal) {
120 continue;
123 if (strequal(domain->name, domainname)) {
124 if (domain->online) {
125 /* We're already online, ignore. */
126 DEBUG(5,("msg_fail_to_go_online: domain %s "
127 "already online.\n", domainname));
128 continue;
131 /* Reschedule the online check. */
132 set_domain_offline(domain);
133 break;
138 /****************************************************************
139 Actually cause a reconnect from a message.
140 ****************************************************************/
142 static void msg_try_to_go_online(struct messaging_context *msg,
143 void *private_data,
144 uint32_t msg_type,
145 struct server_id server_id,
146 DATA_BLOB *data)
148 struct winbindd_domain *domain;
149 const char *domainname = (const char *)data->data;
151 if (data->data == NULL || data->length == 0) {
152 return;
155 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
157 for (domain = domain_list(); domain; domain = domain->next) {
158 if (domain->internal) {
159 continue;
162 if (strequal(domain->name, domainname)) {
164 if (domain->online) {
165 /* We're already online, ignore. */
166 DEBUG(5,("msg_try_to_go_online: domain %s "
167 "already online.\n", domainname));
168 continue;
171 /* This call takes care of setting the online
172 flag to true if we connected, or re-adding
173 the offline handler if false. Bypasses online
174 check so always does network calls. */
176 init_dc_connection_network(domain);
177 break;
182 /****************************************************************
183 Fork a child to try and contact a DC. Do this as contacting a
184 DC requires blocking lookups and we don't want to block our
185 parent.
186 ****************************************************************/
188 static bool fork_child_dc_connect(struct winbindd_domain *domain)
190 struct dc_name_ip *dcs = NULL;
191 int num_dcs = 0;
192 TALLOC_CTX *mem_ctx = NULL;
193 pid_t parent_pid = getpid();
194 char *lfile = NULL;
195 NTSTATUS status;
197 if (domain->dc_probe_pid != (pid_t)-1) {
199 * We might already have a DC probe
200 * child working, check.
202 if (process_exists_by_pid(domain->dc_probe_pid)) {
203 DEBUG(10,("fork_child_dc_connect: pid %u already "
204 "checking for DC's.\n",
205 (unsigned int)domain->dc_probe_pid));
206 return true;
208 domain->dc_probe_pid = (pid_t)-1;
211 domain->dc_probe_pid = fork();
213 if (domain->dc_probe_pid == (pid_t)-1) {
214 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
215 return False;
218 if (domain->dc_probe_pid != (pid_t)0) {
219 /* Parent */
220 messaging_register(winbind_messaging_context(), NULL,
221 MSG_WINBIND_TRY_TO_GO_ONLINE,
222 msg_try_to_go_online);
223 messaging_register(winbind_messaging_context(), NULL,
224 MSG_WINBIND_FAILED_TO_GO_ONLINE,
225 msg_failed_to_go_online);
226 return True;
229 /* Child. */
231 /* Leave messages blocked - we will never process one. */
233 if (!override_logfile) {
234 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
235 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
236 _exit(1);
240 status = winbindd_reinit_after_fork(NULL, lfile);
241 if (!NT_STATUS_IS_OK(status)) {
242 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
243 nt_errstr(status)));
244 messaging_send_buf(winbind_messaging_context(),
245 pid_to_procid(parent_pid),
246 MSG_WINBIND_FAILED_TO_GO_ONLINE,
247 (uint8 *)domain->name,
248 strlen(domain->name)+1);
249 _exit(1);
251 SAFE_FREE(lfile);
253 mem_ctx = talloc_init("fork_child_dc_connect");
254 if (!mem_ctx) {
255 DEBUG(0,("talloc_init failed.\n"));
256 messaging_send_buf(winbind_messaging_context(),
257 pid_to_procid(parent_pid),
258 MSG_WINBIND_FAILED_TO_GO_ONLINE,
259 (uint8 *)domain->name,
260 strlen(domain->name)+1);
261 _exit(1);
264 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
265 /* Still offline ? Can't find DC's. */
266 messaging_send_buf(winbind_messaging_context(),
267 pid_to_procid(parent_pid),
268 MSG_WINBIND_FAILED_TO_GO_ONLINE,
269 (uint8 *)domain->name,
270 strlen(domain->name)+1);
271 _exit(0);
274 /* We got a DC. Send a message to our parent to get it to
275 try and do the same. */
277 messaging_send_buf(winbind_messaging_context(),
278 pid_to_procid(parent_pid),
279 MSG_WINBIND_TRY_TO_GO_ONLINE,
280 (uint8 *)domain->name,
281 strlen(domain->name)+1);
282 _exit(0);
285 /****************************************************************
286 Handler triggered if we're offline to try and detect a DC.
287 ****************************************************************/
289 static void check_domain_online_handler(struct event_context *ctx,
290 struct timed_event *te,
291 struct timeval now,
292 void *private_data)
294 struct winbindd_domain *domain =
295 (struct winbindd_domain *)private_data;
297 DEBUG(10,("check_domain_online_handler: called for domain "
298 "%s (online = %s)\n", domain->name,
299 domain->online ? "True" : "False" ));
301 TALLOC_FREE(domain->check_online_event);
303 /* Are we still in "startup" mode ? */
305 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
306 /* No longer in "startup" mode. */
307 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
308 domain->name ));
309 domain->startup = False;
312 /* We've been told to stay offline, so stay
313 that way. */
315 if (get_global_winbindd_state_offline()) {
316 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
317 domain->name ));
318 return;
321 /* Fork a child to test if it can contact a DC.
322 If it can then send ourselves a message to
323 cause a reconnect. */
325 fork_child_dc_connect(domain);
328 /****************************************************************
329 If we're still offline setup the timeout check.
330 ****************************************************************/
332 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
334 int wbr = lp_winbind_reconnect_delay();
336 if (domain->startup) {
337 domain->check_online_timeout = 10;
338 } else if (domain->check_online_timeout < wbr) {
339 domain->check_online_timeout = wbr;
343 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
344 void *private_data,
345 uint32_t msg_type,
346 struct server_id server_id,
347 DATA_BLOB *data)
349 const char *domain_name = (const char *)data->data;
350 struct winbindd_domain *domain;
352 domain = find_domain_from_name_noinit(domain_name);
353 if (domain == NULL) {
354 return;
357 domain->online = false;
359 DEBUG(10, ("Domain %s is marked as offline now.\n",
360 domain_name));
363 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
364 void *private_data,
365 uint32_t msg_type,
366 struct server_id server_id,
367 DATA_BLOB *data)
369 const char *domain_name = (const char *)data->data;
370 struct winbindd_domain *domain;
372 domain = find_domain_from_name_noinit(domain_name);
373 if (domain == NULL) {
374 return;
377 domain->online = true;
379 DEBUG(10, ("Domain %s is marked as online now.\n",
380 domain_name));
383 /****************************************************************
384 Set domain offline and also add handler to put us back online
385 if we detect a DC.
386 ****************************************************************/
388 void set_domain_offline(struct winbindd_domain *domain)
390 pid_t parent_pid = getppid();
392 DEBUG(10,("set_domain_offline: called for domain %s\n",
393 domain->name ));
395 TALLOC_FREE(domain->check_online_event);
397 if (domain->internal) {
398 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
399 domain->name ));
400 return;
403 domain->online = False;
405 /* Offline domains are always initialized. They're
406 re-initialized when they go back online. */
408 domain->initialized = True;
410 /* We only add the timeout handler that checks and
411 allows us to go back online when we've not
412 been told to remain offline. */
414 if (get_global_winbindd_state_offline()) {
415 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
416 domain->name ));
417 return;
420 /* If we're in startup mode, check again in 10 seconds, not in
421 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
423 calc_new_online_timeout_check(domain);
425 domain->check_online_event = event_add_timed(winbind_event_context(),
426 NULL,
427 timeval_current_ofs(domain->check_online_timeout,0),
428 check_domain_online_handler,
429 domain);
431 /* The above *has* to succeed for winbindd to work. */
432 if (!domain->check_online_event) {
433 smb_panic("set_domain_offline: failed to add online handler");
436 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
437 domain->name ));
439 /* Send a message to the parent that the domain is offline. */
440 if (parent_pid > 1 && !domain->internal) {
441 messaging_send_buf(winbind_messaging_context(),
442 pid_to_procid(parent_pid),
443 MSG_WINBIND_DOMAIN_OFFLINE,
444 (uint8 *)domain->name,
445 strlen(domain->name) + 1);
448 /* Send an offline message to the idmap child when our
449 primary domain goes offline */
451 if ( domain->primary ) {
452 struct winbindd_child *idmap = idmap_child();
454 if ( idmap->pid != 0 ) {
455 messaging_send_buf(winbind_messaging_context(),
456 pid_to_procid(idmap->pid),
457 MSG_WINBIND_OFFLINE,
458 (uint8 *)domain->name,
459 strlen(domain->name)+1);
463 return;
466 /****************************************************************
467 Set domain online - if allowed.
468 ****************************************************************/
470 static void set_domain_online(struct winbindd_domain *domain)
472 pid_t parent_pid = getppid();
474 DEBUG(10,("set_domain_online: called for domain %s\n",
475 domain->name ));
477 if (domain->internal) {
478 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
479 domain->name ));
480 return;
483 if (get_global_winbindd_state_offline()) {
484 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
485 domain->name ));
486 return;
489 winbindd_set_locator_kdc_envs(domain);
491 /* If we are waiting to get a krb5 ticket, trigger immediately. */
492 ccache_regain_all_now();
494 /* Ok, we're out of any startup mode now... */
495 domain->startup = False;
497 if (domain->online == False) {
498 /* We were offline - now we're online. We default to
499 using the MS-RPC backend if we started offline,
500 and if we're going online for the first time we
501 should really re-initialize the backends and the
502 checks to see if we're talking to an AD or NT domain.
505 domain->initialized = False;
507 /* 'reconnect_methods' is the MS-RPC backend. */
508 if (domain->backend == &reconnect_methods) {
509 domain->backend = NULL;
513 /* Ensure we have no online timeout checks. */
514 domain->check_online_timeout = 0;
515 TALLOC_FREE(domain->check_online_event);
517 /* Ensure we ignore any pending child messages. */
518 messaging_deregister(winbind_messaging_context(),
519 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
520 messaging_deregister(winbind_messaging_context(),
521 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
523 domain->online = True;
525 /* Send a message to the parent that the domain is online. */
526 if (parent_pid > 1 && !domain->internal) {
527 messaging_send_buf(winbind_messaging_context(),
528 pid_to_procid(parent_pid),
529 MSG_WINBIND_DOMAIN_ONLINE,
530 (uint8 *)domain->name,
531 strlen(domain->name) + 1);
534 /* Send an online message to the idmap child when our
535 primary domain comes online */
537 if ( domain->primary ) {
538 struct winbindd_child *idmap = idmap_child();
540 if ( idmap->pid != 0 ) {
541 messaging_send_buf(winbind_messaging_context(),
542 pid_to_procid(idmap->pid),
543 MSG_WINBIND_ONLINE,
544 (uint8 *)domain->name,
545 strlen(domain->name)+1);
549 return;
552 /****************************************************************
553 Requested to set a domain online.
554 ****************************************************************/
556 void set_domain_online_request(struct winbindd_domain *domain)
558 struct timeval tev;
560 DEBUG(10,("set_domain_online_request: called for domain %s\n",
561 domain->name ));
563 if (get_global_winbindd_state_offline()) {
564 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
565 domain->name ));
566 return;
569 if (domain->internal) {
570 DEBUG(10, ("set_domain_online_request: Internal domains are "
571 "always online\n"));
572 return;
575 /* We've been told it's safe to go online and
576 try and connect to a DC. But I don't believe it
577 because network manager seems to lie.
578 Wait at least 5 seconds. Heuristics suck... */
581 GetTimeOfDay(&tev);
583 /* Go into "startup" mode again. */
584 domain->startup_time = time_mono(NULL);
585 domain->startup = True;
587 tev.tv_sec += 5;
589 if (!domain->check_online_event) {
590 /* If we've come from being globally offline we
591 don't have a check online event handler set.
592 We need to add one now we're trying to go
593 back online. */
595 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
596 domain->name ));
599 TALLOC_FREE(domain->check_online_event);
601 domain->check_online_event = event_add_timed(winbind_event_context(),
602 NULL,
603 tev,
604 check_domain_online_handler,
605 domain);
607 /* The above *has* to succeed for winbindd to work. */
608 if (!domain->check_online_event) {
609 smb_panic("set_domain_online_request: failed to add online handler");
613 /****************************************************************
614 Add -ve connection cache entries for domain and realm.
615 ****************************************************************/
617 static void winbind_add_failed_connection_entry(
618 const struct winbindd_domain *domain,
619 const char *server,
620 NTSTATUS result)
622 add_failed_connection_entry(domain->name, server, result);
623 /* If this was the saf name for the last thing we talked to,
624 remove it. */
625 saf_delete(domain->name);
626 if (*domain->alt_name) {
627 add_failed_connection_entry(domain->alt_name, server, result);
628 saf_delete(domain->alt_name);
630 winbindd_unset_locator_kdc_env(domain);
633 /* Choose between anonymous or authenticated connections. We need to use
634 an authenticated connection if DCs have the RestrictAnonymous registry
635 entry set > 0, or the "Additional restrictions for anonymous
636 connections" set in the win2k Local Security Policy.
638 Caller to free() result in domain, username, password
641 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
643 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
644 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
645 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
647 if (*username && **username) {
649 if (!*domain || !**domain)
650 *domain = smb_xstrdup(lp_workgroup());
652 if (!*password || !**password)
653 *password = smb_xstrdup("");
655 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
656 *domain, *username));
658 } else {
659 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
660 *username = smb_xstrdup("");
661 *domain = smb_xstrdup("");
662 *password = smb_xstrdup("");
666 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
667 fstring dcname,
668 struct sockaddr_storage *dc_ss)
670 struct winbindd_domain *our_domain = NULL;
671 struct rpc_pipe_client *netlogon_pipe = NULL;
672 NTSTATUS result;
673 WERROR werr;
674 TALLOC_CTX *mem_ctx;
675 unsigned int orig_timeout;
676 const char *tmp = NULL;
677 const char *p;
678 struct dcerpc_binding_handle *b;
680 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
681 * moment.... */
683 if (IS_DC) {
684 return False;
687 if (domain->primary) {
688 return False;
691 our_domain = find_our_domain();
693 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
694 return False;
697 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
698 if (!NT_STATUS_IS_OK(result)) {
699 talloc_destroy(mem_ctx);
700 return False;
703 b = netlogon_pipe->binding_handle;
705 /* This call can take a long time - allow the server to time out.
706 35 seconds should do it. */
708 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
710 if (our_domain->active_directory) {
711 struct netr_DsRGetDCNameInfo *domain_info = NULL;
713 result = dcerpc_netr_DsRGetDCName(b,
714 mem_ctx,
715 our_domain->dcname,
716 domain->name,
717 NULL,
718 NULL,
719 DS_RETURN_DNS_NAME,
720 &domain_info,
721 &werr);
722 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
723 tmp = talloc_strdup(
724 mem_ctx, domain_info->dc_unc);
725 if (tmp == NULL) {
726 DEBUG(0, ("talloc_strdup failed\n"));
727 talloc_destroy(mem_ctx);
728 return false;
730 if (strlen(domain->alt_name) == 0) {
731 fstrcpy(domain->alt_name,
732 domain_info->domain_name);
734 if (strlen(domain->forest_name) == 0) {
735 fstrcpy(domain->forest_name,
736 domain_info->forest_name);
739 } else {
740 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
741 our_domain->dcname,
742 domain->name,
743 &tmp,
744 &werr);
747 /* And restore our original timeout. */
748 rpccli_set_timeout(netlogon_pipe, orig_timeout);
750 if (!NT_STATUS_IS_OK(result)) {
751 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
752 nt_errstr(result)));
753 talloc_destroy(mem_ctx);
754 return false;
757 if (!W_ERROR_IS_OK(werr)) {
758 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
759 win_errstr(werr)));
760 talloc_destroy(mem_ctx);
761 return false;
764 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
765 p = strip_hostname(tmp);
767 fstrcpy(dcname, p);
769 talloc_destroy(mem_ctx);
771 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
773 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
774 return False;
777 return True;
781 * Helper function to assemble trust password and account name
783 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
784 char **machine_password,
785 char **machine_account,
786 char **machine_krb5_principal)
788 const char *account_name;
789 const char *name = NULL;
791 /* If we are a DC and this is not our own domain */
793 if (IS_DC) {
794 name = domain->name;
795 } else {
796 struct winbindd_domain *our_domain = find_our_domain();
798 if (!our_domain)
799 return NT_STATUS_INVALID_SERVER_STATE;
801 name = our_domain->name;
804 if (!get_trust_pw_clear(name, machine_password,
805 &account_name, NULL))
807 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
810 if ((machine_account != NULL) &&
811 (asprintf(machine_account, "%s$", account_name) == -1))
813 return NT_STATUS_NO_MEMORY;
816 /* For now assume our machine account only exists in our domain */
818 if (machine_krb5_principal != NULL)
820 struct winbindd_domain *our_domain = find_our_domain();
822 if (!our_domain) {
823 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
826 if (asprintf(machine_krb5_principal, "%s$@%s",
827 account_name, our_domain->alt_name) == -1)
829 return NT_STATUS_NO_MEMORY;
832 if (!strupper_m(*machine_krb5_principal)) {
833 SAFE_FREE(machine_krb5_principal);
834 return NT_STATUS_INVALID_PARAMETER;
838 return NT_STATUS_OK;
841 /************************************************************************
842 Given a fd with a just-connected TCP connection to a DC, open a connection
843 to the pipe.
844 ************************************************************************/
846 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
847 const int sockfd,
848 const char *controller,
849 struct cli_state **cli,
850 bool *retry)
852 bool try_spnego = false;
853 bool try_ipc_auth = false;
854 char *machine_password = NULL;
855 char *machine_krb5_principal = NULL;
856 char *machine_account = NULL;
857 char *ipc_username = NULL;
858 char *ipc_domain = NULL;
859 char *ipc_password = NULL;
860 int flags = 0;
861 uint16_t sec_mode = 0;
863 struct named_mutex *mutex;
865 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
867 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
868 controller, domain->name ));
870 *retry = True;
872 mutex = grab_named_mutex(talloc_tos(), controller,
873 WINBIND_SERVER_MUTEX_WAIT_TIME);
874 if (mutex == NULL) {
875 close(sockfd);
876 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
877 controller));
878 result = NT_STATUS_POSSIBLE_DEADLOCK;
879 goto done;
882 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
884 *cli = cli_state_create(NULL, sockfd,
885 controller, domain->alt_name,
886 SMB_SIGNING_DEFAULT, flags);
887 if (*cli == NULL) {
888 close(sockfd);
889 DEBUG(1, ("Could not cli_initialize\n"));
890 result = NT_STATUS_NO_MEMORY;
891 goto done;
894 cli_set_timeout(*cli, 10000); /* 10 seconds */
896 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout, PROTOCOL_CORE,
897 PROTOCOL_LATEST);
899 if (!NT_STATUS_IS_OK(result)) {
900 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
901 goto done;
904 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
905 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
906 try_spnego = true;
907 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
908 try_spnego = true;
911 if (!is_dc_trusted_domain_situation(domain->name) && try_spnego) {
912 result = get_trust_creds(domain, &machine_password,
913 &machine_account,
914 &machine_krb5_principal);
915 if (!NT_STATUS_IS_OK(result)) {
916 goto anon_fallback;
919 if (lp_security() == SEC_ADS) {
921 /* Try a krb5 session */
923 (*cli)->use_kerberos = True;
924 DEBUG(5, ("connecting to %s from %s with kerberos principal "
925 "[%s] and realm [%s]\n", controller, lp_netbios_name(),
926 machine_krb5_principal, domain->alt_name));
928 winbindd_set_locator_kdc_envs(domain);
930 result = cli_session_setup(*cli,
931 machine_krb5_principal,
932 machine_password,
933 strlen(machine_password)+1,
934 machine_password,
935 strlen(machine_password)+1,
936 lp_workgroup());
938 if (!NT_STATUS_IS_OK(result)) {
939 DEBUG(4,("failed kerberos session setup with %s\n",
940 nt_errstr(result)));
943 if (NT_STATUS_IS_OK(result)) {
944 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
945 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
946 if (!NT_STATUS_IS_OK(result)) {
947 goto done;
949 goto session_setup_done;
953 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
954 (*cli)->use_kerberos = False;
956 DEBUG(5, ("connecting to %s from %s with username "
957 "[%s]\\[%s]\n", controller, lp_netbios_name(),
958 lp_workgroup(), machine_account));
960 result = cli_session_setup(*cli,
961 machine_account,
962 machine_password,
963 strlen(machine_password)+1,
964 machine_password,
965 strlen(machine_password)+1,
966 lp_workgroup());
967 if (!NT_STATUS_IS_OK(result)) {
968 DEBUG(4, ("authenticated session setup failed with %s\n",
969 nt_errstr(result)));
972 if (NT_STATUS_IS_OK(result)) {
973 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
974 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
975 if (!NT_STATUS_IS_OK(result)) {
976 goto done;
978 goto session_setup_done;
982 /* Fall back to non-kerberos session setup with auth_user */
984 (*cli)->use_kerberos = False;
986 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
988 sec_mode = smb1cli_conn_server_security_mode((*cli)->conn);
990 try_ipc_auth = false;
991 if (try_spnego) {
992 try_ipc_auth = true;
993 } else if (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
994 try_ipc_auth = true;
997 if (try_ipc_auth && (strlen(ipc_username) > 0)) {
999 /* Only try authenticated if we have a username */
1001 DEBUG(5, ("connecting to %s from %s with username "
1002 "[%s]\\[%s]\n", controller, lp_netbios_name(),
1003 ipc_domain, ipc_username));
1005 if (NT_STATUS_IS_OK(cli_session_setup(
1006 *cli, ipc_username,
1007 ipc_password, strlen(ipc_password)+1,
1008 ipc_password, strlen(ipc_password)+1,
1009 ipc_domain))) {
1010 /* Successful logon with given username. */
1011 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
1012 if (!NT_STATUS_IS_OK(result)) {
1013 goto done;
1015 goto session_setup_done;
1016 } else {
1017 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
1018 ipc_domain, ipc_username ));
1022 anon_fallback:
1024 /* Fall back to anonymous connection, this might fail later */
1025 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
1026 "connection for DC %s\n",
1027 controller ));
1029 result = cli_session_setup(*cli, "", NULL, 0, NULL, 0, "");
1030 if (NT_STATUS_IS_OK(result)) {
1031 DEBUG(5, ("Connected anonymously\n"));
1032 result = cli_init_creds(*cli, "", "", "");
1033 if (!NT_STATUS_IS_OK(result)) {
1034 goto done;
1036 goto session_setup_done;
1039 /* We can't session setup */
1040 goto done;
1042 session_setup_done:
1045 * This should be a short term hack until
1046 * dynamic re-authentication is implemented.
1048 * See Bug 9175 - winbindd doesn't recover from
1049 * NT_STATUS_NETWORK_SESSION_EXPIRED
1051 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1052 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1055 /* cache the server name for later connections */
1057 saf_store(domain->name, controller);
1058 if (domain->alt_name && (*cli)->use_kerberos) {
1059 saf_store(domain->alt_name, controller);
1062 winbindd_set_locator_kdc_envs(domain);
1064 result = cli_tree_connect(*cli, "IPC$", "IPC", "", 0);
1066 if (!NT_STATUS_IS_OK(result)) {
1067 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1068 goto done;
1071 TALLOC_FREE(mutex);
1072 *retry = False;
1074 /* set the domain if empty; needed for schannel connections */
1075 if ( !(*cli)->domain[0] ) {
1076 result = cli_set_domain((*cli), domain->name);
1077 if (!NT_STATUS_IS_OK(result)) {
1078 SAFE_FREE(ipc_username);
1079 SAFE_FREE(ipc_domain);
1080 SAFE_FREE(ipc_password);
1081 return result;
1085 result = NT_STATUS_OK;
1087 done:
1088 TALLOC_FREE(mutex);
1089 SAFE_FREE(machine_account);
1090 SAFE_FREE(machine_password);
1091 SAFE_FREE(machine_krb5_principal);
1092 SAFE_FREE(ipc_username);
1093 SAFE_FREE(ipc_domain);
1094 SAFE_FREE(ipc_password);
1096 if (!NT_STATUS_IS_OK(result)) {
1097 winbind_add_failed_connection_entry(domain, controller, result);
1098 if ((*cli) != NULL) {
1099 cli_shutdown(*cli);
1100 *cli = NULL;
1104 return result;
1107 /*******************************************************************
1108 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1109 array.
1111 Keeps the list unique by not adding duplicate entries.
1113 @param[in] mem_ctx talloc memory context to allocate from
1114 @param[in] domain_name domain of the DC
1115 @param[in] dcname name of the DC to add to the list
1116 @param[in] pss Internet address and port pair to add to the list
1117 @param[in,out] dcs array of dc_name_ip structures to add to
1118 @param[in,out] num_dcs number of dcs returned in the dcs array
1119 @return true if the list was added to, false otherwise
1120 *******************************************************************/
1122 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1123 const char *dcname, struct sockaddr_storage *pss,
1124 struct dc_name_ip **dcs, int *num)
1126 int i = 0;
1128 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1129 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1130 return False;
1133 /* Make sure there's no duplicates in the list */
1134 for (i=0; i<*num; i++)
1135 if (sockaddr_equal(
1136 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1137 (struct sockaddr *)(void *)pss))
1138 return False;
1140 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1142 if (*dcs == NULL)
1143 return False;
1145 fstrcpy((*dcs)[*num].name, dcname);
1146 (*dcs)[*num].ss = *pss;
1147 *num += 1;
1148 return True;
1151 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1152 struct sockaddr_storage *pss, uint16 port,
1153 struct sockaddr_storage **addrs, int *num)
1155 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1157 if (*addrs == NULL) {
1158 *num = 0;
1159 return False;
1162 (*addrs)[*num] = *pss;
1163 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1165 *num += 1;
1166 return True;
1169 /*******************************************************************
1170 convert an ip to a name
1171 *******************************************************************/
1173 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1174 const struct winbindd_domain *domain,
1175 struct sockaddr_storage *pss,
1176 fstring name )
1178 struct ip_service ip_list;
1179 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1180 NTSTATUS status;
1181 const char *dc_name;
1183 ip_list.ss = *pss;
1184 ip_list.port = 0;
1186 #ifdef HAVE_ADS
1187 /* For active directory servers, try to get the ldap server name.
1188 None of these failures should be considered critical for now */
1190 if (lp_security() == SEC_ADS) {
1191 ADS_STRUCT *ads;
1192 ADS_STATUS ads_status;
1193 char addr[INET6_ADDRSTRLEN];
1195 print_sockaddr(addr, sizeof(addr), pss);
1197 ads = ads_init(domain->alt_name, domain->name, addr);
1198 ads->auth.flags |= ADS_AUTH_NO_BIND;
1200 ads_status = ads_connect(ads);
1201 if (ADS_ERR_OK(ads_status)) {
1202 /* We got a cldap packet. */
1203 fstrcpy(name, ads->config.ldap_server_name);
1204 namecache_store(name, 0x20, 1, &ip_list);
1206 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1208 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1209 if (ads_closest_dc(ads)) {
1210 char *sitename = sitename_fetch(ads->config.realm);
1212 /* We're going to use this KDC for this realm/domain.
1213 If we are using sites, then force the krb5 libs
1214 to use this KDC. */
1216 create_local_private_krb5_conf_for_domain(domain->alt_name,
1217 domain->name,
1218 sitename,
1219 pss,
1220 name);
1222 SAFE_FREE(sitename);
1223 } else {
1224 /* use an off site KDC */
1225 create_local_private_krb5_conf_for_domain(domain->alt_name,
1226 domain->name,
1227 NULL,
1228 pss,
1229 name);
1231 winbindd_set_locator_kdc_envs(domain);
1233 /* Ensure we contact this DC also. */
1234 saf_store( domain->name, name);
1235 saf_store( domain->alt_name, name);
1238 ads_destroy( &ads );
1239 return True;
1242 ads_destroy( &ads );
1243 return false;
1245 #endif
1247 status = nbt_getdc(winbind_messaging_context(), 10, pss, domain->name,
1248 &domain->sid, nt_version, mem_ctx, &nt_version,
1249 &dc_name, NULL);
1250 if (NT_STATUS_IS_OK(status)) {
1251 fstrcpy(name, dc_name);
1252 namecache_store(name, 0x20, 1, &ip_list);
1253 return True;
1256 /* try node status request */
1258 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1259 namecache_store(name, 0x20, 1, &ip_list);
1260 return True;
1262 return False;
1265 /*******************************************************************
1266 Retrieve a list of IP addresses for domain controllers.
1268 The array is sorted in the preferred connection order.
1270 @param[in] mem_ctx talloc memory context to allocate from
1271 @param[in] domain domain to retrieve DCs for
1272 @param[out] dcs array of dcs that will be returned
1273 @param[out] num_dcs number of dcs returned in the dcs array
1274 @return always true
1275 *******************************************************************/
1277 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1278 struct dc_name_ip **dcs, int *num_dcs)
1280 fstring dcname;
1281 struct sockaddr_storage ss;
1282 struct ip_service *ip_list = NULL;
1283 int iplist_size = 0;
1284 int i;
1285 bool is_our_domain;
1286 enum security_types sec = (enum security_types)lp_security();
1288 is_our_domain = strequal(domain->name, lp_workgroup());
1290 /* If not our domain, get the preferred DC, by asking our primary DC */
1291 if ( !is_our_domain
1292 && get_dc_name_via_netlogon(domain, dcname, &ss)
1293 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1294 num_dcs) )
1296 char addr[INET6_ADDRSTRLEN];
1297 print_sockaddr(addr, sizeof(addr), &ss);
1298 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1299 dcname, addr));
1300 return True;
1303 if (sec == SEC_ADS) {
1304 char *sitename = NULL;
1306 /* We need to make sure we know the local site before
1307 doing any DNS queries, as this will restrict the
1308 get_sorted_dc_list() call below to only fetching
1309 DNS records for the correct site. */
1311 /* Find any DC to get the site record.
1312 We deliberately don't care about the
1313 return here. */
1315 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1317 sitename = sitename_fetch(domain->alt_name);
1318 if (sitename) {
1320 /* Do the site-specific AD dns lookup first. */
1321 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1322 &iplist_size, True);
1324 /* Add ips to the DC array. We don't look up the name
1325 of the DC in this function, but we fill in the char*
1326 of the ip now to make the failed connection cache
1327 work */
1328 for ( i=0; i<iplist_size; i++ ) {
1329 char addr[INET6_ADDRSTRLEN];
1330 print_sockaddr(addr, sizeof(addr),
1331 &ip_list[i].ss);
1332 add_one_dc_unique(mem_ctx,
1333 domain->name,
1334 addr,
1335 &ip_list[i].ss,
1336 dcs,
1337 num_dcs);
1340 SAFE_FREE(ip_list);
1341 SAFE_FREE(sitename);
1342 iplist_size = 0;
1345 /* Now we add DCs from the main AD DNS lookup. */
1346 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1347 &iplist_size, True);
1349 for ( i=0; i<iplist_size; i++ ) {
1350 char addr[INET6_ADDRSTRLEN];
1351 print_sockaddr(addr, sizeof(addr),
1352 &ip_list[i].ss);
1353 add_one_dc_unique(mem_ctx,
1354 domain->name,
1355 addr,
1356 &ip_list[i].ss,
1357 dcs,
1358 num_dcs);
1361 SAFE_FREE(ip_list);
1362 iplist_size = 0;
1365 /* Try standard netbios queries if no ADS and fall back to DNS queries
1366 * if alt_name is available */
1367 if (*num_dcs == 0) {
1368 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1369 false);
1370 if (iplist_size == 0) {
1371 if (domain->alt_name != NULL) {
1372 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1373 &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 return True;
1396 /*******************************************************************
1397 Find and make a connection to a DC in the given domain.
1399 @param[in] mem_ctx talloc memory context to allocate from
1400 @param[in] domain domain to find a dc in
1401 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1402 @param[out] pss DC Internet address and port
1403 @param[out] fd fd of the open socket connected to the newly found dc
1404 @return true when a DC connection is made, false otherwise
1405 *******************************************************************/
1407 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1408 struct winbindd_domain *domain,
1409 fstring dcname, struct sockaddr_storage *pss, int *fd)
1411 struct dc_name_ip *dcs = NULL;
1412 int num_dcs = 0;
1414 const char **dcnames = NULL;
1415 int num_dcnames = 0;
1417 struct sockaddr_storage *addrs = NULL;
1418 int num_addrs = 0;
1420 int i;
1421 size_t fd_index;
1423 NTSTATUS status;
1425 *fd = -1;
1427 again:
1428 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1429 return False;
1431 for (i=0; i<num_dcs; i++) {
1433 if (!add_string_to_array(mem_ctx, dcs[i].name,
1434 &dcnames, &num_dcnames)) {
1435 return False;
1437 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1438 &addrs, &num_addrs)) {
1439 return False;
1443 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1444 return False;
1446 if ((addrs == NULL) || (dcnames == NULL))
1447 return False;
1449 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1450 num_addrs, 0, 10, fd, &fd_index, NULL);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 for (i=0; i<num_dcs; i++) {
1453 char ab[INET6_ADDRSTRLEN];
1454 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1455 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1456 "domain %s address %s. Error was %s\n",
1457 domain->name, ab, nt_errstr(status) ));
1458 winbind_add_failed_connection_entry(domain,
1459 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1461 return False;
1464 *pss = addrs[fd_index];
1466 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1467 /* Ok, we've got a name for the DC */
1468 fstrcpy(dcname, dcnames[fd_index]);
1469 return True;
1472 /* Try to figure out the name */
1473 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1474 return True;
1477 /* We can not continue without the DC's name */
1478 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1479 NT_STATUS_UNSUCCESSFUL);
1481 /* Throw away all arrays as we're doing this again. */
1482 TALLOC_FREE(dcs);
1483 num_dcs = 0;
1485 TALLOC_FREE(dcnames);
1486 num_dcnames = 0;
1488 TALLOC_FREE(addrs);
1489 num_addrs = 0;
1491 close(*fd);
1492 *fd = -1;
1494 goto again;
1497 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1499 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1500 domain_name);
1503 static void store_current_dc_in_gencache(const char *domain_name,
1504 const char *dc_name,
1505 struct cli_state *cli)
1507 char addr[INET6_ADDRSTRLEN];
1508 char *key = NULL;
1509 char *value = NULL;
1511 if (!cli_state_is_connected(cli)) {
1512 return;
1515 print_sockaddr(addr, sizeof(addr),
1516 smbXcli_conn_remote_sockaddr(cli->conn));
1518 key = current_dc_key(talloc_tos(), domain_name);
1519 if (key == NULL) {
1520 goto done;
1523 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1524 if (value == NULL) {
1525 goto done;
1528 gencache_set(key, value, 0x7fffffff);
1529 done:
1530 TALLOC_FREE(value);
1531 TALLOC_FREE(key);
1534 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1535 const char *domain_name,
1536 char **p_dc_name, char **p_dc_ip)
1538 char *key, *value, *p;
1539 bool ret = false;
1540 char *dc_name = NULL;
1541 char *dc_ip = NULL;
1543 key = current_dc_key(talloc_tos(), domain_name);
1544 if (key == NULL) {
1545 goto done;
1547 if (!gencache_get(key, &value, NULL)) {
1548 goto done;
1550 p = strchr(value, ' ');
1551 if (p == NULL) {
1552 goto done;
1554 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1555 if (dc_ip == NULL) {
1556 goto done;
1558 dc_name = talloc_strdup(mem_ctx, p+1);
1559 if (dc_name == NULL) {
1560 goto done;
1563 if (p_dc_ip != NULL) {
1564 *p_dc_ip = dc_ip;
1565 dc_ip = NULL;
1567 if (p_dc_name != NULL) {
1568 *p_dc_name = dc_name;
1569 dc_name = NULL;
1571 ret = true;
1572 done:
1573 TALLOC_FREE(dc_name);
1574 TALLOC_FREE(dc_ip);
1575 TALLOC_FREE(key);
1576 return ret;
1579 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1580 struct winbindd_cm_conn *new_conn)
1582 TALLOC_CTX *mem_ctx;
1583 NTSTATUS result;
1584 char *saf_servername = saf_fetch( domain->name );
1585 int retries;
1587 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1588 SAFE_FREE(saf_servername);
1589 set_domain_offline(domain);
1590 return NT_STATUS_NO_MEMORY;
1593 /* we have to check the server affinity cache here since
1594 later we select a DC based on response time and not preference */
1596 /* Check the negative connection cache
1597 before talking to it. It going down may have
1598 triggered the reconnection. */
1600 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1602 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1603 saf_servername, domain->name ));
1605 /* convert an ip address to a name */
1606 if (is_ipaddress( saf_servername ) ) {
1607 fstring saf_name;
1608 struct sockaddr_storage ss;
1610 if (!interpret_string_addr(&ss, saf_servername,
1611 AI_NUMERICHOST)) {
1612 return NT_STATUS_UNSUCCESSFUL;
1614 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1615 strlcpy(domain->dcname, saf_name, sizeof(domain->dcname));
1616 } else {
1617 winbind_add_failed_connection_entry(
1618 domain, saf_servername,
1619 NT_STATUS_UNSUCCESSFUL);
1621 } else {
1622 fstrcpy( domain->dcname, saf_servername );
1625 SAFE_FREE( saf_servername );
1628 for (retries = 0; retries < 3; retries++) {
1629 int fd = -1;
1630 bool retry = False;
1632 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1634 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1635 domain->dcname, domain->name ));
1637 if (*domain->dcname
1638 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1639 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1641 NTSTATUS status;
1643 status = smbsock_connect(&domain->dcaddr, 0,
1644 NULL, -1, NULL, -1,
1645 &fd, NULL, 10);
1646 if (!NT_STATUS_IS_OK(status)) {
1647 fd = -1;
1651 if ((fd == -1)
1652 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1654 /* This is the one place where we will
1655 set the global winbindd offline state
1656 to true, if a "WINBINDD_OFFLINE" entry
1657 is found in the winbindd cache. */
1658 set_global_winbindd_state_offline();
1659 break;
1662 new_conn->cli = NULL;
1664 result = cm_prepare_connection(domain, fd, domain->dcname,
1665 &new_conn->cli, &retry);
1666 if (!NT_STATUS_IS_OK(result)) {
1667 /* Don't leak the smb connection socket */
1668 close(fd);
1671 if (!retry)
1672 break;
1675 if (NT_STATUS_IS_OK(result)) {
1677 winbindd_set_locator_kdc_envs(domain);
1679 if (domain->online == False) {
1680 /* We're changing state from offline to online. */
1681 set_global_winbindd_state_online();
1683 set_domain_online(domain);
1686 * Much as I hate global state, this seems to be the point
1687 * where we can be certain that we have a proper connection to
1688 * a DC. wbinfo --dc-info needs that information, store it in
1689 * gencache with a looong timeout. This will need revisiting
1690 * once we start to connect to multiple DCs, wbcDcInfo is
1691 * already prepared for that.
1693 store_current_dc_in_gencache(domain->name, domain->dcname,
1694 new_conn->cli);
1695 } else {
1696 /* Ensure we setup the retry handler. */
1697 set_domain_offline(domain);
1700 talloc_destroy(mem_ctx);
1701 return result;
1704 /* Close down all open pipes on a connection. */
1706 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1708 NTSTATUS result;
1710 /* We're closing down a possibly dead
1711 connection. Don't have impossibly long (10s) timeouts. */
1713 if (conn->cli) {
1714 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1717 if (conn->samr_pipe != NULL) {
1718 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1719 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1720 talloc_tos(),
1721 &conn->sam_connect_handle,
1722 &result);
1724 TALLOC_FREE(conn->samr_pipe);
1725 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1726 if (conn->cli) {
1727 cli_set_timeout(conn->cli, 500);
1731 if (conn->lsa_pipe != NULL) {
1732 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1733 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1734 talloc_tos(),
1735 &conn->lsa_policy,
1736 &result);
1738 TALLOC_FREE(conn->lsa_pipe);
1739 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1740 if (conn->cli) {
1741 cli_set_timeout(conn->cli, 500);
1745 if (conn->lsa_pipe_tcp != NULL) {
1746 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1747 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1748 talloc_tos(),
1749 &conn->lsa_policy,
1750 &result);
1752 TALLOC_FREE(conn->lsa_pipe_tcp);
1753 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1754 if (conn->cli) {
1755 cli_set_timeout(conn->cli, 500);
1759 if (conn->netlogon_pipe != NULL) {
1760 TALLOC_FREE(conn->netlogon_pipe);
1761 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1762 if (conn->cli) {
1763 cli_set_timeout(conn->cli, 500);
1767 if (conn->cli) {
1768 cli_shutdown(conn->cli);
1771 conn->cli = NULL;
1774 void close_conns_after_fork(void)
1776 struct winbindd_domain *domain;
1777 struct winbindd_cli_state *cli_state;
1779 for (domain = domain_list(); domain; domain = domain->next) {
1781 * first close the low level SMB TCP connection
1782 * so that we don't generate any SMBclose
1783 * requests in invalidate_cm_connection()
1785 if (cli_state_is_connected(domain->conn.cli)) {
1786 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1789 invalidate_cm_connection(&domain->conn);
1792 for (cli_state = winbindd_client_list();
1793 cli_state != NULL;
1794 cli_state = cli_state->next) {
1795 if (cli_state->sock >= 0) {
1796 close(cli_state->sock);
1797 cli_state->sock = -1;
1802 static bool connection_ok(struct winbindd_domain *domain)
1804 bool ok;
1806 ok = cli_state_is_connected(domain->conn.cli);
1807 if (!ok) {
1808 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1809 domain->dcname, domain->name));
1810 return False;
1813 if (domain->online == False) {
1814 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1815 return False;
1818 return True;
1821 /* Initialize a new connection up to the RPC BIND.
1822 Bypass online status check so always does network calls. */
1824 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1826 NTSTATUS result;
1828 /* Internal connections never use the network. */
1829 if (domain->internal) {
1830 domain->initialized = True;
1831 return NT_STATUS_OK;
1834 if (connection_ok(domain)) {
1835 if (!domain->initialized) {
1836 set_dc_type_and_flags(domain);
1838 return NT_STATUS_OK;
1841 invalidate_cm_connection(&domain->conn);
1843 result = cm_open_connection(domain, &domain->conn);
1845 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1846 set_dc_type_and_flags(domain);
1849 return result;
1852 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1854 if (domain->internal) {
1855 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1858 if (domain->initialized && !domain->online) {
1859 /* We check for online status elsewhere. */
1860 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1863 return init_dc_connection_network(domain);
1866 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1868 NTSTATUS status;
1870 status = init_dc_connection(domain);
1871 if (!NT_STATUS_IS_OK(status)) {
1872 return status;
1875 if (!domain->internal && domain->conn.cli == NULL) {
1876 /* happens for trusted domains without inbound trust */
1877 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1880 return NT_STATUS_OK;
1883 /******************************************************************************
1884 Set the trust flags (direction and forest location) for a domain
1885 ******************************************************************************/
1887 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1889 struct winbindd_domain *our_domain;
1890 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1891 WERROR werr;
1892 struct netr_DomainTrustList trusts;
1893 int i;
1894 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1895 NETR_TRUST_FLAG_OUTBOUND |
1896 NETR_TRUST_FLAG_INBOUND);
1897 struct rpc_pipe_client *cli;
1898 TALLOC_CTX *mem_ctx = NULL;
1899 struct dcerpc_binding_handle *b;
1901 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1903 /* Our primary domain doesn't need to worry about trust flags.
1904 Force it to go through the network setup */
1905 if ( domain->primary ) {
1906 return False;
1909 our_domain = find_our_domain();
1911 if ( !connection_ok(our_domain) ) {
1912 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1913 return False;
1916 /* This won't work unless our domain is AD */
1918 if ( !our_domain->active_directory ) {
1919 return False;
1922 /* Use DsEnumerateDomainTrusts to get us the trust direction
1923 and type */
1925 result = cm_connect_netlogon(our_domain, &cli);
1927 if (!NT_STATUS_IS_OK(result)) {
1928 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1929 "a connection to %s for PIPE_NETLOGON (%s)\n",
1930 domain->name, nt_errstr(result)));
1931 return False;
1934 b = cli->binding_handle;
1936 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1937 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1938 return False;
1941 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1942 cli->desthost,
1943 flags,
1944 &trusts,
1945 &werr);
1946 if (!NT_STATUS_IS_OK(result)) {
1947 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1948 "failed to query trusted domain list: %s\n",
1949 nt_errstr(result)));
1950 talloc_destroy(mem_ctx);
1951 return false;
1953 if (!W_ERROR_IS_OK(werr)) {
1954 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1955 "failed to query trusted domain list: %s\n",
1956 win_errstr(werr)));
1957 talloc_destroy(mem_ctx);
1958 return false;
1961 /* Now find the domain name and get the flags */
1963 for ( i=0; i<trusts.count; i++ ) {
1964 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1965 domain->domain_flags = trusts.array[i].trust_flags;
1966 domain->domain_type = trusts.array[i].trust_type;
1967 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1969 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1970 domain->active_directory = True;
1972 /* This flag is only set if the domain is *our*
1973 primary domain and the primary domain is in
1974 native mode */
1976 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1978 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1979 "native mode.\n", domain->name,
1980 domain->native_mode ? "" : "NOT "));
1982 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1983 "running active directory.\n", domain->name,
1984 domain->active_directory ? "" : "NOT "));
1986 domain->can_do_ncacn_ip_tcp = domain->active_directory;
1987 domain->can_do_validation6 = domain->active_directory;
1989 domain->initialized = True;
1991 break;
1995 talloc_destroy( mem_ctx );
1997 return domain->initialized;
2000 /******************************************************************************
2001 We can 'sense' certain things about the DC by it's replies to certain
2002 questions.
2004 This tells us if this particular remote server is Active Directory, and if it
2005 is native mode.
2006 ******************************************************************************/
2008 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2010 NTSTATUS status, result;
2011 WERROR werr;
2012 TALLOC_CTX *mem_ctx = NULL;
2013 struct rpc_pipe_client *cli = NULL;
2014 struct policy_handle pol;
2015 union dssetup_DsRoleInfo info;
2016 union lsa_PolicyInformation *lsa_info = NULL;
2018 if (!connection_ok(domain)) {
2019 return;
2022 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2023 domain->name);
2024 if (!mem_ctx) {
2025 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2026 return;
2029 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2031 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2032 &ndr_table_dssetup.syntax_id,
2033 &cli);
2035 if (!NT_STATUS_IS_OK(status)) {
2036 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2037 "PI_DSSETUP on domain %s: (%s)\n",
2038 domain->name, nt_errstr(status)));
2040 /* if this is just a non-AD domain we need to continue
2041 * identifying so that we can in the end return with
2042 * domain->initialized = True - gd */
2044 goto no_dssetup;
2047 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2048 DS_ROLE_BASIC_INFORMATION,
2049 &info,
2050 &werr);
2051 TALLOC_FREE(cli);
2053 if (NT_STATUS_IS_OK(status)) {
2054 result = werror_to_ntstatus(werr);
2056 if (!NT_STATUS_IS_OK(status)) {
2057 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2058 "on domain %s failed: (%s)\n",
2059 domain->name, nt_errstr(status)));
2061 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2062 * every opcode on the DSSETUP pipe, continue with
2063 * no_dssetup mode here as well to get domain->initialized
2064 * set - gd */
2066 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2067 goto no_dssetup;
2070 TALLOC_FREE(mem_ctx);
2071 return;
2074 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2075 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2076 domain->native_mode = True;
2077 } else {
2078 domain->native_mode = False;
2081 no_dssetup:
2082 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2083 &ndr_table_lsarpc.syntax_id, &cli);
2085 if (!NT_STATUS_IS_OK(status)) {
2086 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2087 "PI_LSARPC on domain %s: (%s)\n",
2088 domain->name, nt_errstr(status)));
2089 TALLOC_FREE(cli);
2090 TALLOC_FREE(mem_ctx);
2091 return;
2094 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2095 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2097 if (NT_STATUS_IS_OK(status)) {
2098 /* This particular query is exactly what Win2k clients use
2099 to determine that the DC is active directory */
2100 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2101 &pol,
2102 LSA_POLICY_INFO_DNS,
2103 &lsa_info,
2104 &result);
2107 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2108 domain->active_directory = True;
2110 if (lsa_info->dns.name.string) {
2111 fstrcpy(domain->name, lsa_info->dns.name.string);
2114 if (lsa_info->dns.dns_domain.string) {
2115 fstrcpy(domain->alt_name,
2116 lsa_info->dns.dns_domain.string);
2119 /* See if we can set some domain trust flags about
2120 ourself */
2122 if (lsa_info->dns.dns_forest.string) {
2123 fstrcpy(domain->forest_name,
2124 lsa_info->dns.dns_forest.string);
2126 if (strequal(domain->forest_name, domain->alt_name)) {
2127 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2131 if (lsa_info->dns.sid) {
2132 sid_copy(&domain->sid, lsa_info->dns.sid);
2134 } else {
2135 domain->active_directory = False;
2137 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2138 SEC_FLAG_MAXIMUM_ALLOWED,
2139 &pol);
2141 if (!NT_STATUS_IS_OK(status)) {
2142 goto done;
2145 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2146 &pol,
2147 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2148 &lsa_info,
2149 &result);
2150 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2152 if (lsa_info->account_domain.name.string) {
2153 fstrcpy(domain->name,
2154 lsa_info->account_domain.name.string);
2157 if (lsa_info->account_domain.sid) {
2158 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2162 done:
2164 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2165 domain->name, domain->native_mode ? "" : "NOT "));
2167 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2168 domain->name, domain->active_directory ? "" : "NOT "));
2170 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2171 domain->can_do_validation6 = domain->active_directory;
2173 TALLOC_FREE(cli);
2175 TALLOC_FREE(mem_ctx);
2177 domain->initialized = True;
2180 /**********************************************************************
2181 Set the domain_flags (trust attributes, domain operating modes, etc...
2182 ***********************************************************************/
2184 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2186 /* we always have to contact our primary domain */
2188 if ( domain->primary ) {
2189 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2190 "primary domain\n"));
2191 set_dc_type_and_flags_connect( domain );
2192 return;
2195 /* Use our DC to get the information if possible */
2197 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2198 /* Otherwise, fallback to contacting the
2199 domain directly */
2200 set_dc_type_and_flags_connect( domain );
2203 return;
2208 /**********************************************************************
2209 ***********************************************************************/
2211 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2212 struct netlogon_creds_CredentialState **ppdc)
2214 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2215 struct rpc_pipe_client *netlogon_pipe;
2217 if (lp_client_schannel() == False) {
2218 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2221 result = cm_connect_netlogon(domain, &netlogon_pipe);
2222 if (!NT_STATUS_IS_OK(result)) {
2223 return result;
2226 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2227 netlogon pipe. */
2229 if (!domain->conn.netlogon_pipe->dc) {
2230 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2233 *ppdc = domain->conn.netlogon_pipe->dc;
2234 return NT_STATUS_OK;
2237 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2238 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2240 struct winbindd_cm_conn *conn;
2241 NTSTATUS status, result;
2242 struct netlogon_creds_CredentialState *p_creds;
2243 char *machine_password = NULL;
2244 char *machine_account = NULL;
2245 char *domain_name = NULL;
2247 if (sid_check_is_our_sam(&domain->sid)) {
2248 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2251 status = init_dc_connection_rpc(domain);
2252 if (!NT_STATUS_IS_OK(status)) {
2253 return status;
2256 conn = &domain->conn;
2258 if (rpccli_is_connected(conn->samr_pipe)) {
2259 goto done;
2262 TALLOC_FREE(conn->samr_pipe);
2265 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2266 * sign and sealed pipe using the machine account password by
2267 * preference. If we can't - try schannel, if that fails, try
2268 * anonymous.
2271 if ((conn->cli->user_name[0] == '\0') ||
2272 (conn->cli->domain[0] == '\0') ||
2273 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2275 status = get_trust_creds(domain, &machine_password,
2276 &machine_account, NULL);
2277 if (!NT_STATUS_IS_OK(status)) {
2278 DEBUG(10, ("cm_connect_sam: No no user available for "
2279 "domain %s, trying schannel\n", conn->cli->domain));
2280 goto schannel;
2282 domain_name = domain->name;
2283 } else {
2284 machine_password = SMB_STRDUP(conn->cli->password);
2285 machine_account = SMB_STRDUP(conn->cli->user_name);
2286 domain_name = conn->cli->domain;
2289 if (!machine_password || !machine_account) {
2290 status = NT_STATUS_NO_MEMORY;
2291 goto done;
2294 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2295 authenticated SAMR pipe with sign & seal. */
2296 status = cli_rpc_pipe_open_spnego(conn->cli,
2297 &ndr_table_samr,
2298 NCACN_NP,
2299 GENSEC_OID_NTLMSSP,
2300 DCERPC_AUTH_LEVEL_PRIVACY,
2301 smbXcli_conn_remote_name(conn->cli->conn),
2302 domain_name,
2303 machine_account,
2304 machine_password,
2305 &conn->samr_pipe);
2307 if (!NT_STATUS_IS_OK(status)) {
2308 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2309 "pipe for domain %s using NTLMSSP "
2310 "authenticated pipe: user %s\\%s. Error was "
2311 "%s\n", domain->name, domain_name,
2312 machine_account, nt_errstr(status)));
2313 goto schannel;
2316 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2317 "domain %s using NTLMSSP authenticated "
2318 "pipe: user %s\\%s\n", domain->name,
2319 domain_name, machine_account));
2321 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2322 conn->samr_pipe->desthost,
2323 SEC_FLAG_MAXIMUM_ALLOWED,
2324 &conn->sam_connect_handle,
2325 &result);
2326 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2327 goto open_domain;
2329 if (NT_STATUS_IS_OK(status)) {
2330 status = result;
2333 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2334 "failed for domain %s, error was %s. Trying schannel\n",
2335 domain->name, nt_errstr(status) ));
2336 TALLOC_FREE(conn->samr_pipe);
2338 schannel:
2340 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2342 status = cm_get_schannel_creds(domain, &p_creds);
2343 if (!NT_STATUS_IS_OK(status)) {
2344 /* If this call fails - conn->cli can now be NULL ! */
2345 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2346 "for domain %s (error %s), trying anon\n",
2347 domain->name,
2348 nt_errstr(status) ));
2349 goto anonymous;
2351 status = cli_rpc_pipe_open_schannel_with_key
2352 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2353 DCERPC_AUTH_LEVEL_PRIVACY,
2354 domain->name, &p_creds, &conn->samr_pipe);
2356 if (!NT_STATUS_IS_OK(status)) {
2357 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2358 "domain %s using schannel. Error was %s\n",
2359 domain->name, nt_errstr(status) ));
2360 goto anonymous;
2362 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2363 "schannel.\n", domain->name ));
2365 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2366 conn->samr_pipe->desthost,
2367 SEC_FLAG_MAXIMUM_ALLOWED,
2368 &conn->sam_connect_handle,
2369 &result);
2370 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2371 goto open_domain;
2373 if (NT_STATUS_IS_OK(status)) {
2374 status = result;
2376 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2377 "for domain %s, error was %s. Trying anonymous\n",
2378 domain->name, nt_errstr(status) ));
2379 TALLOC_FREE(conn->samr_pipe);
2381 anonymous:
2383 /* Finally fall back to anonymous. */
2384 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2385 &conn->samr_pipe);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 goto done;
2391 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2392 conn->samr_pipe->desthost,
2393 SEC_FLAG_MAXIMUM_ALLOWED,
2394 &conn->sam_connect_handle,
2395 &result);
2396 if (!NT_STATUS_IS_OK(status)) {
2397 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2398 "for domain %s Error was %s\n",
2399 domain->name, nt_errstr(status) ));
2400 goto done;
2402 if (!NT_STATUS_IS_OK(result)) {
2403 status = result;
2404 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2405 "for domain %s Error was %s\n",
2406 domain->name, nt_errstr(result)));
2407 goto done;
2410 open_domain:
2411 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2412 mem_ctx,
2413 &conn->sam_connect_handle,
2414 SEC_FLAG_MAXIMUM_ALLOWED,
2415 &domain->sid,
2416 &conn->sam_domain_handle,
2417 &result);
2418 if (!NT_STATUS_IS_OK(status)) {
2419 goto done;
2422 status = result;
2423 done:
2425 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2427 * if we got access denied, we might just have no access rights
2428 * to talk to the remote samr server server (e.g. when we are a
2429 * PDC and we are connecting a w2k8 pdc via an interdomain
2430 * trust). In that case do not invalidate the whole connection
2431 * stack
2433 TALLOC_FREE(conn->samr_pipe);
2434 ZERO_STRUCT(conn->sam_domain_handle);
2435 return status;
2436 } else if (!NT_STATUS_IS_OK(status)) {
2437 invalidate_cm_connection(conn);
2438 return status;
2441 *cli = conn->samr_pipe;
2442 *sam_handle = conn->sam_domain_handle;
2443 SAFE_FREE(machine_password);
2444 SAFE_FREE(machine_account);
2445 return status;
2448 /**********************************************************************
2449 open an schanneld ncacn_ip_tcp connection to LSA
2450 ***********************************************************************/
2452 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2453 TALLOC_CTX *mem_ctx,
2454 struct rpc_pipe_client **cli)
2456 struct winbindd_cm_conn *conn;
2457 struct netlogon_creds_CredentialState *creds;
2458 NTSTATUS status;
2460 DEBUG(10,("cm_connect_lsa_tcp\n"));
2462 status = init_dc_connection_rpc(domain);
2463 if (!NT_STATUS_IS_OK(status)) {
2464 return status;
2467 conn = &domain->conn;
2469 if (conn->lsa_pipe_tcp &&
2470 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2471 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2472 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2473 goto done;
2476 TALLOC_FREE(conn->lsa_pipe_tcp);
2478 status = cm_get_schannel_creds(domain, &creds);
2479 if (!NT_STATUS_IS_OK(status)) {
2480 goto done;
2483 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2484 &ndr_table_lsarpc.syntax_id,
2485 NCACN_IP_TCP,
2486 DCERPC_AUTH_LEVEL_PRIVACY,
2487 domain->name,
2488 &creds,
2489 &conn->lsa_pipe_tcp);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2492 nt_errstr(status)));
2493 goto done;
2496 done:
2497 if (!NT_STATUS_IS_OK(status)) {
2498 TALLOC_FREE(conn->lsa_pipe_tcp);
2499 return status;
2502 *cli = conn->lsa_pipe_tcp;
2504 return status;
2507 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2508 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2510 struct winbindd_cm_conn *conn;
2511 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2512 struct netlogon_creds_CredentialState *p_creds;
2514 result = init_dc_connection_rpc(domain);
2515 if (!NT_STATUS_IS_OK(result))
2516 return result;
2518 conn = &domain->conn;
2520 if (rpccli_is_connected(conn->lsa_pipe)) {
2521 goto done;
2524 TALLOC_FREE(conn->lsa_pipe);
2526 if ((conn->cli->user_name[0] == '\0') ||
2527 (conn->cli->domain[0] == '\0') ||
2528 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2529 DEBUG(10, ("cm_connect_lsa: No no user available for "
2530 "domain %s, trying schannel\n", conn->cli->domain));
2531 goto schannel;
2534 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2535 * authenticated LSA pipe with sign & seal. */
2536 result = cli_rpc_pipe_open_spnego
2537 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2538 GENSEC_OID_NTLMSSP,
2539 DCERPC_AUTH_LEVEL_PRIVACY,
2540 smbXcli_conn_remote_name(conn->cli->conn),
2541 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2542 &conn->lsa_pipe);
2544 if (!NT_STATUS_IS_OK(result)) {
2545 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2546 "domain %s using NTLMSSP authenticated pipe: user "
2547 "%s\\%s. Error was %s. Trying schannel.\n",
2548 domain->name, conn->cli->domain,
2549 conn->cli->user_name, nt_errstr(result)));
2550 goto schannel;
2553 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2554 "NTLMSSP authenticated pipe: user %s\\%s\n",
2555 domain->name, conn->cli->domain, conn->cli->user_name ));
2557 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2558 SEC_FLAG_MAXIMUM_ALLOWED,
2559 &conn->lsa_policy);
2560 if (NT_STATUS_IS_OK(result)) {
2561 goto done;
2564 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2565 "schannel\n"));
2567 TALLOC_FREE(conn->lsa_pipe);
2569 schannel:
2571 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2573 result = cm_get_schannel_creds(domain, &p_creds);
2574 if (!NT_STATUS_IS_OK(result)) {
2575 /* If this call fails - conn->cli can now be NULL ! */
2576 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2577 "for domain %s (error %s), trying anon\n",
2578 domain->name,
2579 nt_errstr(result) ));
2580 goto anonymous;
2582 result = cli_rpc_pipe_open_schannel_with_key
2583 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2584 DCERPC_AUTH_LEVEL_PRIVACY,
2585 domain->name, &p_creds, &conn->lsa_pipe);
2587 if (!NT_STATUS_IS_OK(result)) {
2588 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2589 "domain %s using schannel. Error was %s\n",
2590 domain->name, nt_errstr(result) ));
2591 goto anonymous;
2593 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2594 "schannel.\n", domain->name ));
2596 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2597 SEC_FLAG_MAXIMUM_ALLOWED,
2598 &conn->lsa_policy);
2599 if (NT_STATUS_IS_OK(result)) {
2600 goto done;
2603 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2604 "anonymous\n"));
2606 TALLOC_FREE(conn->lsa_pipe);
2608 anonymous:
2610 result = cli_rpc_pipe_open_noauth(conn->cli,
2611 &ndr_table_lsarpc.syntax_id,
2612 &conn->lsa_pipe);
2613 if (!NT_STATUS_IS_OK(result)) {
2614 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2615 goto done;
2618 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2619 SEC_FLAG_MAXIMUM_ALLOWED,
2620 &conn->lsa_policy);
2621 done:
2622 if (!NT_STATUS_IS_OK(result)) {
2623 invalidate_cm_connection(conn);
2624 return result;
2627 *cli = conn->lsa_pipe;
2628 *lsa_policy = conn->lsa_policy;
2629 return result;
2632 /****************************************************************************
2633 Open a LSA connection to a DC, suiteable for LSA lookup calls.
2634 ****************************************************************************/
2636 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
2637 TALLOC_CTX *mem_ctx,
2638 struct rpc_pipe_client **cli,
2639 struct policy_handle *lsa_policy)
2641 NTSTATUS status;
2643 if (domain->can_do_ncacn_ip_tcp) {
2644 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2645 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
2646 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
2647 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
2648 invalidate_cm_connection(&domain->conn);
2649 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2651 if (NT_STATUS_IS_OK(status)) {
2652 return status;
2656 * we tried twice to connect via ncan_ip_tcp and schannel and
2657 * failed - maybe it is a trusted domain we can't connect to ?
2658 * do not try tcp next time - gd
2660 domain->can_do_ncacn_ip_tcp = false;
2663 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
2665 return status;
2668 /****************************************************************************
2669 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2670 session key stored in conn->netlogon_pipe->dc->sess_key.
2671 ****************************************************************************/
2673 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2674 struct rpc_pipe_client **cli)
2676 struct winbindd_cm_conn *conn;
2677 NTSTATUS result;
2679 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
2680 uint8 mach_pwd[16];
2681 enum netr_SchannelType sec_chan_type;
2682 const char *account_name;
2683 struct rpc_pipe_client *netlogon_pipe = NULL;
2685 *cli = NULL;
2687 result = init_dc_connection_rpc(domain);
2688 if (!NT_STATUS_IS_OK(result)) {
2689 return result;
2692 conn = &domain->conn;
2694 if (rpccli_is_connected(conn->netlogon_pipe)) {
2695 *cli = conn->netlogon_pipe;
2696 return NT_STATUS_OK;
2699 TALLOC_FREE(conn->netlogon_pipe);
2701 result = cli_rpc_pipe_open_noauth(conn->cli,
2702 &ndr_table_netlogon.syntax_id,
2703 &netlogon_pipe);
2704 if (!NT_STATUS_IS_OK(result)) {
2705 return result;
2708 if ((!IS_DC) && (!domain->primary)) {
2709 /* Clear the schannel request bit and drop down */
2710 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2711 goto no_schannel;
2714 if (lp_client_schannel() != False) {
2715 neg_flags |= NETLOGON_NEG_SCHANNEL;
2718 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2719 &sec_chan_type))
2721 TALLOC_FREE(netlogon_pipe);
2722 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2725 result = rpccli_netlogon_setup_creds(
2726 netlogon_pipe,
2727 domain->dcname, /* server name. */
2728 domain->name, /* domain name */
2729 lp_netbios_name(), /* client name */
2730 account_name, /* machine account */
2731 mach_pwd, /* machine password */
2732 sec_chan_type, /* from get_trust_pw */
2733 &neg_flags);
2735 if (!NT_STATUS_IS_OK(result)) {
2736 TALLOC_FREE(netlogon_pipe);
2737 return result;
2740 if ((lp_client_schannel() == True) &&
2741 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2742 DEBUG(3, ("Server did not offer schannel\n"));
2743 TALLOC_FREE(netlogon_pipe);
2744 return NT_STATUS_ACCESS_DENIED;
2747 no_schannel:
2748 if ((lp_client_schannel() == False) ||
2749 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2751 * NetSamLogonEx only works for schannel
2753 domain->can_do_samlogon_ex = False;
2755 /* We're done - just keep the existing connection to NETLOGON
2756 * open */
2757 conn->netlogon_pipe = netlogon_pipe;
2758 *cli = conn->netlogon_pipe;
2759 return NT_STATUS_OK;
2762 /* Using the credentials from the first pipe, open a signed and sealed
2763 second netlogon pipe. The session key is stored in the schannel
2764 part of the new pipe auth struct.
2767 result = cli_rpc_pipe_open_schannel_with_key(
2768 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2769 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2770 &conn->netlogon_pipe);
2772 /* We can now close the initial netlogon pipe. */
2773 TALLOC_FREE(netlogon_pipe);
2775 if (!NT_STATUS_IS_OK(result)) {
2776 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2777 "was %s\n", nt_errstr(result)));
2779 invalidate_cm_connection(conn);
2780 return result;
2784 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2785 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2786 * supported). We used to only try SamLogonEx for AD, but
2787 * Samba DCs can also do it. And because we don't distinguish
2788 * between Samba and NT4, always try it once.
2790 domain->can_do_samlogon_ex = true;
2792 *cli = conn->netlogon_pipe;
2793 return NT_STATUS_OK;
2796 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2797 void *private_data,
2798 uint32_t msg_type,
2799 struct server_id server_id,
2800 DATA_BLOB *data)
2802 struct winbindd_domain *domain;
2803 char *freeit = NULL;
2804 char *addr;
2806 if ((data == NULL)
2807 || (data->data == NULL)
2808 || (data->length == 0)
2809 || (data->data[data->length-1] != '\0')) {
2810 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2811 "string\n"));
2812 return;
2815 addr = (char *)data->data;
2816 DEBUG(10, ("IP %s dropped\n", addr));
2818 if (!is_ipaddress(addr)) {
2819 char *slash;
2821 * Some code sends us ip addresses with the /netmask
2822 * suffix
2824 slash = strchr(addr, '/');
2825 if (slash == NULL) {
2826 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2827 addr));
2828 return;
2830 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2831 if (freeit == NULL) {
2832 DEBUG(1, ("talloc failed\n"));
2833 return;
2835 addr = freeit;
2836 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2839 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2840 char sockaddr[INET6_ADDRSTRLEN];
2842 if (!cli_state_is_connected(domain->conn.cli)) {
2843 continue;
2846 print_sockaddr(sockaddr, sizeof(sockaddr),
2847 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
2849 if (strequal(sockaddr, addr)) {
2850 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2853 TALLOC_FREE(freeit);