s4:libcli/raw: remove unused SMB_SIGNING_AUTO handling
[Samba/gebeck_regimport.git] / source3 / winbindd / winbindd_cm.c
blob33c4deed08acd882efb9d545717cbdbb1906ae51
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"
80 #undef DBGC_CLASS
81 #define DBGC_CLASS DBGC_WINBIND
83 struct dc_name_ip {
84 fstring name;
85 struct sockaddr_storage ss;
88 extern struct winbindd_methods reconnect_methods;
89 extern bool override_logfile;
91 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
92 static void set_dc_type_and_flags( struct winbindd_domain *domain );
93 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
94 struct dc_name_ip **dcs, int *num_dcs);
96 /****************************************************************
97 Child failed to find DC's. Reschedule check.
98 ****************************************************************/
100 static void msg_failed_to_go_online(struct messaging_context *msg,
101 void *private_data,
102 uint32_t msg_type,
103 struct server_id server_id,
104 DATA_BLOB *data)
106 struct winbindd_domain *domain;
107 const char *domainname = (const char *)data->data;
109 if (data->data == NULL || data->length == 0) {
110 return;
113 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
115 for (domain = domain_list(); domain; domain = domain->next) {
116 if (domain->internal) {
117 continue;
120 if (strequal(domain->name, domainname)) {
121 if (domain->online) {
122 /* We're already online, ignore. */
123 DEBUG(5,("msg_fail_to_go_online: domain %s "
124 "already online.\n", domainname));
125 continue;
128 /* Reschedule the online check. */
129 set_domain_offline(domain);
130 break;
135 /****************************************************************
136 Actually cause a reconnect from a message.
137 ****************************************************************/
139 static void msg_try_to_go_online(struct messaging_context *msg,
140 void *private_data,
141 uint32_t msg_type,
142 struct server_id server_id,
143 DATA_BLOB *data)
145 struct winbindd_domain *domain;
146 const char *domainname = (const char *)data->data;
148 if (data->data == NULL || data->length == 0) {
149 return;
152 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
154 for (domain = domain_list(); domain; domain = domain->next) {
155 if (domain->internal) {
156 continue;
159 if (strequal(domain->name, domainname)) {
161 if (domain->online) {
162 /* We're already online, ignore. */
163 DEBUG(5,("msg_try_to_go_online: domain %s "
164 "already online.\n", domainname));
165 continue;
168 /* This call takes care of setting the online
169 flag to true if we connected, or re-adding
170 the offline handler if false. Bypasses online
171 check so always does network calls. */
173 init_dc_connection_network(domain);
174 break;
179 /****************************************************************
180 Fork a child to try and contact a DC. Do this as contacting a
181 DC requires blocking lookups and we don't want to block our
182 parent.
183 ****************************************************************/
185 static bool fork_child_dc_connect(struct winbindd_domain *domain)
187 struct dc_name_ip *dcs = NULL;
188 int num_dcs = 0;
189 TALLOC_CTX *mem_ctx = NULL;
190 pid_t parent_pid = sys_getpid();
191 char *lfile = NULL;
192 NTSTATUS status;
194 if (domain->dc_probe_pid != (pid_t)-1) {
196 * We might already have a DC probe
197 * child working, check.
199 if (process_exists_by_pid(domain->dc_probe_pid)) {
200 DEBUG(10,("fork_child_dc_connect: pid %u already "
201 "checking for DC's.\n",
202 (unsigned int)domain->dc_probe_pid));
203 return true;
205 domain->dc_probe_pid = (pid_t)-1;
208 domain->dc_probe_pid = sys_fork();
210 if (domain->dc_probe_pid == (pid_t)-1) {
211 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
212 return False;
215 if (domain->dc_probe_pid != (pid_t)0) {
216 /* Parent */
217 messaging_register(winbind_messaging_context(), NULL,
218 MSG_WINBIND_TRY_TO_GO_ONLINE,
219 msg_try_to_go_online);
220 messaging_register(winbind_messaging_context(), NULL,
221 MSG_WINBIND_FAILED_TO_GO_ONLINE,
222 msg_failed_to_go_online);
223 return True;
226 /* Child. */
228 /* Leave messages blocked - we will never process one. */
230 if (!override_logfile) {
231 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
232 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
233 _exit(1);
237 status = winbindd_reinit_after_fork(NULL, lfile);
238 if (!NT_STATUS_IS_OK(status)) {
239 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
240 nt_errstr(status)));
241 messaging_send_buf(winbind_messaging_context(),
242 pid_to_procid(parent_pid),
243 MSG_WINBIND_FAILED_TO_GO_ONLINE,
244 (uint8 *)domain->name,
245 strlen(domain->name)+1);
246 _exit(1);
248 SAFE_FREE(lfile);
250 mem_ctx = talloc_init("fork_child_dc_connect");
251 if (!mem_ctx) {
252 DEBUG(0,("talloc_init failed.\n"));
253 messaging_send_buf(winbind_messaging_context(),
254 pid_to_procid(parent_pid),
255 MSG_WINBIND_FAILED_TO_GO_ONLINE,
256 (uint8 *)domain->name,
257 strlen(domain->name)+1);
258 _exit(1);
261 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
262 /* Still offline ? Can't find DC's. */
263 messaging_send_buf(winbind_messaging_context(),
264 pid_to_procid(parent_pid),
265 MSG_WINBIND_FAILED_TO_GO_ONLINE,
266 (uint8 *)domain->name,
267 strlen(domain->name)+1);
268 _exit(0);
271 /* We got a DC. Send a message to our parent to get it to
272 try and do the same. */
274 messaging_send_buf(winbind_messaging_context(),
275 pid_to_procid(parent_pid),
276 MSG_WINBIND_TRY_TO_GO_ONLINE,
277 (uint8 *)domain->name,
278 strlen(domain->name)+1);
279 _exit(0);
282 /****************************************************************
283 Handler triggered if we're offline to try and detect a DC.
284 ****************************************************************/
286 static void check_domain_online_handler(struct event_context *ctx,
287 struct timed_event *te,
288 struct timeval now,
289 void *private_data)
291 struct winbindd_domain *domain =
292 (struct winbindd_domain *)private_data;
294 DEBUG(10,("check_domain_online_handler: called for domain "
295 "%s (online = %s)\n", domain->name,
296 domain->online ? "True" : "False" ));
298 TALLOC_FREE(domain->check_online_event);
300 /* Are we still in "startup" mode ? */
302 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
303 /* No longer in "startup" mode. */
304 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
305 domain->name ));
306 domain->startup = False;
309 /* We've been told to stay offline, so stay
310 that way. */
312 if (get_global_winbindd_state_offline()) {
313 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
314 domain->name ));
315 return;
318 /* Fork a child to test if it can contact a DC.
319 If it can then send ourselves a message to
320 cause a reconnect. */
322 fork_child_dc_connect(domain);
325 /****************************************************************
326 If we're still offline setup the timeout check.
327 ****************************************************************/
329 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
331 int wbr = lp_winbind_reconnect_delay();
333 if (domain->startup) {
334 domain->check_online_timeout = 10;
335 } else if (domain->check_online_timeout < wbr) {
336 domain->check_online_timeout = wbr;
340 /****************************************************************
341 Set domain offline and also add handler to put us back online
342 if we detect a DC.
343 ****************************************************************/
345 void set_domain_offline(struct winbindd_domain *domain)
347 DEBUG(10,("set_domain_offline: called for domain %s\n",
348 domain->name ));
350 TALLOC_FREE(domain->check_online_event);
352 if (domain->internal) {
353 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
354 domain->name ));
355 return;
358 domain->online = False;
360 /* Offline domains are always initialized. They're
361 re-initialized when they go back online. */
363 domain->initialized = True;
365 /* We only add the timeout handler that checks and
366 allows us to go back online when we've not
367 been told to remain offline. */
369 if (get_global_winbindd_state_offline()) {
370 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
371 domain->name ));
372 return;
375 /* If we're in startup mode, check again in 10 seconds, not in
376 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
378 calc_new_online_timeout_check(domain);
380 domain->check_online_event = event_add_timed(winbind_event_context(),
381 NULL,
382 timeval_current_ofs(domain->check_online_timeout,0),
383 check_domain_online_handler,
384 domain);
386 /* The above *has* to succeed for winbindd to work. */
387 if (!domain->check_online_event) {
388 smb_panic("set_domain_offline: failed to add online handler");
391 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
392 domain->name ));
394 /* Send an offline message to the idmap child when our
395 primary domain goes offline */
397 if ( domain->primary ) {
398 struct winbindd_child *idmap = idmap_child();
400 if ( idmap->pid != 0 ) {
401 messaging_send_buf(winbind_messaging_context(),
402 pid_to_procid(idmap->pid),
403 MSG_WINBIND_OFFLINE,
404 (uint8 *)domain->name,
405 strlen(domain->name)+1);
409 return;
412 /****************************************************************
413 Set domain online - if allowed.
414 ****************************************************************/
416 static void set_domain_online(struct winbindd_domain *domain)
418 DEBUG(10,("set_domain_online: called for domain %s\n",
419 domain->name ));
421 if (domain->internal) {
422 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
423 domain->name ));
424 return;
427 if (get_global_winbindd_state_offline()) {
428 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
429 domain->name ));
430 return;
433 winbindd_set_locator_kdc_envs(domain);
435 /* If we are waiting to get a krb5 ticket, trigger immediately. */
436 ccache_regain_all_now();
438 /* Ok, we're out of any startup mode now... */
439 domain->startup = False;
441 if (domain->online == False) {
442 /* We were offline - now we're online. We default to
443 using the MS-RPC backend if we started offline,
444 and if we're going online for the first time we
445 should really re-initialize the backends and the
446 checks to see if we're talking to an AD or NT domain.
449 domain->initialized = False;
451 /* 'reconnect_methods' is the MS-RPC backend. */
452 if (domain->backend == &reconnect_methods) {
453 domain->backend = NULL;
457 /* Ensure we have no online timeout checks. */
458 domain->check_online_timeout = 0;
459 TALLOC_FREE(domain->check_online_event);
461 /* Ensure we ignore any pending child messages. */
462 messaging_deregister(winbind_messaging_context(),
463 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
464 messaging_deregister(winbind_messaging_context(),
465 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
467 domain->online = True;
469 /* Send an online message to the idmap child when our
470 primary domain comes online */
472 if ( domain->primary ) {
473 struct winbindd_child *idmap = idmap_child();
475 if ( idmap->pid != 0 ) {
476 messaging_send_buf(winbind_messaging_context(),
477 pid_to_procid(idmap->pid),
478 MSG_WINBIND_ONLINE,
479 (uint8 *)domain->name,
480 strlen(domain->name)+1);
484 return;
487 /****************************************************************
488 Requested to set a domain online.
489 ****************************************************************/
491 void set_domain_online_request(struct winbindd_domain *domain)
493 struct timeval tev;
495 DEBUG(10,("set_domain_online_request: called for domain %s\n",
496 domain->name ));
498 if (get_global_winbindd_state_offline()) {
499 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
500 domain->name ));
501 return;
504 if (domain->internal) {
505 DEBUG(10, ("set_domain_online_request: Internal domains are "
506 "always online\n"));
507 return;
510 /* We've been told it's safe to go online and
511 try and connect to a DC. But I don't believe it
512 because network manager seems to lie.
513 Wait at least 5 seconds. Heuristics suck... */
516 GetTimeOfDay(&tev);
518 /* Go into "startup" mode again. */
519 domain->startup_time = time_mono(NULL);
520 domain->startup = True;
522 tev.tv_sec += 5;
524 if (!domain->check_online_event) {
525 /* If we've come from being globally offline we
526 don't have a check online event handler set.
527 We need to add one now we're trying to go
528 back online. */
530 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
531 domain->name ));
534 TALLOC_FREE(domain->check_online_event);
536 domain->check_online_event = event_add_timed(winbind_event_context(),
537 NULL,
538 tev,
539 check_domain_online_handler,
540 domain);
542 /* The above *has* to succeed for winbindd to work. */
543 if (!domain->check_online_event) {
544 smb_panic("set_domain_online_request: failed to add online handler");
548 /****************************************************************
549 Add -ve connection cache entries for domain and realm.
550 ****************************************************************/
552 static void winbind_add_failed_connection_entry(
553 const struct winbindd_domain *domain,
554 const char *server,
555 NTSTATUS result)
557 add_failed_connection_entry(domain->name, server, result);
558 /* If this was the saf name for the last thing we talked to,
559 remove it. */
560 saf_delete(domain->name);
561 if (*domain->alt_name) {
562 add_failed_connection_entry(domain->alt_name, server, result);
563 saf_delete(domain->alt_name);
565 winbindd_unset_locator_kdc_env(domain);
568 /* Choose between anonymous or authenticated connections. We need to use
569 an authenticated connection if DCs have the RestrictAnonymous registry
570 entry set > 0, or the "Additional restrictions for anonymous
571 connections" set in the win2k Local Security Policy.
573 Caller to free() result in domain, username, password
576 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
578 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
579 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
580 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
582 if (*username && **username) {
584 if (!*domain || !**domain)
585 *domain = smb_xstrdup(lp_workgroup());
587 if (!*password || !**password)
588 *password = smb_xstrdup("");
590 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
591 *domain, *username));
593 } else {
594 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
595 *username = smb_xstrdup("");
596 *domain = smb_xstrdup("");
597 *password = smb_xstrdup("");
601 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
602 fstring dcname,
603 struct sockaddr_storage *dc_ss)
605 struct winbindd_domain *our_domain = NULL;
606 struct rpc_pipe_client *netlogon_pipe = NULL;
607 NTSTATUS result;
608 WERROR werr;
609 TALLOC_CTX *mem_ctx;
610 unsigned int orig_timeout;
611 const char *tmp = NULL;
612 const char *p;
613 struct dcerpc_binding_handle *b;
615 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
616 * moment.... */
618 if (IS_DC) {
619 return False;
622 if (domain->primary) {
623 return False;
626 our_domain = find_our_domain();
628 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
629 return False;
632 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
633 if (!NT_STATUS_IS_OK(result)) {
634 talloc_destroy(mem_ctx);
635 return False;
638 b = netlogon_pipe->binding_handle;
640 /* This call can take a long time - allow the server to time out.
641 35 seconds should do it. */
643 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
645 if (our_domain->active_directory) {
646 struct netr_DsRGetDCNameInfo *domain_info = NULL;
648 result = dcerpc_netr_DsRGetDCName(b,
649 mem_ctx,
650 our_domain->dcname,
651 domain->name,
652 NULL,
653 NULL,
654 DS_RETURN_DNS_NAME,
655 &domain_info,
656 &werr);
657 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
658 tmp = talloc_strdup(
659 mem_ctx, domain_info->dc_unc);
660 if (tmp == NULL) {
661 DEBUG(0, ("talloc_strdup failed\n"));
662 talloc_destroy(mem_ctx);
663 return false;
665 if (strlen(domain->alt_name) == 0) {
666 fstrcpy(domain->alt_name,
667 domain_info->domain_name);
669 if (strlen(domain->forest_name) == 0) {
670 fstrcpy(domain->forest_name,
671 domain_info->forest_name);
674 } else {
675 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
676 our_domain->dcname,
677 domain->name,
678 &tmp,
679 &werr);
682 /* And restore our original timeout. */
683 rpccli_set_timeout(netlogon_pipe, orig_timeout);
685 if (!NT_STATUS_IS_OK(result)) {
686 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
687 nt_errstr(result)));
688 talloc_destroy(mem_ctx);
689 return false;
692 if (!W_ERROR_IS_OK(werr)) {
693 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
694 win_errstr(werr)));
695 talloc_destroy(mem_ctx);
696 return false;
699 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
700 p = strip_hostname(tmp);
702 fstrcpy(dcname, p);
704 talloc_destroy(mem_ctx);
706 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
708 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
709 return False;
712 return True;
716 * Helper function to assemble trust password and account name
718 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
719 char **machine_password,
720 char **machine_account,
721 char **machine_krb5_principal)
723 const char *account_name;
724 const char *name = NULL;
726 /* If we are a DC and this is not our own domain */
728 if (IS_DC) {
729 name = domain->name;
730 } else {
731 struct winbindd_domain *our_domain = find_our_domain();
733 if (!our_domain)
734 return NT_STATUS_INVALID_SERVER_STATE;
736 name = our_domain->name;
739 if (!get_trust_pw_clear(name, machine_password,
740 &account_name, NULL))
742 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
745 if ((machine_account != NULL) &&
746 (asprintf(machine_account, "%s$", account_name) == -1))
748 return NT_STATUS_NO_MEMORY;
751 /* For now assume our machine account only exists in our domain */
753 if (machine_krb5_principal != NULL)
755 struct winbindd_domain *our_domain = find_our_domain();
757 if (!our_domain) {
758 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
761 if (asprintf(machine_krb5_principal, "%s$@%s",
762 account_name, our_domain->alt_name) == -1)
764 return NT_STATUS_NO_MEMORY;
767 strupper_m(*machine_krb5_principal);
770 return NT_STATUS_OK;
773 /************************************************************************
774 Given a fd with a just-connected TCP connection to a DC, open a connection
775 to the pipe.
776 ************************************************************************/
778 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
779 const int sockfd,
780 const char *controller,
781 struct cli_state **cli,
782 bool *retry)
784 char *machine_password = NULL;
785 char *machine_krb5_principal = NULL;
786 char *machine_account = NULL;
787 char *ipc_username = NULL;
788 char *ipc_domain = NULL;
789 char *ipc_password = NULL;
790 int flags = 0;
791 uint16_t sec_mode = 0;
793 struct named_mutex *mutex;
795 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
797 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
798 controller, domain->name ));
800 *retry = True;
802 mutex = grab_named_mutex(talloc_tos(), controller,
803 WINBIND_SERVER_MUTEX_WAIT_TIME);
804 if (mutex == NULL) {
805 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
806 controller));
807 result = NT_STATUS_POSSIBLE_DEADLOCK;
808 goto done;
811 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
813 *cli = cli_state_create(NULL, sockfd,
814 controller, domain->alt_name,
815 Undefined, flags);
816 if (*cli == NULL) {
817 DEBUG(1, ("Could not cli_initialize\n"));
818 result = NT_STATUS_NO_MEMORY;
819 goto done;
822 cli_set_timeout(*cli, 10000); /* 10 seconds */
824 result = cli_negprot(*cli, PROTOCOL_NT1);
826 if (!NT_STATUS_IS_OK(result)) {
827 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
828 goto done;
831 if (!is_dc_trusted_domain_situation(domain->name) &&
832 cli_state_protocol(*cli) >= PROTOCOL_NT1 &&
833 cli_state_capabilities(*cli) & CAP_EXTENDED_SECURITY)
835 ADS_STATUS ads_status;
837 result = get_trust_creds(domain, &machine_password,
838 &machine_account,
839 &machine_krb5_principal);
840 if (!NT_STATUS_IS_OK(result)) {
841 goto anon_fallback;
844 if (lp_security() == SEC_ADS) {
846 /* Try a krb5 session */
848 (*cli)->use_kerberos = True;
849 DEBUG(5, ("connecting to %s from %s with kerberos principal "
850 "[%s] and realm [%s]\n", controller, lp_netbios_name(),
851 machine_krb5_principal, domain->alt_name));
853 winbindd_set_locator_kdc_envs(domain);
855 result = cli_session_setup(*cli,
856 machine_krb5_principal,
857 machine_password,
858 strlen(machine_password)+1,
859 machine_password,
860 strlen(machine_password)+1,
861 lp_workgroup());
863 if (!NT_STATUS_IS_OK(result)) {
864 DEBUG(4,("failed kerberos session setup with %s\n",
865 nt_errstr(result)));
868 if (NT_STATUS_IS_OK(result)) {
869 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
870 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
871 if (!NT_STATUS_IS_OK(result)) {
872 goto done;
874 goto session_setup_done;
878 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
879 (*cli)->use_kerberos = False;
881 DEBUG(5, ("connecting to %s from %s with username "
882 "[%s]\\[%s]\n", controller, lp_netbios_name(),
883 lp_workgroup(), machine_account));
885 result = cli_session_setup(*cli,
886 machine_account,
887 machine_password,
888 strlen(machine_password)+1,
889 machine_password,
890 strlen(machine_password)+1,
891 lp_workgroup());
892 if (!NT_STATUS_IS_OK(result)) {
893 DEBUG(4, ("authenticated session setup failed with %s\n",
894 nt_errstr(result)));
897 result = ads_ntstatus(ads_status);
898 if (NT_STATUS_IS_OK(result)) {
899 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
900 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
901 if (!NT_STATUS_IS_OK(result)) {
902 goto done;
904 goto session_setup_done;
908 /* Fall back to non-kerberos session setup with auth_user */
910 (*cli)->use_kerberos = False;
912 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
914 sec_mode = cli_state_security_mode(*cli);
915 if (((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
916 (strlen(ipc_username) > 0)) {
918 /* Only try authenticated if we have a username */
920 DEBUG(5, ("connecting to %s from %s with username "
921 "[%s]\\[%s]\n", controller, lp_netbios_name(),
922 ipc_domain, ipc_username));
924 if (NT_STATUS_IS_OK(cli_session_setup(
925 *cli, ipc_username,
926 ipc_password, strlen(ipc_password)+1,
927 ipc_password, strlen(ipc_password)+1,
928 ipc_domain))) {
929 /* Successful logon with given username. */
930 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
931 if (!NT_STATUS_IS_OK(result)) {
932 goto done;
934 goto session_setup_done;
935 } else {
936 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
937 ipc_domain, ipc_username ));
941 anon_fallback:
943 /* Fall back to anonymous connection, this might fail later */
944 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
945 "connection for DC %s\n",
946 controller ));
948 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
949 NULL, 0, ""))) {
950 DEBUG(5, ("Connected anonymously\n"));
951 result = cli_init_creds(*cli, "", "", "");
952 if (!NT_STATUS_IS_OK(result)) {
953 goto done;
955 goto session_setup_done;
958 result = cli_nt_error(*cli);
960 if (NT_STATUS_IS_OK(result))
961 result = NT_STATUS_UNSUCCESSFUL;
963 /* We can't session setup */
965 goto done;
967 session_setup_done:
969 /* cache the server name for later connections */
971 saf_store(domain->name, controller);
972 if (domain->alt_name && (*cli)->use_kerberos) {
973 saf_store(domain->alt_name, controller);
976 winbindd_set_locator_kdc_envs(domain);
978 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
980 if (!NT_STATUS_IS_OK(result)) {
981 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
982 goto done;
985 TALLOC_FREE(mutex);
986 *retry = False;
988 /* set the domain if empty; needed for schannel connections */
989 if ( !(*cli)->domain[0] ) {
990 result = cli_set_domain((*cli), domain->name);
991 if (!NT_STATUS_IS_OK(result)) {
992 return result;
996 result = NT_STATUS_OK;
998 done:
999 TALLOC_FREE(mutex);
1000 SAFE_FREE(machine_account);
1001 SAFE_FREE(machine_password);
1002 SAFE_FREE(machine_krb5_principal);
1003 SAFE_FREE(ipc_username);
1004 SAFE_FREE(ipc_domain);
1005 SAFE_FREE(ipc_password);
1007 if (!NT_STATUS_IS_OK(result)) {
1008 winbind_add_failed_connection_entry(domain, controller, result);
1009 if ((*cli) != NULL) {
1010 cli_shutdown(*cli);
1011 *cli = NULL;
1015 return result;
1018 /*******************************************************************
1019 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1020 array.
1022 Keeps the list unique by not adding duplicate entries.
1024 @param[in] mem_ctx talloc memory context to allocate from
1025 @param[in] domain_name domain of the DC
1026 @param[in] dcname name of the DC to add to the list
1027 @param[in] pss Internet address and port pair to add to the list
1028 @param[in,out] dcs array of dc_name_ip structures to add to
1029 @param[in,out] num_dcs number of dcs returned in the dcs array
1030 @return true if the list was added to, false otherwise
1031 *******************************************************************/
1033 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1034 const char *dcname, struct sockaddr_storage *pss,
1035 struct dc_name_ip **dcs, int *num)
1037 int i = 0;
1039 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1040 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1041 return False;
1044 /* Make sure there's no duplicates in the list */
1045 for (i=0; i<*num; i++)
1046 if (sockaddr_equal(
1047 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1048 (struct sockaddr *)(void *)pss))
1049 return False;
1051 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1053 if (*dcs == NULL)
1054 return False;
1056 fstrcpy((*dcs)[*num].name, dcname);
1057 (*dcs)[*num].ss = *pss;
1058 *num += 1;
1059 return True;
1062 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1063 struct sockaddr_storage *pss, uint16 port,
1064 struct sockaddr_storage **addrs, int *num)
1066 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1068 if (*addrs == NULL) {
1069 *num = 0;
1070 return False;
1073 (*addrs)[*num] = *pss;
1074 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1076 *num += 1;
1077 return True;
1080 /*******************************************************************
1081 convert an ip to a name
1082 *******************************************************************/
1084 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1085 const struct winbindd_domain *domain,
1086 struct sockaddr_storage *pss,
1087 fstring name )
1089 struct ip_service ip_list;
1090 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1091 NTSTATUS status;
1092 const char *dc_name;
1094 ip_list.ss = *pss;
1095 ip_list.port = 0;
1097 #ifdef HAVE_ADS
1098 /* For active directory servers, try to get the ldap server name.
1099 None of these failures should be considered critical for now */
1101 if (lp_security() == SEC_ADS) {
1102 ADS_STRUCT *ads;
1103 ADS_STATUS ads_status;
1104 char addr[INET6_ADDRSTRLEN];
1106 print_sockaddr(addr, sizeof(addr), pss);
1108 ads = ads_init(domain->alt_name, domain->name, addr);
1109 ads->auth.flags |= ADS_AUTH_NO_BIND;
1111 ads_status = ads_connect(ads);
1112 if (ADS_ERR_OK(ads_status)) {
1113 /* We got a cldap packet. */
1114 fstrcpy(name, ads->config.ldap_server_name);
1115 namecache_store(name, 0x20, 1, &ip_list);
1117 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1119 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1120 if (ads_closest_dc(ads)) {
1121 char *sitename = sitename_fetch(ads->config.realm);
1123 /* We're going to use this KDC for this realm/domain.
1124 If we are using sites, then force the krb5 libs
1125 to use this KDC. */
1127 create_local_private_krb5_conf_for_domain(domain->alt_name,
1128 domain->name,
1129 sitename,
1130 pss,
1131 name);
1133 SAFE_FREE(sitename);
1134 } else {
1135 /* use an off site KDC */
1136 create_local_private_krb5_conf_for_domain(domain->alt_name,
1137 domain->name,
1138 NULL,
1139 pss,
1140 name);
1142 winbindd_set_locator_kdc_envs(domain);
1144 /* Ensure we contact this DC also. */
1145 saf_store( domain->name, name);
1146 saf_store( domain->alt_name, name);
1149 ads_destroy( &ads );
1150 return True;
1153 ads_destroy( &ads );
1155 #endif
1157 status = nbt_getdc(winbind_messaging_context(), pss, domain->name,
1158 &domain->sid, nt_version, mem_ctx, &nt_version,
1159 &dc_name, NULL);
1160 if (NT_STATUS_IS_OK(status)) {
1161 fstrcpy(name, dc_name);
1162 namecache_store(name, 0x20, 1, &ip_list);
1163 return True;
1166 /* try node status request */
1168 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1169 namecache_store(name, 0x20, 1, &ip_list);
1170 return True;
1172 return False;
1175 /*******************************************************************
1176 Retrieve a list of IP addresses for domain controllers.
1178 The array is sorted in the preferred connection order.
1180 @param[in] mem_ctx talloc memory context to allocate from
1181 @param[in] domain domain to retrieve DCs for
1182 @param[out] dcs array of dcs that will be returned
1183 @param[out] num_dcs number of dcs returned in the dcs array
1184 @return always true
1185 *******************************************************************/
1187 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1188 struct dc_name_ip **dcs, int *num_dcs)
1190 fstring dcname;
1191 struct sockaddr_storage ss;
1192 struct ip_service *ip_list = NULL;
1193 int iplist_size = 0;
1194 int i;
1195 bool is_our_domain;
1196 enum security_types sec = (enum security_types)lp_security();
1198 is_our_domain = strequal(domain->name, lp_workgroup());
1200 /* If not our domain, get the preferred DC, by asking our primary DC */
1201 if ( !is_our_domain
1202 && get_dc_name_via_netlogon(domain, dcname, &ss)
1203 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1204 num_dcs) )
1206 char addr[INET6_ADDRSTRLEN];
1207 print_sockaddr(addr, sizeof(addr), &ss);
1208 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1209 dcname, addr));
1210 return True;
1213 if (sec == SEC_ADS) {
1214 char *sitename = NULL;
1216 /* We need to make sure we know the local site before
1217 doing any DNS queries, as this will restrict the
1218 get_sorted_dc_list() call below to only fetching
1219 DNS records for the correct site. */
1221 /* Find any DC to get the site record.
1222 We deliberately don't care about the
1223 return here. */
1225 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1227 sitename = sitename_fetch(domain->alt_name);
1228 if (sitename) {
1230 /* Do the site-specific AD dns lookup first. */
1231 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1232 &iplist_size, True);
1234 /* Add ips to the DC array. We don't look up the name
1235 of the DC in this function, but we fill in the char*
1236 of the ip now to make the failed connection cache
1237 work */
1238 for ( i=0; i<iplist_size; i++ ) {
1239 char addr[INET6_ADDRSTRLEN];
1240 print_sockaddr(addr, sizeof(addr),
1241 &ip_list[i].ss);
1242 add_one_dc_unique(mem_ctx,
1243 domain->name,
1244 addr,
1245 &ip_list[i].ss,
1246 dcs,
1247 num_dcs);
1250 SAFE_FREE(ip_list);
1251 SAFE_FREE(sitename);
1252 iplist_size = 0;
1255 /* Now we add DCs from the main AD DNS lookup. */
1256 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1257 &iplist_size, True);
1259 for ( i=0; i<iplist_size; i++ ) {
1260 char addr[INET6_ADDRSTRLEN];
1261 print_sockaddr(addr, sizeof(addr),
1262 &ip_list[i].ss);
1263 add_one_dc_unique(mem_ctx,
1264 domain->name,
1265 addr,
1266 &ip_list[i].ss,
1267 dcs,
1268 num_dcs);
1271 SAFE_FREE(ip_list);
1272 iplist_size = 0;
1275 /* Try standard netbios queries if no ADS */
1276 if (*num_dcs == 0) {
1277 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1278 False);
1280 for ( i=0; i<iplist_size; i++ ) {
1281 char addr[INET6_ADDRSTRLEN];
1282 print_sockaddr(addr, sizeof(addr),
1283 &ip_list[i].ss);
1284 add_one_dc_unique(mem_ctx,
1285 domain->name,
1286 addr,
1287 &ip_list[i].ss,
1288 dcs,
1289 num_dcs);
1292 SAFE_FREE(ip_list);
1293 iplist_size = 0;
1296 return True;
1299 /*******************************************************************
1300 Find and make a connection to a DC in the given domain.
1302 @param[in] mem_ctx talloc memory context to allocate from
1303 @param[in] domain domain to find a dc in
1304 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1305 @param[out] pss DC Internet address and port
1306 @param[out] fd fd of the open socket connected to the newly found dc
1307 @return true when a DC connection is made, false otherwise
1308 *******************************************************************/
1310 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1311 struct winbindd_domain *domain,
1312 fstring dcname, struct sockaddr_storage *pss, int *fd)
1314 struct dc_name_ip *dcs = NULL;
1315 int num_dcs = 0;
1317 const char **dcnames = NULL;
1318 int num_dcnames = 0;
1320 struct sockaddr_storage *addrs = NULL;
1321 int num_addrs = 0;
1323 int i;
1324 size_t fd_index;
1326 NTSTATUS status;
1328 *fd = -1;
1330 again:
1331 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1332 return False;
1334 for (i=0; i<num_dcs; i++) {
1336 if (!add_string_to_array(mem_ctx, dcs[i].name,
1337 &dcnames, &num_dcnames)) {
1338 return False;
1340 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1341 &addrs, &num_addrs)) {
1342 return False;
1346 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1347 return False;
1349 if ((addrs == NULL) || (dcnames == NULL))
1350 return False;
1352 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1353 num_addrs, 0, 10, fd, &fd_index, NULL);
1354 if (!NT_STATUS_IS_OK(status)) {
1355 for (i=0; i<num_dcs; i++) {
1356 char ab[INET6_ADDRSTRLEN];
1357 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1358 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1359 "domain %s address %s. Error was %s\n",
1360 domain->name, ab, nt_errstr(status) ));
1361 winbind_add_failed_connection_entry(domain,
1362 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1364 return False;
1367 *pss = addrs[fd_index];
1369 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1370 /* Ok, we've got a name for the DC */
1371 fstrcpy(dcname, dcnames[fd_index]);
1372 return True;
1375 /* Try to figure out the name */
1376 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1377 return True;
1380 /* We can not continue without the DC's name */
1381 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1382 NT_STATUS_UNSUCCESSFUL);
1384 /* Throw away all arrays as we're doing this again. */
1385 TALLOC_FREE(dcs);
1386 num_dcs = 0;
1388 TALLOC_FREE(dcnames);
1389 num_dcnames = 0;
1391 TALLOC_FREE(addrs);
1392 num_addrs = 0;
1394 close(*fd);
1395 *fd = -1;
1397 goto again;
1400 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1402 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1403 domain_name);
1406 static void store_current_dc_in_gencache(const char *domain_name,
1407 const char *dc_name,
1408 struct cli_state *cli)
1410 char addr[INET6_ADDRSTRLEN];
1411 char *key = NULL;
1412 char *value = NULL;
1414 if (!cli_state_is_connected(cli)) {
1415 return;
1418 print_sockaddr(addr, sizeof(addr),
1419 cli_state_remote_sockaddr(cli));
1421 key = current_dc_key(talloc_tos(), domain_name);
1422 if (key == NULL) {
1423 goto done;
1426 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1427 if (value == NULL) {
1428 goto done;
1431 gencache_set(key, value, 0x7fffffff);
1432 done:
1433 TALLOC_FREE(value);
1434 TALLOC_FREE(key);
1437 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1438 const char *domain_name,
1439 char **p_dc_name, char **p_dc_ip)
1441 char *key, *value, *p;
1442 bool ret = false;
1443 char *dc_name = NULL;
1444 char *dc_ip = NULL;
1446 key = current_dc_key(talloc_tos(), domain_name);
1447 if (key == NULL) {
1448 goto done;
1450 if (!gencache_get(key, &value, NULL)) {
1451 goto done;
1453 p = strchr(value, ' ');
1454 if (p == NULL) {
1455 goto done;
1457 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1458 if (dc_ip == NULL) {
1459 goto done;
1461 dc_name = talloc_strdup(mem_ctx, p+1);
1462 if (dc_name == NULL) {
1463 goto done;
1466 if (p_dc_ip != NULL) {
1467 *p_dc_ip = dc_ip;
1468 dc_ip = NULL;
1470 if (p_dc_name != NULL) {
1471 *p_dc_name = dc_name;
1472 dc_name = NULL;
1474 ret = true;
1475 done:
1476 TALLOC_FREE(dc_name);
1477 TALLOC_FREE(dc_ip);
1478 TALLOC_FREE(key);
1479 return ret;
1482 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1483 struct winbindd_cm_conn *new_conn)
1485 TALLOC_CTX *mem_ctx;
1486 NTSTATUS result;
1487 char *saf_servername = saf_fetch( domain->name );
1488 int retries;
1490 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1491 SAFE_FREE(saf_servername);
1492 set_domain_offline(domain);
1493 return NT_STATUS_NO_MEMORY;
1496 /* we have to check the server affinity cache here since
1497 later we select a DC based on response time and not preference */
1499 /* Check the negative connection cache
1500 before talking to it. It going down may have
1501 triggered the reconnection. */
1503 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1505 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1506 saf_servername, domain->name ));
1508 /* convert an ip address to a name */
1509 if (is_ipaddress( saf_servername ) ) {
1510 fstring saf_name;
1511 struct sockaddr_storage ss;
1513 if (!interpret_string_addr(&ss, saf_servername,
1514 AI_NUMERICHOST)) {
1515 return NT_STATUS_UNSUCCESSFUL;
1517 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1518 strlcpy(domain->dcname, saf_name, sizeof(domain->dcname));
1519 } else {
1520 winbind_add_failed_connection_entry(
1521 domain, saf_servername,
1522 NT_STATUS_UNSUCCESSFUL);
1524 } else {
1525 fstrcpy( domain->dcname, saf_servername );
1528 SAFE_FREE( saf_servername );
1531 for (retries = 0; retries < 3; retries++) {
1532 int fd = -1;
1533 bool retry = False;
1535 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1537 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1538 domain->dcname, domain->name ));
1540 if (*domain->dcname
1541 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1542 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1544 NTSTATUS status;
1546 status = smbsock_connect(&domain->dcaddr, 0,
1547 NULL, -1, NULL, -1,
1548 &fd, NULL, 10);
1549 if (!NT_STATUS_IS_OK(status)) {
1550 fd = -1;
1554 if ((fd == -1)
1555 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1557 /* This is the one place where we will
1558 set the global winbindd offline state
1559 to true, if a "WINBINDD_OFFLINE" entry
1560 is found in the winbindd cache. */
1561 set_global_winbindd_state_offline();
1562 break;
1565 new_conn->cli = NULL;
1567 result = cm_prepare_connection(domain, fd, domain->dcname,
1568 &new_conn->cli, &retry);
1570 if (!retry)
1571 break;
1574 if (NT_STATUS_IS_OK(result)) {
1576 winbindd_set_locator_kdc_envs(domain);
1578 if (domain->online == False) {
1579 /* We're changing state from offline to online. */
1580 set_global_winbindd_state_online();
1582 set_domain_online(domain);
1585 * Much as I hate global state, this seems to be the point
1586 * where we can be certain that we have a proper connection to
1587 * a DC. wbinfo --dc-info needs that information, store it in
1588 * gencache with a looong timeout. This will need revisiting
1589 * once we start to connect to multiple DCs, wbcDcInfo is
1590 * already prepared for that.
1592 store_current_dc_in_gencache(domain->name, domain->dcname,
1593 new_conn->cli);
1594 } else {
1595 /* Ensure we setup the retry handler. */
1596 set_domain_offline(domain);
1599 talloc_destroy(mem_ctx);
1600 return result;
1603 /* Close down all open pipes on a connection. */
1605 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1607 NTSTATUS result;
1609 /* We're closing down a possibly dead
1610 connection. Don't have impossibly long (10s) timeouts. */
1612 if (conn->cli) {
1613 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1616 if (conn->samr_pipe != NULL) {
1617 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1618 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1619 talloc_tos(),
1620 &conn->sam_connect_handle,
1621 &result);
1623 TALLOC_FREE(conn->samr_pipe);
1624 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1625 if (conn->cli) {
1626 cli_set_timeout(conn->cli, 500);
1630 if (conn->lsa_pipe != NULL) {
1631 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1632 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1633 talloc_tos(),
1634 &conn->lsa_policy,
1635 &result);
1637 TALLOC_FREE(conn->lsa_pipe);
1638 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1639 if (conn->cli) {
1640 cli_set_timeout(conn->cli, 500);
1644 if (conn->lsa_pipe_tcp != NULL) {
1645 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1646 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1647 talloc_tos(),
1648 &conn->lsa_policy,
1649 &result);
1651 TALLOC_FREE(conn->lsa_pipe_tcp);
1652 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1653 if (conn->cli) {
1654 cli_set_timeout(conn->cli, 500);
1658 if (conn->netlogon_pipe != NULL) {
1659 TALLOC_FREE(conn->netlogon_pipe);
1660 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1661 if (conn->cli) {
1662 cli_set_timeout(conn->cli, 500);
1666 if (conn->cli) {
1667 cli_shutdown(conn->cli);
1670 conn->cli = NULL;
1673 void close_conns_after_fork(void)
1675 struct winbindd_domain *domain;
1676 struct winbindd_cli_state *cli_state;
1678 for (domain = domain_list(); domain; domain = domain->next) {
1680 * first close the low level SMB TCP connection
1681 * so that we don't generate any SMBclose
1682 * requests in invalidate_cm_connection()
1684 if (cli_state_is_connected(domain->conn.cli)) {
1685 cli_state_disconnect(domain->conn.cli);
1688 invalidate_cm_connection(&domain->conn);
1691 for (cli_state = winbindd_client_list();
1692 cli_state != NULL;
1693 cli_state = cli_state->next) {
1694 if (cli_state->sock >= 0) {
1695 close(cli_state->sock);
1696 cli_state->sock = -1;
1701 static bool connection_ok(struct winbindd_domain *domain)
1703 bool ok;
1705 ok = cli_state_is_connected(domain->conn.cli);
1706 if (!ok) {
1707 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1708 domain->dcname, domain->name));
1709 return False;
1712 if (domain->online == False) {
1713 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1714 return False;
1717 return True;
1720 /* Initialize a new connection up to the RPC BIND.
1721 Bypass online status check so always does network calls. */
1723 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1725 NTSTATUS result;
1727 /* Internal connections never use the network. */
1728 if (domain->internal) {
1729 domain->initialized = True;
1730 return NT_STATUS_OK;
1733 if (!winbindd_can_contact_domain(domain)) {
1734 invalidate_cm_connection(&domain->conn);
1735 domain->initialized = True;
1736 return NT_STATUS_OK;
1739 if (connection_ok(domain)) {
1740 if (!domain->initialized) {
1741 set_dc_type_and_flags(domain);
1743 return NT_STATUS_OK;
1746 invalidate_cm_connection(&domain->conn);
1748 result = cm_open_connection(domain, &domain->conn);
1750 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1751 set_dc_type_and_flags(domain);
1754 return result;
1757 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1759 if (domain->internal) {
1760 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1763 if (domain->initialized && !domain->online) {
1764 /* We check for online status elsewhere. */
1765 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1768 return init_dc_connection_network(domain);
1771 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1773 NTSTATUS status;
1775 status = init_dc_connection(domain);
1776 if (!NT_STATUS_IS_OK(status)) {
1777 return status;
1780 if (!domain->internal && domain->conn.cli == NULL) {
1781 /* happens for trusted domains without inbound trust */
1782 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1785 return NT_STATUS_OK;
1788 /******************************************************************************
1789 Set the trust flags (direction and forest location) for a domain
1790 ******************************************************************************/
1792 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1794 struct winbindd_domain *our_domain;
1795 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1796 WERROR werr;
1797 struct netr_DomainTrustList trusts;
1798 int i;
1799 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1800 NETR_TRUST_FLAG_OUTBOUND |
1801 NETR_TRUST_FLAG_INBOUND);
1802 struct rpc_pipe_client *cli;
1803 TALLOC_CTX *mem_ctx = NULL;
1804 struct dcerpc_binding_handle *b;
1806 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1808 /* Our primary domain doesn't need to worry about trust flags.
1809 Force it to go through the network setup */
1810 if ( domain->primary ) {
1811 return False;
1814 our_domain = find_our_domain();
1816 if ( !connection_ok(our_domain) ) {
1817 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1818 return False;
1821 /* This won't work unless our domain is AD */
1823 if ( !our_domain->active_directory ) {
1824 return False;
1827 /* Use DsEnumerateDomainTrusts to get us the trust direction
1828 and type */
1830 result = cm_connect_netlogon(our_domain, &cli);
1832 if (!NT_STATUS_IS_OK(result)) {
1833 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1834 "a connection to %s for PIPE_NETLOGON (%s)\n",
1835 domain->name, nt_errstr(result)));
1836 return False;
1839 b = cli->binding_handle;
1841 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1842 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1843 return False;
1846 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1847 cli->desthost,
1848 flags,
1849 &trusts,
1850 &werr);
1851 if (!NT_STATUS_IS_OK(result)) {
1852 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1853 "failed to query trusted domain list: %s\n",
1854 nt_errstr(result)));
1855 talloc_destroy(mem_ctx);
1856 return false;
1858 if (!W_ERROR_IS_OK(werr)) {
1859 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1860 "failed to query trusted domain list: %s\n",
1861 win_errstr(werr)));
1862 talloc_destroy(mem_ctx);
1863 return false;
1866 /* Now find the domain name and get the flags */
1868 for ( i=0; i<trusts.count; i++ ) {
1869 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1870 domain->domain_flags = trusts.array[i].trust_flags;
1871 domain->domain_type = trusts.array[i].trust_type;
1872 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1874 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1875 domain->active_directory = True;
1877 /* This flag is only set if the domain is *our*
1878 primary domain and the primary domain is in
1879 native mode */
1881 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1883 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1884 "native mode.\n", domain->name,
1885 domain->native_mode ? "" : "NOT "));
1887 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1888 "running active directory.\n", domain->name,
1889 domain->active_directory ? "" : "NOT "));
1892 domain->initialized = True;
1894 break;
1898 talloc_destroy( mem_ctx );
1900 return domain->initialized;
1903 /******************************************************************************
1904 We can 'sense' certain things about the DC by it's replies to certain
1905 questions.
1907 This tells us if this particular remote server is Active Directory, and if it
1908 is native mode.
1909 ******************************************************************************/
1911 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1913 NTSTATUS status, result;
1914 WERROR werr;
1915 TALLOC_CTX *mem_ctx = NULL;
1916 struct rpc_pipe_client *cli = NULL;
1917 struct policy_handle pol;
1918 union dssetup_DsRoleInfo info;
1919 union lsa_PolicyInformation *lsa_info = NULL;
1921 if (!connection_ok(domain)) {
1922 return;
1925 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1926 domain->name);
1927 if (!mem_ctx) {
1928 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1929 return;
1932 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1934 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
1935 &ndr_table_dssetup.syntax_id,
1936 &cli);
1938 if (!NT_STATUS_IS_OK(status)) {
1939 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1940 "PI_DSSETUP on domain %s: (%s)\n",
1941 domain->name, nt_errstr(status)));
1943 /* if this is just a non-AD domain we need to continue
1944 * identifying so that we can in the end return with
1945 * domain->initialized = True - gd */
1947 goto no_dssetup;
1950 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
1951 DS_ROLE_BASIC_INFORMATION,
1952 &info,
1953 &werr);
1954 TALLOC_FREE(cli);
1956 if (NT_STATUS_IS_OK(status)) {
1957 result = werror_to_ntstatus(werr);
1959 if (!NT_STATUS_IS_OK(status)) {
1960 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1961 "on domain %s failed: (%s)\n",
1962 domain->name, nt_errstr(status)));
1964 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1965 * every opcode on the DSSETUP pipe, continue with
1966 * no_dssetup mode here as well to get domain->initialized
1967 * set - gd */
1969 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1970 goto no_dssetup;
1973 TALLOC_FREE(mem_ctx);
1974 return;
1977 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1978 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1979 domain->native_mode = True;
1980 } else {
1981 domain->native_mode = False;
1984 no_dssetup:
1985 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
1986 &ndr_table_lsarpc.syntax_id, &cli);
1988 if (!NT_STATUS_IS_OK(status)) {
1989 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1990 "PI_LSARPC on domain %s: (%s)\n",
1991 domain->name, nt_errstr(status)));
1992 TALLOC_FREE(cli);
1993 TALLOC_FREE(mem_ctx);
1994 return;
1997 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1998 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2000 if (NT_STATUS_IS_OK(status)) {
2001 /* This particular query is exactly what Win2k clients use
2002 to determine that the DC is active directory */
2003 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2004 &pol,
2005 LSA_POLICY_INFO_DNS,
2006 &lsa_info,
2007 &result);
2010 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2011 domain->active_directory = True;
2013 if (lsa_info->dns.name.string) {
2014 fstrcpy(domain->name, lsa_info->dns.name.string);
2017 if (lsa_info->dns.dns_domain.string) {
2018 fstrcpy(domain->alt_name,
2019 lsa_info->dns.dns_domain.string);
2022 /* See if we can set some domain trust flags about
2023 ourself */
2025 if (lsa_info->dns.dns_forest.string) {
2026 fstrcpy(domain->forest_name,
2027 lsa_info->dns.dns_forest.string);
2029 if (strequal(domain->forest_name, domain->alt_name)) {
2030 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2034 if (lsa_info->dns.sid) {
2035 sid_copy(&domain->sid, lsa_info->dns.sid);
2037 } else {
2038 domain->active_directory = False;
2040 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2041 SEC_FLAG_MAXIMUM_ALLOWED,
2042 &pol);
2044 if (!NT_STATUS_IS_OK(status)) {
2045 goto done;
2048 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2049 &pol,
2050 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2051 &lsa_info,
2052 &result);
2053 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2055 if (lsa_info->account_domain.name.string) {
2056 fstrcpy(domain->name,
2057 lsa_info->account_domain.name.string);
2060 if (lsa_info->account_domain.sid) {
2061 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2065 done:
2067 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2068 domain->name, domain->native_mode ? "" : "NOT "));
2070 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2071 domain->name, domain->active_directory ? "" : "NOT "));
2073 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2074 domain->can_do_validation6 = domain->active_directory;
2076 TALLOC_FREE(cli);
2078 TALLOC_FREE(mem_ctx);
2080 domain->initialized = True;
2083 /**********************************************************************
2084 Set the domain_flags (trust attributes, domain operating modes, etc...
2085 ***********************************************************************/
2087 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2089 /* we always have to contact our primary domain */
2091 if ( domain->primary ) {
2092 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2093 "primary domain\n"));
2094 set_dc_type_and_flags_connect( domain );
2095 return;
2098 /* Use our DC to get the information if possible */
2100 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2101 /* Otherwise, fallback to contacting the
2102 domain directly */
2103 set_dc_type_and_flags_connect( domain );
2106 return;
2111 /**********************************************************************
2112 ***********************************************************************/
2114 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2115 struct netlogon_creds_CredentialState **ppdc)
2117 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2118 struct rpc_pipe_client *netlogon_pipe;
2120 if (lp_client_schannel() == False) {
2121 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2124 result = cm_connect_netlogon(domain, &netlogon_pipe);
2125 if (!NT_STATUS_IS_OK(result)) {
2126 return result;
2129 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2130 netlogon pipe. */
2132 if (!domain->conn.netlogon_pipe->dc) {
2133 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2136 *ppdc = domain->conn.netlogon_pipe->dc;
2137 return NT_STATUS_OK;
2140 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2141 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2143 struct winbindd_cm_conn *conn;
2144 NTSTATUS status, result;
2145 struct netlogon_creds_CredentialState *p_creds;
2146 char *machine_password = NULL;
2147 char *machine_account = NULL;
2148 char *domain_name = NULL;
2150 if (sid_check_is_domain(&domain->sid)) {
2151 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2154 status = init_dc_connection_rpc(domain);
2155 if (!NT_STATUS_IS_OK(status)) {
2156 return status;
2159 conn = &domain->conn;
2161 if (rpccli_is_connected(conn->samr_pipe)) {
2162 goto done;
2165 TALLOC_FREE(conn->samr_pipe);
2168 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2169 * sign and sealed pipe using the machine account password by
2170 * preference. If we can't - try schannel, if that fails, try
2171 * anonymous.
2174 if ((conn->cli->user_name[0] == '\0') ||
2175 (conn->cli->domain[0] == '\0') ||
2176 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2178 status = get_trust_creds(domain, &machine_password,
2179 &machine_account, NULL);
2180 if (!NT_STATUS_IS_OK(status)) {
2181 DEBUG(10, ("cm_connect_sam: No no user available for "
2182 "domain %s, trying schannel\n", conn->cli->domain));
2183 goto schannel;
2185 domain_name = domain->name;
2186 } else {
2187 machine_password = SMB_STRDUP(conn->cli->password);
2188 machine_account = SMB_STRDUP(conn->cli->user_name);
2189 domain_name = conn->cli->domain;
2192 if (!machine_password || !machine_account) {
2193 status = NT_STATUS_NO_MEMORY;
2194 goto done;
2197 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2198 authenticated SAMR pipe with sign & seal. */
2199 status = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2200 &ndr_table_samr.syntax_id,
2201 NCACN_NP,
2202 DCERPC_AUTH_LEVEL_PRIVACY,
2203 domain_name,
2204 machine_account,
2205 machine_password,
2206 &conn->samr_pipe);
2208 if (!NT_STATUS_IS_OK(status)) {
2209 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2210 "pipe for domain %s using NTLMSSP "
2211 "authenticated pipe: user %s\\%s. Error was "
2212 "%s\n", domain->name, domain_name,
2213 machine_account, nt_errstr(status)));
2214 goto schannel;
2217 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2218 "domain %s using NTLMSSP authenticated "
2219 "pipe: user %s\\%s\n", domain->name,
2220 domain_name, machine_account));
2222 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2223 conn->samr_pipe->desthost,
2224 SEC_FLAG_MAXIMUM_ALLOWED,
2225 &conn->sam_connect_handle,
2226 &result);
2227 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2228 goto open_domain;
2230 if (NT_STATUS_IS_OK(status)) {
2231 status = result;
2234 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2235 "failed for domain %s, error was %s. Trying schannel\n",
2236 domain->name, nt_errstr(status) ));
2237 TALLOC_FREE(conn->samr_pipe);
2239 schannel:
2241 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2243 status = cm_get_schannel_creds(domain, &p_creds);
2244 if (!NT_STATUS_IS_OK(status)) {
2245 /* If this call fails - conn->cli can now be NULL ! */
2246 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2247 "for domain %s (error %s), trying anon\n",
2248 domain->name,
2249 nt_errstr(status) ));
2250 goto anonymous;
2252 status = cli_rpc_pipe_open_schannel_with_key
2253 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2254 DCERPC_AUTH_LEVEL_PRIVACY,
2255 domain->name, &p_creds, &conn->samr_pipe);
2257 if (!NT_STATUS_IS_OK(status)) {
2258 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2259 "domain %s using schannel. Error was %s\n",
2260 domain->name, nt_errstr(status) ));
2261 goto anonymous;
2263 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2264 "schannel.\n", domain->name ));
2266 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2267 conn->samr_pipe->desthost,
2268 SEC_FLAG_MAXIMUM_ALLOWED,
2269 &conn->sam_connect_handle,
2270 &result);
2271 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2272 goto open_domain;
2274 if (NT_STATUS_IS_OK(status)) {
2275 status = result;
2277 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2278 "for domain %s, error was %s. Trying anonymous\n",
2279 domain->name, nt_errstr(status) ));
2280 TALLOC_FREE(conn->samr_pipe);
2282 anonymous:
2284 /* Finally fall back to anonymous. */
2285 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2286 &conn->samr_pipe);
2288 if (!NT_STATUS_IS_OK(status)) {
2289 goto done;
2292 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2293 conn->samr_pipe->desthost,
2294 SEC_FLAG_MAXIMUM_ALLOWED,
2295 &conn->sam_connect_handle,
2296 &result);
2297 if (!NT_STATUS_IS_OK(status)) {
2298 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2299 "for domain %s Error was %s\n",
2300 domain->name, nt_errstr(status) ));
2301 goto done;
2303 if (!NT_STATUS_IS_OK(result)) {
2304 status = result;
2305 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2306 "for domain %s Error was %s\n",
2307 domain->name, nt_errstr(result)));
2308 goto done;
2311 open_domain:
2312 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2313 mem_ctx,
2314 &conn->sam_connect_handle,
2315 SEC_FLAG_MAXIMUM_ALLOWED,
2316 &domain->sid,
2317 &conn->sam_domain_handle,
2318 &result);
2319 if (!NT_STATUS_IS_OK(status)) {
2320 goto done;
2323 status = result;
2324 done:
2326 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2328 * if we got access denied, we might just have no access rights
2329 * to talk to the remote samr server server (e.g. when we are a
2330 * PDC and we are connecting a w2k8 pdc via an interdomain
2331 * trust). In that case do not invalidate the whole connection
2332 * stack
2334 TALLOC_FREE(conn->samr_pipe);
2335 ZERO_STRUCT(conn->sam_domain_handle);
2336 return status;
2337 } else if (!NT_STATUS_IS_OK(status)) {
2338 invalidate_cm_connection(conn);
2339 return status;
2342 *cli = conn->samr_pipe;
2343 *sam_handle = conn->sam_domain_handle;
2344 SAFE_FREE(machine_password);
2345 SAFE_FREE(machine_account);
2346 return status;
2349 /**********************************************************************
2350 open an schanneld ncacn_ip_tcp connection to LSA
2351 ***********************************************************************/
2353 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2354 TALLOC_CTX *mem_ctx,
2355 struct rpc_pipe_client **cli)
2357 struct winbindd_cm_conn *conn;
2358 struct netlogon_creds_CredentialState *creds;
2359 NTSTATUS status;
2361 DEBUG(10,("cm_connect_lsa_tcp\n"));
2363 status = init_dc_connection_rpc(domain);
2364 if (!NT_STATUS_IS_OK(status)) {
2365 return status;
2368 conn = &domain->conn;
2370 if (conn->lsa_pipe_tcp &&
2371 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2372 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2373 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2374 goto done;
2377 TALLOC_FREE(conn->lsa_pipe_tcp);
2379 status = cm_get_schannel_creds(domain, &creds);
2380 if (!NT_STATUS_IS_OK(status)) {
2381 goto done;
2384 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2385 &ndr_table_lsarpc.syntax_id,
2386 NCACN_IP_TCP,
2387 DCERPC_AUTH_LEVEL_PRIVACY,
2388 domain->name,
2389 &creds,
2390 &conn->lsa_pipe_tcp);
2391 if (!NT_STATUS_IS_OK(status)) {
2392 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2393 nt_errstr(status)));
2394 goto done;
2397 done:
2398 if (!NT_STATUS_IS_OK(status)) {
2399 TALLOC_FREE(conn->lsa_pipe_tcp);
2400 return status;
2403 *cli = conn->lsa_pipe_tcp;
2405 return status;
2408 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2409 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2411 struct winbindd_cm_conn *conn;
2412 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2413 struct netlogon_creds_CredentialState *p_creds;
2415 result = init_dc_connection_rpc(domain);
2416 if (!NT_STATUS_IS_OK(result))
2417 return result;
2419 conn = &domain->conn;
2421 if (rpccli_is_connected(conn->lsa_pipe)) {
2422 goto done;
2425 TALLOC_FREE(conn->lsa_pipe);
2427 if ((conn->cli->user_name[0] == '\0') ||
2428 (conn->cli->domain[0] == '\0') ||
2429 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2430 DEBUG(10, ("cm_connect_lsa: No no user available for "
2431 "domain %s, trying schannel\n", conn->cli->domain));
2432 goto schannel;
2435 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2436 * authenticated LSA pipe with sign & seal. */
2437 result = cli_rpc_pipe_open_spnego_ntlmssp
2438 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2439 DCERPC_AUTH_LEVEL_PRIVACY,
2440 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2441 &conn->lsa_pipe);
2443 if (!NT_STATUS_IS_OK(result)) {
2444 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2445 "domain %s using NTLMSSP authenticated pipe: user "
2446 "%s\\%s. Error was %s. Trying schannel.\n",
2447 domain->name, conn->cli->domain,
2448 conn->cli->user_name, nt_errstr(result)));
2449 goto schannel;
2452 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2453 "NTLMSSP authenticated pipe: user %s\\%s\n",
2454 domain->name, conn->cli->domain, conn->cli->user_name ));
2456 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2457 SEC_FLAG_MAXIMUM_ALLOWED,
2458 &conn->lsa_policy);
2459 if (NT_STATUS_IS_OK(result)) {
2460 goto done;
2463 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2464 "schannel\n"));
2466 TALLOC_FREE(conn->lsa_pipe);
2468 schannel:
2470 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2472 result = cm_get_schannel_creds(domain, &p_creds);
2473 if (!NT_STATUS_IS_OK(result)) {
2474 /* If this call fails - conn->cli can now be NULL ! */
2475 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2476 "for domain %s (error %s), trying anon\n",
2477 domain->name,
2478 nt_errstr(result) ));
2479 goto anonymous;
2481 result = cli_rpc_pipe_open_schannel_with_key
2482 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2483 DCERPC_AUTH_LEVEL_PRIVACY,
2484 domain->name, &p_creds, &conn->lsa_pipe);
2486 if (!NT_STATUS_IS_OK(result)) {
2487 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2488 "domain %s using schannel. Error was %s\n",
2489 domain->name, nt_errstr(result) ));
2490 goto anonymous;
2492 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2493 "schannel.\n", domain->name ));
2495 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2496 SEC_FLAG_MAXIMUM_ALLOWED,
2497 &conn->lsa_policy);
2498 if (NT_STATUS_IS_OK(result)) {
2499 goto done;
2502 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2503 "anonymous\n"));
2505 TALLOC_FREE(conn->lsa_pipe);
2507 anonymous:
2509 result = cli_rpc_pipe_open_noauth(conn->cli,
2510 &ndr_table_lsarpc.syntax_id,
2511 &conn->lsa_pipe);
2512 if (!NT_STATUS_IS_OK(result)) {
2513 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2514 goto done;
2517 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2518 SEC_FLAG_MAXIMUM_ALLOWED,
2519 &conn->lsa_policy);
2520 done:
2521 if (!NT_STATUS_IS_OK(result)) {
2522 invalidate_cm_connection(conn);
2523 return result;
2526 *cli = conn->lsa_pipe;
2527 *lsa_policy = conn->lsa_policy;
2528 return result;
2531 /****************************************************************************
2532 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2533 session key stored in conn->netlogon_pipe->dc->sess_key.
2534 ****************************************************************************/
2536 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2537 struct rpc_pipe_client **cli)
2539 struct winbindd_cm_conn *conn;
2540 NTSTATUS result;
2542 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2543 uint8 mach_pwd[16];
2544 enum netr_SchannelType sec_chan_type;
2545 const char *account_name;
2546 struct rpc_pipe_client *netlogon_pipe = NULL;
2548 *cli = NULL;
2550 result = init_dc_connection_rpc(domain);
2551 if (!NT_STATUS_IS_OK(result)) {
2552 return result;
2555 conn = &domain->conn;
2557 if (rpccli_is_connected(conn->netlogon_pipe)) {
2558 *cli = conn->netlogon_pipe;
2559 return NT_STATUS_OK;
2562 TALLOC_FREE(conn->netlogon_pipe);
2564 result = cli_rpc_pipe_open_noauth(conn->cli,
2565 &ndr_table_netlogon.syntax_id,
2566 &netlogon_pipe);
2567 if (!NT_STATUS_IS_OK(result)) {
2568 return result;
2571 if ((!IS_DC) && (!domain->primary)) {
2572 /* Clear the schannel request bit and drop down */
2573 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2574 goto no_schannel;
2577 if (lp_client_schannel() != False) {
2578 neg_flags |= NETLOGON_NEG_SCHANNEL;
2581 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2582 &sec_chan_type))
2584 TALLOC_FREE(netlogon_pipe);
2585 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2588 result = rpccli_netlogon_setup_creds(
2589 netlogon_pipe,
2590 domain->dcname, /* server name. */
2591 domain->name, /* domain name */
2592 lp_netbios_name(), /* client name */
2593 account_name, /* machine account */
2594 mach_pwd, /* machine password */
2595 sec_chan_type, /* from get_trust_pw */
2596 &neg_flags);
2598 if (!NT_STATUS_IS_OK(result)) {
2599 TALLOC_FREE(netlogon_pipe);
2600 return result;
2603 if ((lp_client_schannel() == True) &&
2604 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2605 DEBUG(3, ("Server did not offer schannel\n"));
2606 TALLOC_FREE(netlogon_pipe);
2607 return NT_STATUS_ACCESS_DENIED;
2610 no_schannel:
2611 if ((lp_client_schannel() == False) ||
2612 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2614 * NetSamLogonEx only works for schannel
2616 domain->can_do_samlogon_ex = False;
2618 /* We're done - just keep the existing connection to NETLOGON
2619 * open */
2620 conn->netlogon_pipe = netlogon_pipe;
2621 *cli = conn->netlogon_pipe;
2622 return NT_STATUS_OK;
2625 /* Using the credentials from the first pipe, open a signed and sealed
2626 second netlogon pipe. The session key is stored in the schannel
2627 part of the new pipe auth struct.
2630 result = cli_rpc_pipe_open_schannel_with_key(
2631 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2632 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2633 &conn->netlogon_pipe);
2635 /* We can now close the initial netlogon pipe. */
2636 TALLOC_FREE(netlogon_pipe);
2638 if (!NT_STATUS_IS_OK(result)) {
2639 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2640 "was %s\n", nt_errstr(result)));
2642 invalidate_cm_connection(conn);
2643 return result;
2647 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2648 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2649 * supported). We used to only try SamLogonEx for AD, but
2650 * Samba DCs can also do it. And because we don't distinguish
2651 * between Samba and NT4, always try it once.
2653 domain->can_do_samlogon_ex = true;
2655 *cli = conn->netlogon_pipe;
2656 return NT_STATUS_OK;
2659 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2660 void *private_data,
2661 uint32_t msg_type,
2662 struct server_id server_id,
2663 DATA_BLOB *data)
2665 struct winbindd_domain *domain;
2666 char *freeit = NULL;
2667 char *addr;
2669 if ((data == NULL)
2670 || (data->data == NULL)
2671 || (data->length == 0)
2672 || (data->data[data->length-1] != '\0')) {
2673 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2674 "string\n"));
2675 return;
2678 addr = (char *)data->data;
2679 DEBUG(10, ("IP %s dropped\n", addr));
2681 if (!is_ipaddress(addr)) {
2682 char *slash;
2684 * Some code sends us ip addresses with the /netmask
2685 * suffix
2687 slash = strchr(addr, '/');
2688 if (slash == NULL) {
2689 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2690 addr));
2691 return;
2693 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2694 if (freeit == NULL) {
2695 DEBUG(1, ("talloc failed\n"));
2696 return;
2698 addr = freeit;
2699 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2702 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2703 char sockaddr[INET6_ADDRSTRLEN];
2705 if (!cli_state_is_connected(domain->conn.cli)) {
2706 continue;
2709 print_sockaddr(sockaddr, sizeof(sockaddr),
2710 cli_state_local_sockaddr(domain->conn.cli));
2712 if (strequal(sockaddr, addr)) {
2713 cli_state_disconnect(domain->conn.cli);
2716 TALLOC_FREE(freeit);