s3-winbind: Add functions for domain online/offline handling.
[Samba/wip.git] / source3 / winbindd / winbindd_cm.c
blobcfd15ffc0504204344a45ad4fe8ca7b83d9acd70
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 (const uint8_t *)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 (const uint8_t *)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 (const uint8_t *)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 (const uint8_t *)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 tevent_context *ctx,
290 struct tevent_timer *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 DEBUG(10,("set_domain_offline: called for domain %s\n",
391 domain->name ));
393 TALLOC_FREE(domain->check_online_event);
395 if (domain->internal) {
396 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
397 domain->name ));
398 return;
401 domain->online = False;
403 /* Offline domains are always initialized. They're
404 re-initialized when they go back online. */
406 domain->initialized = True;
408 /* We only add the timeout handler that checks and
409 allows us to go back online when we've not
410 been told to remain offline. */
412 if (get_global_winbindd_state_offline()) {
413 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
414 domain->name ));
415 return;
418 /* If we're in startup mode, check again in 10 seconds, not in
419 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
421 calc_new_online_timeout_check(domain);
423 domain->check_online_event = tevent_add_timer(winbind_event_context(),
424 NULL,
425 timeval_current_ofs(domain->check_online_timeout,0),
426 check_domain_online_handler,
427 domain);
429 /* The above *has* to succeed for winbindd to work. */
430 if (!domain->check_online_event) {
431 smb_panic("set_domain_offline: failed to add online handler");
434 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
435 domain->name ));
437 /* Send an offline message to the idmap child when our
438 primary domain goes offline */
440 if ( domain->primary ) {
441 struct winbindd_child *idmap = idmap_child();
443 if ( idmap->pid != 0 ) {
444 messaging_send_buf(winbind_messaging_context(),
445 pid_to_procid(idmap->pid),
446 MSG_WINBIND_OFFLINE,
447 (const uint8_t *)domain->name,
448 strlen(domain->name)+1);
452 return;
455 /****************************************************************
456 Set domain online - if allowed.
457 ****************************************************************/
459 static void set_domain_online(struct winbindd_domain *domain)
461 DEBUG(10,("set_domain_online: called for domain %s\n",
462 domain->name ));
464 if (domain->internal) {
465 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
466 domain->name ));
467 return;
470 if (get_global_winbindd_state_offline()) {
471 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
472 domain->name ));
473 return;
476 winbindd_set_locator_kdc_envs(domain);
478 /* If we are waiting to get a krb5 ticket, trigger immediately. */
479 ccache_regain_all_now();
481 /* Ok, we're out of any startup mode now... */
482 domain->startup = False;
484 if (domain->online == False) {
485 /* We were offline - now we're online. We default to
486 using the MS-RPC backend if we started offline,
487 and if we're going online for the first time we
488 should really re-initialize the backends and the
489 checks to see if we're talking to an AD or NT domain.
492 domain->initialized = False;
494 /* 'reconnect_methods' is the MS-RPC backend. */
495 if (domain->backend == &reconnect_methods) {
496 domain->backend = NULL;
500 /* Ensure we have no online timeout checks. */
501 domain->check_online_timeout = 0;
502 TALLOC_FREE(domain->check_online_event);
504 /* Ensure we ignore any pending child messages. */
505 messaging_deregister(winbind_messaging_context(),
506 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
507 messaging_deregister(winbind_messaging_context(),
508 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
510 domain->online = True;
512 /* Send an online message to the idmap child when our
513 primary domain comes online */
515 if ( domain->primary ) {
516 struct winbindd_child *idmap = idmap_child();
518 if ( idmap->pid != 0 ) {
519 messaging_send_buf(winbind_messaging_context(),
520 pid_to_procid(idmap->pid),
521 MSG_WINBIND_ONLINE,
522 (const uint8_t *)domain->name,
523 strlen(domain->name)+1);
527 return;
530 /****************************************************************
531 Requested to set a domain online.
532 ****************************************************************/
534 void set_domain_online_request(struct winbindd_domain *domain)
536 struct timeval tev;
538 DEBUG(10,("set_domain_online_request: called for domain %s\n",
539 domain->name ));
541 if (get_global_winbindd_state_offline()) {
542 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
543 domain->name ));
544 return;
547 if (domain->internal) {
548 DEBUG(10, ("set_domain_online_request: Internal domains are "
549 "always online\n"));
550 return;
553 /* We've been told it's safe to go online and
554 try and connect to a DC. But I don't believe it
555 because network manager seems to lie.
556 Wait at least 5 seconds. Heuristics suck... */
559 GetTimeOfDay(&tev);
561 /* Go into "startup" mode again. */
562 domain->startup_time = time_mono(NULL);
563 domain->startup = True;
565 tev.tv_sec += 5;
567 if (!domain->check_online_event) {
568 /* If we've come from being globally offline we
569 don't have a check online event handler set.
570 We need to add one now we're trying to go
571 back online. */
573 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
574 domain->name ));
577 TALLOC_FREE(domain->check_online_event);
579 domain->check_online_event = tevent_add_timer(winbind_event_context(),
580 NULL,
581 tev,
582 check_domain_online_handler,
583 domain);
585 /* The above *has* to succeed for winbindd to work. */
586 if (!domain->check_online_event) {
587 smb_panic("set_domain_online_request: failed to add online handler");
591 /****************************************************************
592 Add -ve connection cache entries for domain and realm.
593 ****************************************************************/
595 static void winbind_add_failed_connection_entry(
596 const struct winbindd_domain *domain,
597 const char *server,
598 NTSTATUS result)
600 add_failed_connection_entry(domain->name, server, result);
601 /* If this was the saf name for the last thing we talked to,
602 remove it. */
603 saf_delete(domain->name);
604 if (domain->alt_name != NULL) {
605 add_failed_connection_entry(domain->alt_name, server, result);
606 saf_delete(domain->alt_name);
608 winbindd_unset_locator_kdc_env(domain);
611 /* Choose between anonymous or authenticated connections. We need to use
612 an authenticated connection if DCs have the RestrictAnonymous registry
613 entry set > 0, or the "Additional restrictions for anonymous
614 connections" set in the win2k Local Security Policy.
616 Caller to free() result in domain, username, password
619 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
621 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
622 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
623 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
625 if (*username && **username) {
627 if (!*domain || !**domain)
628 *domain = smb_xstrdup(lp_workgroup());
630 if (!*password || !**password)
631 *password = smb_xstrdup("");
633 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
634 *domain, *username));
636 } else {
637 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
638 *username = smb_xstrdup("");
639 *domain = smb_xstrdup("");
640 *password = smb_xstrdup("");
644 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
645 fstring dcname,
646 struct sockaddr_storage *dc_ss)
648 struct winbindd_domain *our_domain = NULL;
649 struct rpc_pipe_client *netlogon_pipe = NULL;
650 NTSTATUS result;
651 WERROR werr;
652 TALLOC_CTX *mem_ctx;
653 unsigned int orig_timeout;
654 const char *tmp = NULL;
655 const char *p;
656 struct dcerpc_binding_handle *b;
658 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
659 * moment.... */
661 if (IS_DC) {
662 return False;
665 if (domain->primary) {
666 return False;
669 our_domain = find_our_domain();
671 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
672 return False;
675 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
676 if (!NT_STATUS_IS_OK(result)) {
677 talloc_destroy(mem_ctx);
678 return False;
681 b = netlogon_pipe->binding_handle;
683 /* This call can take a long time - allow the server to time out.
684 35 seconds should do it. */
686 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
688 if (our_domain->active_directory) {
689 struct netr_DsRGetDCNameInfo *domain_info = NULL;
691 result = dcerpc_netr_DsRGetDCName(b,
692 mem_ctx,
693 our_domain->dcname,
694 domain->name,
695 NULL,
696 NULL,
697 DS_RETURN_DNS_NAME,
698 &domain_info,
699 &werr);
700 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
701 tmp = talloc_strdup(
702 mem_ctx, domain_info->dc_unc);
703 if (tmp == NULL) {
704 DEBUG(0, ("talloc_strdup failed\n"));
705 talloc_destroy(mem_ctx);
706 return false;
708 if (domain->alt_name == NULL) {
709 domain->alt_name = talloc_strdup(domain,
710 domain_info->domain_name);
711 if (domain->alt_name == NULL) {
712 DEBUG(0, ("talloc_strdup failed\n"));
713 talloc_destroy(mem_ctx);
714 return false;
717 if (domain->forest_name == NULL) {
718 domain->forest_name = talloc_strdup(domain,
719 domain_info->forest_name);
720 if (domain->forest_name == NULL) {
721 DEBUG(0, ("talloc_strdup failed\n"));
722 talloc_destroy(mem_ctx);
723 return false;
727 } else {
728 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
729 our_domain->dcname,
730 domain->name,
731 &tmp,
732 &werr);
735 /* And restore our original timeout. */
736 rpccli_set_timeout(netlogon_pipe, orig_timeout);
738 if (!NT_STATUS_IS_OK(result)) {
739 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
740 nt_errstr(result)));
741 talloc_destroy(mem_ctx);
742 return false;
745 if (!W_ERROR_IS_OK(werr)) {
746 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
747 win_errstr(werr)));
748 talloc_destroy(mem_ctx);
749 return false;
752 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
753 p = strip_hostname(tmp);
755 fstrcpy(dcname, p);
757 talloc_destroy(mem_ctx);
759 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
761 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
762 return False;
765 return True;
769 * Helper function to assemble trust password and account name
771 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
772 char **machine_password,
773 char **machine_account,
774 char **machine_krb5_principal)
776 const char *account_name;
777 const char *name = NULL;
779 /* If we are a DC and this is not our own domain */
781 if (IS_DC) {
782 name = domain->name;
783 } else {
784 struct winbindd_domain *our_domain = find_our_domain();
786 if (!our_domain)
787 return NT_STATUS_INVALID_SERVER_STATE;
789 name = our_domain->name;
792 if (!get_trust_pw_clear(name, machine_password,
793 &account_name, NULL))
795 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
798 if ((machine_account != NULL) &&
799 (asprintf(machine_account, "%s$", account_name) == -1))
801 return NT_STATUS_NO_MEMORY;
804 /* For now assume our machine account only exists in our domain */
806 if (machine_krb5_principal != NULL)
808 struct winbindd_domain *our_domain = find_our_domain();
810 if (!our_domain) {
811 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
814 if (asprintf(machine_krb5_principal, "%s$@%s",
815 account_name, our_domain->alt_name) == -1)
817 return NT_STATUS_NO_MEMORY;
820 if (!strupper_m(*machine_krb5_principal)) {
821 SAFE_FREE(*machine_krb5_principal);
822 return NT_STATUS_INVALID_PARAMETER;
826 return NT_STATUS_OK;
829 /************************************************************************
830 Given a fd with a just-connected TCP connection to a DC, open a connection
831 to the pipe.
832 ************************************************************************/
834 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
835 const int sockfd,
836 const char *controller,
837 struct cli_state **cli,
838 bool *retry)
840 bool try_spnego = false;
841 bool try_ipc_auth = false;
842 char *machine_password = NULL;
843 char *machine_krb5_principal = NULL;
844 char *machine_account = NULL;
845 char *ipc_username = NULL;
846 char *ipc_domain = NULL;
847 char *ipc_password = NULL;
848 int flags = 0;
849 uint16_t sec_mode = 0;
851 struct named_mutex *mutex;
853 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
855 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
856 controller, domain->name ));
858 *retry = True;
860 mutex = grab_named_mutex(talloc_tos(), controller,
861 WINBIND_SERVER_MUTEX_WAIT_TIME);
862 if (mutex == NULL) {
863 close(sockfd);
864 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
865 controller));
866 result = NT_STATUS_POSSIBLE_DEADLOCK;
867 goto done;
870 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
872 *cli = cli_state_create(NULL, sockfd,
873 controller, domain->alt_name,
874 SMB_SIGNING_DEFAULT, flags);
875 if (*cli == NULL) {
876 close(sockfd);
877 DEBUG(1, ("Could not cli_initialize\n"));
878 result = NT_STATUS_NO_MEMORY;
879 goto done;
882 cli_set_timeout(*cli, 10000); /* 10 seconds */
884 result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
885 lp_cli_minprotocol(),
886 lp_cli_maxprotocol());
888 if (!NT_STATUS_IS_OK(result)) {
889 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
890 goto done;
893 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
894 smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
895 try_spnego = true;
896 } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
897 try_spnego = true;
900 if (!is_dc_trusted_domain_situation(domain->name) && try_spnego) {
901 result = get_trust_creds(domain, &machine_password,
902 &machine_account,
903 &machine_krb5_principal);
904 if (!NT_STATUS_IS_OK(result)) {
905 goto anon_fallback;
908 if (lp_security() == SEC_ADS) {
910 /* Try a krb5 session */
912 (*cli)->use_kerberos = True;
913 DEBUG(5, ("connecting to %s from %s with kerberos principal "
914 "[%s] and realm [%s]\n", controller, lp_netbios_name(),
915 machine_krb5_principal, domain->alt_name));
917 winbindd_set_locator_kdc_envs(domain);
919 result = cli_session_setup(*cli,
920 machine_krb5_principal,
921 machine_password,
922 strlen(machine_password)+1,
923 machine_password,
924 strlen(machine_password)+1,
925 lp_workgroup());
927 if (!NT_STATUS_IS_OK(result)) {
928 DEBUG(4,("failed kerberos session setup with %s\n",
929 nt_errstr(result)));
932 if (NT_STATUS_IS_OK(result)) {
933 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
934 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
935 if (!NT_STATUS_IS_OK(result)) {
936 goto done;
938 goto session_setup_done;
942 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
943 (*cli)->use_kerberos = False;
945 DEBUG(5, ("connecting to %s from %s with username "
946 "[%s]\\[%s]\n", controller, lp_netbios_name(),
947 lp_workgroup(), machine_account));
949 result = cli_session_setup(*cli,
950 machine_account,
951 machine_password,
952 strlen(machine_password)+1,
953 machine_password,
954 strlen(machine_password)+1,
955 lp_workgroup());
956 if (!NT_STATUS_IS_OK(result)) {
957 DEBUG(4, ("authenticated session setup failed with %s\n",
958 nt_errstr(result)));
961 if (NT_STATUS_IS_OK(result)) {
962 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
963 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
964 if (!NT_STATUS_IS_OK(result)) {
965 goto done;
967 goto session_setup_done;
971 /* Fall back to non-kerberos session setup with auth_user */
973 (*cli)->use_kerberos = False;
975 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
977 sec_mode = smb1cli_conn_server_security_mode((*cli)->conn);
979 try_ipc_auth = false;
980 if (try_spnego) {
981 try_ipc_auth = true;
982 } else if (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
983 try_ipc_auth = true;
986 if (try_ipc_auth && (strlen(ipc_username) > 0)) {
988 /* Only try authenticated if we have a username */
990 DEBUG(5, ("connecting to %s from %s with username "
991 "[%s]\\[%s]\n", controller, lp_netbios_name(),
992 ipc_domain, ipc_username));
994 if (NT_STATUS_IS_OK(cli_session_setup(
995 *cli, ipc_username,
996 ipc_password, strlen(ipc_password)+1,
997 ipc_password, strlen(ipc_password)+1,
998 ipc_domain))) {
999 /* Successful logon with given username. */
1000 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
1001 if (!NT_STATUS_IS_OK(result)) {
1002 goto done;
1004 goto session_setup_done;
1005 } else {
1006 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
1007 ipc_domain, ipc_username ));
1011 anon_fallback:
1013 /* Fall back to anonymous connection, this might fail later */
1014 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
1015 "connection for DC %s\n",
1016 controller ));
1018 result = cli_session_setup(*cli, "", NULL, 0, NULL, 0, "");
1019 if (NT_STATUS_IS_OK(result)) {
1020 DEBUG(5, ("Connected anonymously\n"));
1021 result = cli_init_creds(*cli, "", "", "");
1022 if (!NT_STATUS_IS_OK(result)) {
1023 goto done;
1025 goto session_setup_done;
1028 /* We can't session setup */
1029 goto done;
1031 session_setup_done:
1034 * This should be a short term hack until
1035 * dynamic re-authentication is implemented.
1037 * See Bug 9175 - winbindd doesn't recover from
1038 * NT_STATUS_NETWORK_SESSION_EXPIRED
1040 if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1041 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1044 /* cache the server name for later connections */
1046 saf_store(domain->name, controller);
1047 if (domain->alt_name && (*cli)->use_kerberos) {
1048 saf_store(domain->alt_name, controller);
1051 winbindd_set_locator_kdc_envs(domain);
1053 result = cli_tree_connect(*cli, "IPC$", "IPC", "", 0);
1055 if (!NT_STATUS_IS_OK(result)) {
1056 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1057 goto done;
1060 TALLOC_FREE(mutex);
1061 *retry = False;
1063 /* set the domain if empty; needed for schannel connections */
1064 if ( !(*cli)->domain[0] ) {
1065 result = cli_set_domain((*cli), domain->name);
1066 if (!NT_STATUS_IS_OK(result)) {
1067 SAFE_FREE(ipc_username);
1068 SAFE_FREE(ipc_domain);
1069 SAFE_FREE(ipc_password);
1070 return result;
1074 result = NT_STATUS_OK;
1076 done:
1077 TALLOC_FREE(mutex);
1078 SAFE_FREE(machine_account);
1079 SAFE_FREE(machine_password);
1080 SAFE_FREE(machine_krb5_principal);
1081 SAFE_FREE(ipc_username);
1082 SAFE_FREE(ipc_domain);
1083 SAFE_FREE(ipc_password);
1085 if (!NT_STATUS_IS_OK(result)) {
1086 winbind_add_failed_connection_entry(domain, controller, result);
1087 if ((*cli) != NULL) {
1088 cli_shutdown(*cli);
1089 *cli = NULL;
1093 return result;
1096 /*******************************************************************
1097 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1098 array.
1100 Keeps the list unique by not adding duplicate entries.
1102 @param[in] mem_ctx talloc memory context to allocate from
1103 @param[in] domain_name domain of the DC
1104 @param[in] dcname name of the DC to add to the list
1105 @param[in] pss Internet address and port pair to add to the list
1106 @param[in,out] dcs array of dc_name_ip structures to add to
1107 @param[in,out] num_dcs number of dcs returned in the dcs array
1108 @return true if the list was added to, false otherwise
1109 *******************************************************************/
1111 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1112 const char *dcname, struct sockaddr_storage *pss,
1113 struct dc_name_ip **dcs, int *num)
1115 int i = 0;
1117 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1118 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1119 return False;
1122 /* Make sure there's no duplicates in the list */
1123 for (i=0; i<*num; i++)
1124 if (sockaddr_equal(
1125 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1126 (struct sockaddr *)(void *)pss))
1127 return False;
1129 *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1131 if (*dcs == NULL)
1132 return False;
1134 fstrcpy((*dcs)[*num].name, dcname);
1135 (*dcs)[*num].ss = *pss;
1136 *num += 1;
1137 return True;
1140 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1141 struct sockaddr_storage *pss, uint16 port,
1142 struct sockaddr_storage **addrs, int *num)
1144 *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1146 if (*addrs == NULL) {
1147 *num = 0;
1148 return False;
1151 (*addrs)[*num] = *pss;
1152 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1154 *num += 1;
1155 return True;
1158 /*******************************************************************
1159 convert an ip to a name
1160 *******************************************************************/
1162 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1163 const struct winbindd_domain *domain,
1164 struct sockaddr_storage *pss,
1165 char **name)
1167 struct ip_service ip_list;
1168 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1169 NTSTATUS status;
1170 const char *dc_name;
1171 fstring nbtname;
1173 ip_list.ss = *pss;
1174 ip_list.port = 0;
1176 #ifdef HAVE_ADS
1177 /* For active directory servers, try to get the ldap server name.
1178 None of these failures should be considered critical for now */
1180 if (lp_security() == SEC_ADS) {
1181 ADS_STRUCT *ads;
1182 ADS_STATUS ads_status;
1183 char addr[INET6_ADDRSTRLEN];
1185 print_sockaddr(addr, sizeof(addr), pss);
1187 ads = ads_init(domain->alt_name, domain->name, addr);
1188 ads->auth.flags |= ADS_AUTH_NO_BIND;
1190 ads_status = ads_connect(ads);
1191 if (ADS_ERR_OK(ads_status)) {
1192 /* We got a cldap packet. */
1193 *name = talloc_strdup(mem_ctx,
1194 ads->config.ldap_server_name);
1195 if (*name == NULL) {
1196 return false;
1198 namecache_store(*name, 0x20, 1, &ip_list);
1200 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1202 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1203 if (ads_closest_dc(ads)) {
1204 char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1206 /* We're going to use this KDC for this realm/domain.
1207 If we are using sites, then force the krb5 libs
1208 to use this KDC. */
1210 create_local_private_krb5_conf_for_domain(domain->alt_name,
1211 domain->name,
1212 sitename,
1213 pss,
1214 *name);
1216 TALLOC_FREE(sitename);
1217 } else {
1218 /* use an off site KDC */
1219 create_local_private_krb5_conf_for_domain(domain->alt_name,
1220 domain->name,
1221 NULL,
1222 pss,
1223 *name);
1225 winbindd_set_locator_kdc_envs(domain);
1227 /* Ensure we contact this DC also. */
1228 saf_store(domain->name, *name);
1229 saf_store(domain->alt_name, *name);
1232 ads_destroy( &ads );
1233 return True;
1236 ads_destroy( &ads );
1237 return false;
1239 #endif
1241 status = nbt_getdc(winbind_messaging_context(), 10, pss, domain->name,
1242 &domain->sid, nt_version, mem_ctx, &nt_version,
1243 &dc_name, NULL);
1244 if (NT_STATUS_IS_OK(status)) {
1245 *name = talloc_strdup(mem_ctx, dc_name);
1246 if (*name == NULL) {
1247 return false;
1249 namecache_store(*name, 0x20, 1, &ip_list);
1250 return True;
1253 /* try node status request */
1255 if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1256 namecache_store(nbtname, 0x20, 1, &ip_list);
1258 if (name != NULL) {
1259 *name = talloc_strdup(mem_ctx, nbtname);
1260 if (*name == NULL) {
1261 return false;
1265 return true;
1267 return False;
1270 /*******************************************************************
1271 Retrieve a list of IP addresses for domain controllers.
1273 The array is sorted in the preferred connection order.
1275 @param[in] mem_ctx talloc memory context to allocate from
1276 @param[in] domain domain to retrieve DCs for
1277 @param[out] dcs array of dcs that will be returned
1278 @param[out] num_dcs number of dcs returned in the dcs array
1279 @return always true
1280 *******************************************************************/
1282 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1283 struct dc_name_ip **dcs, int *num_dcs)
1285 fstring dcname;
1286 struct sockaddr_storage ss;
1287 struct ip_service *ip_list = NULL;
1288 int iplist_size = 0;
1289 int i;
1290 bool is_our_domain;
1291 enum security_types sec = (enum security_types)lp_security();
1293 is_our_domain = strequal(domain->name, lp_workgroup());
1295 /* If not our domain, get the preferred DC, by asking our primary DC */
1296 if ( !is_our_domain
1297 && get_dc_name_via_netlogon(domain, dcname, &ss)
1298 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1299 num_dcs) )
1301 char addr[INET6_ADDRSTRLEN];
1302 print_sockaddr(addr, sizeof(addr), &ss);
1303 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1304 dcname, addr));
1305 return True;
1308 if (sec == SEC_ADS) {
1309 char *sitename = NULL;
1311 /* We need to make sure we know the local site before
1312 doing any DNS queries, as this will restrict the
1313 get_sorted_dc_list() call below to only fetching
1314 DNS records for the correct site. */
1316 /* Find any DC to get the site record.
1317 We deliberately don't care about the
1318 return here. */
1320 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1322 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1323 if (sitename) {
1325 /* Do the site-specific AD dns lookup first. */
1326 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1327 &iplist_size, True);
1329 /* Add ips to the DC array. We don't look up the name
1330 of the DC in this function, but we fill in the char*
1331 of the ip now to make the failed connection cache
1332 work */
1333 for ( i=0; i<iplist_size; i++ ) {
1334 char addr[INET6_ADDRSTRLEN];
1335 print_sockaddr(addr, sizeof(addr),
1336 &ip_list[i].ss);
1337 add_one_dc_unique(mem_ctx,
1338 domain->name,
1339 addr,
1340 &ip_list[i].ss,
1341 dcs,
1342 num_dcs);
1345 SAFE_FREE(ip_list);
1346 TALLOC_FREE(sitename);
1347 iplist_size = 0;
1350 /* Now we add DCs from the main AD DNS lookup. */
1351 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1352 &iplist_size, True);
1354 for ( i=0; i<iplist_size; i++ ) {
1355 char addr[INET6_ADDRSTRLEN];
1356 print_sockaddr(addr, sizeof(addr),
1357 &ip_list[i].ss);
1358 add_one_dc_unique(mem_ctx,
1359 domain->name,
1360 addr,
1361 &ip_list[i].ss,
1362 dcs,
1363 num_dcs);
1366 SAFE_FREE(ip_list);
1367 iplist_size = 0;
1370 /* Try standard netbios queries if no ADS and fall back to DNS queries
1371 * if alt_name is available */
1372 if (*num_dcs == 0) {
1373 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1374 false);
1375 if (iplist_size == 0) {
1376 if (domain->alt_name != NULL) {
1377 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1378 &iplist_size, true);
1382 for ( i=0; i<iplist_size; i++ ) {
1383 char addr[INET6_ADDRSTRLEN];
1384 print_sockaddr(addr, sizeof(addr),
1385 &ip_list[i].ss);
1386 add_one_dc_unique(mem_ctx,
1387 domain->name,
1388 addr,
1389 &ip_list[i].ss,
1390 dcs,
1391 num_dcs);
1394 SAFE_FREE(ip_list);
1395 iplist_size = 0;
1398 return True;
1401 /*******************************************************************
1402 Find and make a connection to a DC in the given domain.
1404 @param[in] mem_ctx talloc memory context to allocate from
1405 @param[in] domain domain to find a dc in
1406 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1407 @param[out] pss DC Internet address and port
1408 @param[out] fd fd of the open socket connected to the newly found dc
1409 @return true when a DC connection is made, false otherwise
1410 *******************************************************************/
1412 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1413 struct winbindd_domain *domain,
1414 char **dcname, struct sockaddr_storage *pss, int *fd)
1416 struct dc_name_ip *dcs = NULL;
1417 int num_dcs = 0;
1419 const char **dcnames = NULL;
1420 int num_dcnames = 0;
1422 struct sockaddr_storage *addrs = NULL;
1423 int num_addrs = 0;
1425 int i;
1426 size_t fd_index;
1428 NTSTATUS status;
1430 *fd = -1;
1432 again:
1433 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1434 return False;
1436 for (i=0; i<num_dcs; i++) {
1438 if (!add_string_to_array(mem_ctx, dcs[i].name,
1439 &dcnames, &num_dcnames)) {
1440 return False;
1442 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1443 &addrs, &num_addrs)) {
1444 return False;
1448 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1449 return False;
1451 if ((addrs == NULL) || (dcnames == NULL))
1452 return False;
1454 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1455 num_addrs, 0, 10, fd, &fd_index, NULL);
1456 if (!NT_STATUS_IS_OK(status)) {
1457 for (i=0; i<num_dcs; i++) {
1458 char ab[INET6_ADDRSTRLEN];
1459 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1460 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1461 "domain %s address %s. Error was %s\n",
1462 domain->name, ab, nt_errstr(status) ));
1463 winbind_add_failed_connection_entry(domain,
1464 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1466 return False;
1469 *pss = addrs[fd_index];
1471 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1472 /* Ok, we've got a name for the DC */
1473 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1474 if (*dcname == NULL) {
1475 return false;
1477 return true;
1480 /* Try to figure out the name */
1481 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1482 return True;
1485 /* We can not continue without the DC's name */
1486 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1487 NT_STATUS_UNSUCCESSFUL);
1489 /* Throw away all arrays as we're doing this again. */
1490 TALLOC_FREE(dcs);
1491 num_dcs = 0;
1493 TALLOC_FREE(dcnames);
1494 num_dcnames = 0;
1496 TALLOC_FREE(addrs);
1497 num_addrs = 0;
1499 close(*fd);
1500 *fd = -1;
1502 goto again;
1505 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1507 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1508 domain_name);
1511 static void store_current_dc_in_gencache(const char *domain_name,
1512 const char *dc_name,
1513 struct cli_state *cli)
1515 char addr[INET6_ADDRSTRLEN];
1516 char *key = NULL;
1517 char *value = NULL;
1519 if (!cli_state_is_connected(cli)) {
1520 return;
1523 print_sockaddr(addr, sizeof(addr),
1524 smbXcli_conn_remote_sockaddr(cli->conn));
1526 key = current_dc_key(talloc_tos(), domain_name);
1527 if (key == NULL) {
1528 goto done;
1531 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1532 if (value == NULL) {
1533 goto done;
1536 gencache_set(key, value, 0x7fffffff);
1537 done:
1538 TALLOC_FREE(value);
1539 TALLOC_FREE(key);
1542 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1543 const char *domain_name,
1544 char **p_dc_name, char **p_dc_ip)
1546 char *key, *value, *p;
1547 bool ret = false;
1548 char *dc_name = NULL;
1549 char *dc_ip = NULL;
1551 key = current_dc_key(talloc_tos(), domain_name);
1552 if (key == NULL) {
1553 goto done;
1555 if (!gencache_get(key, mem_ctx, &value, NULL)) {
1556 goto done;
1558 p = strchr(value, ' ');
1559 if (p == NULL) {
1560 goto done;
1562 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1563 if (dc_ip == NULL) {
1564 goto done;
1566 dc_name = talloc_strdup(mem_ctx, p+1);
1567 if (dc_name == NULL) {
1568 goto done;
1571 if (p_dc_ip != NULL) {
1572 *p_dc_ip = dc_ip;
1573 dc_ip = NULL;
1575 if (p_dc_name != NULL) {
1576 *p_dc_name = dc_name;
1577 dc_name = NULL;
1579 ret = true;
1580 done:
1581 TALLOC_FREE(dc_name);
1582 TALLOC_FREE(dc_ip);
1583 TALLOC_FREE(key);
1584 TALLOC_FREE(value);
1585 return ret;
1588 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1589 struct winbindd_cm_conn *new_conn)
1591 TALLOC_CTX *mem_ctx;
1592 NTSTATUS result;
1593 char *saf_servername;
1594 int retries;
1596 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1597 set_domain_offline(domain);
1598 return NT_STATUS_NO_MEMORY;
1601 saf_servername = saf_fetch(mem_ctx, domain->name );
1603 /* we have to check the server affinity cache here since
1604 later we select a DC based on response time and not preference */
1606 /* Check the negative connection cache
1607 before talking to it. It going down may have
1608 triggered the reconnection. */
1610 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1612 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1613 saf_servername, domain->name ));
1615 /* convert an ip address to a name */
1616 if (is_ipaddress( saf_servername ) ) {
1617 char *dcname = NULL;
1618 struct sockaddr_storage ss;
1620 if (!interpret_string_addr(&ss, saf_servername,
1621 AI_NUMERICHOST)) {
1622 TALLOC_FREE(mem_ctx);
1623 return NT_STATUS_UNSUCCESSFUL;
1625 if (dcip_to_name(mem_ctx, domain, &ss, &dcname)) {
1626 domain->dcname = talloc_strdup(domain,
1627 dcname);
1628 if (domain->dcname == NULL) {
1629 TALLOC_FREE(mem_ctx);
1630 return NT_STATUS_NO_MEMORY;
1632 } else {
1633 winbind_add_failed_connection_entry(
1634 domain, saf_servername,
1635 NT_STATUS_UNSUCCESSFUL);
1637 } else {
1638 domain->dcname = talloc_strdup(domain, saf_servername);
1639 if (domain->dcname == NULL) {
1640 TALLOC_FREE(mem_ctx);
1641 return NT_STATUS_NO_MEMORY;
1646 for (retries = 0; retries < 3; retries++) {
1647 int fd = -1;
1648 bool retry = False;
1649 char *dcname = NULL;
1651 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1653 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1654 domain->dcname ? domain->dcname : "", domain->name ));
1656 if (domain->dcname != NULL
1657 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1658 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1660 NTSTATUS status;
1662 status = smbsock_connect(&domain->dcaddr, 0,
1663 NULL, -1, NULL, -1,
1664 &fd, NULL, 10);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 fd = -1;
1670 if ((fd == -1) &&
1671 !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd))
1673 /* This is the one place where we will
1674 set the global winbindd offline state
1675 to true, if a "WINBINDD_OFFLINE" entry
1676 is found in the winbindd cache. */
1677 set_global_winbindd_state_offline();
1678 break;
1680 if (dcname != NULL) {
1681 talloc_free(domain->dcname);
1683 domain->dcname = talloc_move(domain, &dcname);
1684 if (domain->dcname == NULL) {
1685 result = NT_STATUS_NO_MEMORY;
1686 break;
1690 new_conn->cli = NULL;
1692 result = cm_prepare_connection(domain, fd, domain->dcname,
1693 &new_conn->cli, &retry);
1694 if (!NT_STATUS_IS_OK(result)) {
1695 /* Don't leak the smb connection socket */
1696 close(fd);
1699 if (!retry)
1700 break;
1703 if (NT_STATUS_IS_OK(result)) {
1705 winbindd_set_locator_kdc_envs(domain);
1707 if (domain->online == False) {
1708 /* We're changing state from offline to online. */
1709 set_global_winbindd_state_online();
1711 set_domain_online(domain);
1714 * Much as I hate global state, this seems to be the point
1715 * where we can be certain that we have a proper connection to
1716 * a DC. wbinfo --dc-info needs that information, store it in
1717 * gencache with a looong timeout. This will need revisiting
1718 * once we start to connect to multiple DCs, wbcDcInfo is
1719 * already prepared for that.
1721 store_current_dc_in_gencache(domain->name, domain->dcname,
1722 new_conn->cli);
1723 } else {
1724 /* Ensure we setup the retry handler. */
1725 set_domain_offline(domain);
1728 talloc_destroy(mem_ctx);
1729 return result;
1732 /* Close down all open pipes on a connection. */
1734 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1736 NTSTATUS result;
1738 /* We're closing down a possibly dead
1739 connection. Don't have impossibly long (10s) timeouts. */
1741 if (conn->cli) {
1742 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1745 if (conn->samr_pipe != NULL) {
1746 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1747 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1748 talloc_tos(),
1749 &conn->sam_connect_handle,
1750 &result);
1752 TALLOC_FREE(conn->samr_pipe);
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->lsa_pipe != NULL) {
1760 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1761 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1762 talloc_tos(),
1763 &conn->lsa_policy,
1764 &result);
1766 TALLOC_FREE(conn->lsa_pipe);
1767 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1768 if (conn->cli) {
1769 cli_set_timeout(conn->cli, 500);
1773 if (conn->lsa_pipe_tcp != NULL) {
1774 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1775 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1776 talloc_tos(),
1777 &conn->lsa_policy,
1778 &result);
1780 TALLOC_FREE(conn->lsa_pipe_tcp);
1781 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1782 if (conn->cli) {
1783 cli_set_timeout(conn->cli, 500);
1787 if (conn->netlogon_pipe != NULL) {
1788 TALLOC_FREE(conn->netlogon_pipe);
1789 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1790 if (conn->cli) {
1791 cli_set_timeout(conn->cli, 500);
1795 if (conn->cli) {
1796 cli_shutdown(conn->cli);
1799 conn->cli = NULL;
1802 void close_conns_after_fork(void)
1804 struct winbindd_domain *domain;
1805 struct winbindd_cli_state *cli_state;
1807 for (domain = domain_list(); domain; domain = domain->next) {
1809 * first close the low level SMB TCP connection
1810 * so that we don't generate any SMBclose
1811 * requests in invalidate_cm_connection()
1813 if (cli_state_is_connected(domain->conn.cli)) {
1814 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1817 invalidate_cm_connection(&domain->conn);
1820 for (cli_state = winbindd_client_list();
1821 cli_state != NULL;
1822 cli_state = cli_state->next) {
1823 if (cli_state->sock >= 0) {
1824 close(cli_state->sock);
1825 cli_state->sock = -1;
1830 static bool connection_ok(struct winbindd_domain *domain)
1832 bool ok;
1834 ok = cli_state_is_connected(domain->conn.cli);
1835 if (!ok) {
1836 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1837 domain->dcname, domain->name));
1838 return False;
1841 if (domain->online == False) {
1842 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1843 return False;
1846 return True;
1849 /* Initialize a new connection up to the RPC BIND.
1850 Bypass online status check so always does network calls. */
1852 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1854 NTSTATUS result;
1856 /* Internal connections never use the network. */
1857 if (domain->internal) {
1858 domain->initialized = True;
1859 return NT_STATUS_OK;
1862 if (connection_ok(domain)) {
1863 if (!domain->initialized) {
1864 set_dc_type_and_flags(domain);
1866 return NT_STATUS_OK;
1869 invalidate_cm_connection(&domain->conn);
1871 result = cm_open_connection(domain, &domain->conn);
1873 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1874 set_dc_type_and_flags(domain);
1877 return result;
1880 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1882 if (domain->internal) {
1883 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1886 if (domain->initialized && !domain->online) {
1887 /* We check for online status elsewhere. */
1888 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1891 return init_dc_connection_network(domain);
1894 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1896 NTSTATUS status;
1898 status = init_dc_connection(domain);
1899 if (!NT_STATUS_IS_OK(status)) {
1900 return status;
1903 if (!domain->internal && domain->conn.cli == NULL) {
1904 /* happens for trusted domains without inbound trust */
1905 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1908 return NT_STATUS_OK;
1911 /******************************************************************************
1912 Set the trust flags (direction and forest location) for a domain
1913 ******************************************************************************/
1915 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1917 struct winbindd_domain *our_domain;
1918 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1919 WERROR werr;
1920 struct netr_DomainTrustList trusts;
1921 int i;
1922 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1923 NETR_TRUST_FLAG_OUTBOUND |
1924 NETR_TRUST_FLAG_INBOUND);
1925 struct rpc_pipe_client *cli;
1926 TALLOC_CTX *mem_ctx = NULL;
1927 struct dcerpc_binding_handle *b;
1929 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1931 /* Our primary domain doesn't need to worry about trust flags.
1932 Force it to go through the network setup */
1933 if ( domain->primary ) {
1934 return False;
1937 our_domain = find_our_domain();
1939 if ( !connection_ok(our_domain) ) {
1940 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1941 return False;
1944 /* This won't work unless our domain is AD */
1946 if ( !our_domain->active_directory ) {
1947 return False;
1950 /* Use DsEnumerateDomainTrusts to get us the trust direction
1951 and type */
1953 result = cm_connect_netlogon(our_domain, &cli);
1955 if (!NT_STATUS_IS_OK(result)) {
1956 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1957 "a connection to %s for PIPE_NETLOGON (%s)\n",
1958 domain->name, nt_errstr(result)));
1959 return False;
1962 b = cli->binding_handle;
1964 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1965 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1966 return False;
1969 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1970 cli->desthost,
1971 flags,
1972 &trusts,
1973 &werr);
1974 if (!NT_STATUS_IS_OK(result)) {
1975 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1976 "failed to query trusted domain list: %s\n",
1977 nt_errstr(result)));
1978 talloc_destroy(mem_ctx);
1979 return false;
1981 if (!W_ERROR_IS_OK(werr)) {
1982 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1983 "failed to query trusted domain list: %s\n",
1984 win_errstr(werr)));
1985 talloc_destroy(mem_ctx);
1986 return false;
1989 /* Now find the domain name and get the flags */
1991 for ( i=0; i<trusts.count; i++ ) {
1992 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1993 domain->domain_flags = trusts.array[i].trust_flags;
1994 domain->domain_type = trusts.array[i].trust_type;
1995 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1997 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1998 domain->active_directory = True;
2000 /* This flag is only set if the domain is *our*
2001 primary domain and the primary domain is in
2002 native mode */
2004 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2006 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2007 "native mode.\n", domain->name,
2008 domain->native_mode ? "" : "NOT "));
2010 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2011 "running active directory.\n", domain->name,
2012 domain->active_directory ? "" : "NOT "));
2014 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2015 domain->can_do_validation6 = domain->active_directory;
2017 domain->initialized = True;
2019 break;
2023 talloc_destroy( mem_ctx );
2025 return domain->initialized;
2028 /******************************************************************************
2029 We can 'sense' certain things about the DC by it's replies to certain
2030 questions.
2032 This tells us if this particular remote server is Active Directory, and if it
2033 is native mode.
2034 ******************************************************************************/
2036 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2038 NTSTATUS status, result;
2039 WERROR werr;
2040 TALLOC_CTX *mem_ctx = NULL;
2041 struct rpc_pipe_client *cli = NULL;
2042 struct policy_handle pol;
2043 union dssetup_DsRoleInfo info;
2044 union lsa_PolicyInformation *lsa_info = NULL;
2046 if (!connection_ok(domain)) {
2047 return;
2050 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2051 domain->name);
2052 if (!mem_ctx) {
2053 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2054 return;
2057 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2059 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2060 &ndr_table_dssetup,
2061 &cli);
2063 if (!NT_STATUS_IS_OK(status)) {
2064 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2065 "PI_DSSETUP on domain %s: (%s)\n",
2066 domain->name, nt_errstr(status)));
2068 /* if this is just a non-AD domain we need to continue
2069 * identifying so that we can in the end return with
2070 * domain->initialized = True - gd */
2072 goto no_dssetup;
2075 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2076 DS_ROLE_BASIC_INFORMATION,
2077 &info,
2078 &werr);
2079 TALLOC_FREE(cli);
2081 if (NT_STATUS_IS_OK(status)) {
2082 result = werror_to_ntstatus(werr);
2084 if (!NT_STATUS_IS_OK(status)) {
2085 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2086 "on domain %s failed: (%s)\n",
2087 domain->name, nt_errstr(status)));
2089 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2090 * every opcode on the DSSETUP pipe, continue with
2091 * no_dssetup mode here as well to get domain->initialized
2092 * set - gd */
2094 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2095 goto no_dssetup;
2098 TALLOC_FREE(mem_ctx);
2099 return;
2102 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2103 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2104 domain->native_mode = True;
2105 } else {
2106 domain->native_mode = False;
2109 no_dssetup:
2110 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2111 &ndr_table_lsarpc, &cli);
2113 if (!NT_STATUS_IS_OK(status)) {
2114 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2115 "PI_LSARPC on domain %s: (%s)\n",
2116 domain->name, nt_errstr(status)));
2117 TALLOC_FREE(cli);
2118 TALLOC_FREE(mem_ctx);
2119 return;
2122 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2123 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2125 if (NT_STATUS_IS_OK(status)) {
2126 /* This particular query is exactly what Win2k clients use
2127 to determine that the DC is active directory */
2128 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2129 &pol,
2130 LSA_POLICY_INFO_DNS,
2131 &lsa_info,
2132 &result);
2135 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2136 domain->active_directory = True;
2138 if (lsa_info->dns.name.string) {
2139 talloc_free(domain->name);
2140 domain->name = talloc_strdup(domain,
2141 lsa_info->dns.name.string);
2142 if (domain->name == NULL) {
2143 goto done;
2147 if (lsa_info->dns.dns_domain.string) {
2148 talloc_free(domain->alt_name);
2149 domain->alt_name =
2150 talloc_strdup(domain,
2151 lsa_info->dns.dns_domain.string);
2152 if (domain->alt_name == NULL) {
2153 goto done;
2157 /* See if we can set some domain trust flags about
2158 ourself */
2160 if (lsa_info->dns.dns_forest.string) {
2161 talloc_free(domain->forest_name);
2162 domain->forest_name =
2163 talloc_strdup(domain,
2164 lsa_info->dns.dns_forest.string);
2165 if (domain->forest_name == NULL) {
2166 goto done;
2169 if (strequal(domain->forest_name, domain->alt_name)) {
2170 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2174 if (lsa_info->dns.sid) {
2175 sid_copy(&domain->sid, lsa_info->dns.sid);
2177 } else {
2178 domain->active_directory = False;
2180 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2181 SEC_FLAG_MAXIMUM_ALLOWED,
2182 &pol);
2184 if (!NT_STATUS_IS_OK(status)) {
2185 goto done;
2188 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2189 &pol,
2190 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2191 &lsa_info,
2192 &result);
2193 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2195 if (lsa_info->account_domain.name.string) {
2196 talloc_free(domain->name);
2197 domain->name =
2198 talloc_strdup(domain,
2199 lsa_info->account_domain.name.string);
2202 if (lsa_info->account_domain.sid) {
2203 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2207 done:
2209 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2210 domain->name, domain->native_mode ? "" : "NOT "));
2212 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2213 domain->name, domain->active_directory ? "" : "NOT "));
2215 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2216 domain->can_do_validation6 = domain->active_directory;
2218 TALLOC_FREE(cli);
2220 TALLOC_FREE(mem_ctx);
2222 domain->initialized = True;
2225 /**********************************************************************
2226 Set the domain_flags (trust attributes, domain operating modes, etc...
2227 ***********************************************************************/
2229 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2231 /* we always have to contact our primary domain */
2233 if ( domain->primary ) {
2234 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2235 "primary domain\n"));
2236 set_dc_type_and_flags_connect( domain );
2237 return;
2240 /* Use our DC to get the information if possible */
2242 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2243 /* Otherwise, fallback to contacting the
2244 domain directly */
2245 set_dc_type_and_flags_connect( domain );
2248 return;
2253 /**********************************************************************
2254 ***********************************************************************/
2256 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2257 struct netlogon_creds_CredentialState **ppdc)
2259 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2260 struct rpc_pipe_client *netlogon_pipe;
2262 if (lp_client_schannel() == False) {
2263 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2266 result = cm_connect_netlogon(domain, &netlogon_pipe);
2267 if (!NT_STATUS_IS_OK(result)) {
2268 return result;
2271 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2272 netlogon pipe. */
2274 if (!domain->conn.netlogon_pipe->dc) {
2275 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2278 *ppdc = domain->conn.netlogon_pipe->dc;
2279 return NT_STATUS_OK;
2282 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2283 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2285 struct winbindd_cm_conn *conn;
2286 NTSTATUS status, result;
2287 struct netlogon_creds_CredentialState *p_creds;
2288 char *machine_password = NULL;
2289 char *machine_account = NULL;
2290 const char *domain_name = NULL;
2292 if (sid_check_is_our_sam(&domain->sid)) {
2293 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2296 status = init_dc_connection_rpc(domain);
2297 if (!NT_STATUS_IS_OK(status)) {
2298 return status;
2301 conn = &domain->conn;
2303 if (rpccli_is_connected(conn->samr_pipe)) {
2304 goto done;
2307 TALLOC_FREE(conn->samr_pipe);
2310 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2311 * sign and sealed pipe using the machine account password by
2312 * preference. If we can't - try schannel, if that fails, try
2313 * anonymous.
2316 if ((conn->cli->user_name[0] == '\0') ||
2317 (conn->cli->domain[0] == '\0') ||
2318 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2320 status = get_trust_creds(domain, &machine_password,
2321 &machine_account, NULL);
2322 if (!NT_STATUS_IS_OK(status)) {
2323 DEBUG(10, ("cm_connect_sam: No no user available for "
2324 "domain %s, trying schannel\n", conn->cli->domain));
2325 goto schannel;
2327 domain_name = domain->name;
2328 } else {
2329 machine_password = SMB_STRDUP(conn->cli->password);
2330 machine_account = SMB_STRDUP(conn->cli->user_name);
2331 domain_name = conn->cli->domain;
2334 if (!machine_password || !machine_account) {
2335 status = NT_STATUS_NO_MEMORY;
2336 goto done;
2339 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2340 authenticated SAMR pipe with sign & seal. */
2341 status = cli_rpc_pipe_open_spnego(conn->cli,
2342 &ndr_table_samr,
2343 NCACN_NP,
2344 GENSEC_OID_NTLMSSP,
2345 DCERPC_AUTH_LEVEL_PRIVACY,
2346 smbXcli_conn_remote_name(conn->cli->conn),
2347 domain_name,
2348 machine_account,
2349 machine_password,
2350 &conn->samr_pipe);
2352 if (!NT_STATUS_IS_OK(status)) {
2353 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2354 "pipe for domain %s using NTLMSSP "
2355 "authenticated pipe: user %s\\%s. Error was "
2356 "%s\n", domain->name, domain_name,
2357 machine_account, nt_errstr(status)));
2358 goto schannel;
2361 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2362 "domain %s using NTLMSSP authenticated "
2363 "pipe: user %s\\%s\n", domain->name,
2364 domain_name, machine_account));
2366 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2367 conn->samr_pipe->desthost,
2368 SEC_FLAG_MAXIMUM_ALLOWED,
2369 &conn->sam_connect_handle,
2370 &result);
2371 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2372 goto open_domain;
2374 if (NT_STATUS_IS_OK(status)) {
2375 status = result;
2378 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2379 "failed for domain %s, error was %s. Trying schannel\n",
2380 domain->name, nt_errstr(status) ));
2381 TALLOC_FREE(conn->samr_pipe);
2383 schannel:
2385 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2387 status = cm_get_schannel_creds(domain, &p_creds);
2388 if (!NT_STATUS_IS_OK(status)) {
2389 /* If this call fails - conn->cli can now be NULL ! */
2390 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2391 "for domain %s (error %s), trying anon\n",
2392 domain->name,
2393 nt_errstr(status) ));
2394 goto anonymous;
2396 status = cli_rpc_pipe_open_schannel_with_key
2397 (conn->cli, &ndr_table_samr, NCACN_NP,
2398 DCERPC_AUTH_LEVEL_PRIVACY,
2399 domain->name, &p_creds, &conn->samr_pipe);
2401 if (!NT_STATUS_IS_OK(status)) {
2402 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2403 "domain %s using schannel. Error was %s\n",
2404 domain->name, nt_errstr(status) ));
2405 goto anonymous;
2407 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2408 "schannel.\n", domain->name ));
2410 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2411 conn->samr_pipe->desthost,
2412 SEC_FLAG_MAXIMUM_ALLOWED,
2413 &conn->sam_connect_handle,
2414 &result);
2415 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2416 goto open_domain;
2418 if (NT_STATUS_IS_OK(status)) {
2419 status = result;
2421 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2422 "for domain %s, error was %s. Trying anonymous\n",
2423 domain->name, nt_errstr(status) ));
2424 TALLOC_FREE(conn->samr_pipe);
2426 anonymous:
2428 /* Finally fall back to anonymous. */
2429 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2430 &conn->samr_pipe);
2432 if (!NT_STATUS_IS_OK(status)) {
2433 goto done;
2436 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2437 conn->samr_pipe->desthost,
2438 SEC_FLAG_MAXIMUM_ALLOWED,
2439 &conn->sam_connect_handle,
2440 &result);
2441 if (!NT_STATUS_IS_OK(status)) {
2442 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2443 "for domain %s Error was %s\n",
2444 domain->name, nt_errstr(status) ));
2445 goto done;
2447 if (!NT_STATUS_IS_OK(result)) {
2448 status = result;
2449 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2450 "for domain %s Error was %s\n",
2451 domain->name, nt_errstr(result)));
2452 goto done;
2455 open_domain:
2456 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2457 mem_ctx,
2458 &conn->sam_connect_handle,
2459 SEC_FLAG_MAXIMUM_ALLOWED,
2460 &domain->sid,
2461 &conn->sam_domain_handle,
2462 &result);
2463 if (!NT_STATUS_IS_OK(status)) {
2464 goto done;
2467 status = result;
2468 done:
2470 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2472 * if we got access denied, we might just have no access rights
2473 * to talk to the remote samr server server (e.g. when we are a
2474 * PDC and we are connecting a w2k8 pdc via an interdomain
2475 * trust). In that case do not invalidate the whole connection
2476 * stack
2478 TALLOC_FREE(conn->samr_pipe);
2479 ZERO_STRUCT(conn->sam_domain_handle);
2480 return status;
2481 } else if (!NT_STATUS_IS_OK(status)) {
2482 invalidate_cm_connection(conn);
2483 return status;
2486 *cli = conn->samr_pipe;
2487 *sam_handle = conn->sam_domain_handle;
2488 SAFE_FREE(machine_password);
2489 SAFE_FREE(machine_account);
2490 return status;
2493 /**********************************************************************
2494 open an schanneld ncacn_ip_tcp connection to LSA
2495 ***********************************************************************/
2497 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2498 TALLOC_CTX *mem_ctx,
2499 struct rpc_pipe_client **cli)
2501 struct winbindd_cm_conn *conn;
2502 struct netlogon_creds_CredentialState *creds;
2503 NTSTATUS status;
2505 DEBUG(10,("cm_connect_lsa_tcp\n"));
2507 status = init_dc_connection_rpc(domain);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 return status;
2512 conn = &domain->conn;
2514 if (conn->lsa_pipe_tcp &&
2515 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2516 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2517 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2518 goto done;
2521 TALLOC_FREE(conn->lsa_pipe_tcp);
2523 status = cm_get_schannel_creds(domain, &creds);
2524 if (!NT_STATUS_IS_OK(status)) {
2525 goto done;
2528 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2529 &ndr_table_lsarpc,
2530 NCACN_IP_TCP,
2531 DCERPC_AUTH_LEVEL_PRIVACY,
2532 domain->name,
2533 &creds,
2534 &conn->lsa_pipe_tcp);
2535 if (!NT_STATUS_IS_OK(status)) {
2536 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2537 nt_errstr(status)));
2538 goto done;
2541 done:
2542 if (!NT_STATUS_IS_OK(status)) {
2543 TALLOC_FREE(conn->lsa_pipe_tcp);
2544 return status;
2547 *cli = conn->lsa_pipe_tcp;
2549 return status;
2552 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2553 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2555 struct winbindd_cm_conn *conn;
2556 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2557 struct netlogon_creds_CredentialState *p_creds;
2559 result = init_dc_connection_rpc(domain);
2560 if (!NT_STATUS_IS_OK(result))
2561 return result;
2563 conn = &domain->conn;
2565 if (rpccli_is_connected(conn->lsa_pipe)) {
2566 goto done;
2569 TALLOC_FREE(conn->lsa_pipe);
2571 if ((conn->cli->user_name[0] == '\0') ||
2572 (conn->cli->domain[0] == '\0') ||
2573 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2574 DEBUG(10, ("cm_connect_lsa: No no user available for "
2575 "domain %s, trying schannel\n", conn->cli->domain));
2576 goto schannel;
2579 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2580 * authenticated LSA pipe with sign & seal. */
2581 result = cli_rpc_pipe_open_spnego
2582 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2583 GENSEC_OID_NTLMSSP,
2584 DCERPC_AUTH_LEVEL_PRIVACY,
2585 smbXcli_conn_remote_name(conn->cli->conn),
2586 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2587 &conn->lsa_pipe);
2589 if (!NT_STATUS_IS_OK(result)) {
2590 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2591 "domain %s using NTLMSSP authenticated pipe: user "
2592 "%s\\%s. Error was %s. Trying schannel.\n",
2593 domain->name, conn->cli->domain,
2594 conn->cli->user_name, nt_errstr(result)));
2595 goto schannel;
2598 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2599 "NTLMSSP authenticated pipe: user %s\\%s\n",
2600 domain->name, conn->cli->domain, conn->cli->user_name ));
2602 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2603 SEC_FLAG_MAXIMUM_ALLOWED,
2604 &conn->lsa_policy);
2605 if (NT_STATUS_IS_OK(result)) {
2606 goto done;
2609 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2610 "schannel\n"));
2612 TALLOC_FREE(conn->lsa_pipe);
2614 schannel:
2616 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2618 result = cm_get_schannel_creds(domain, &p_creds);
2619 if (!NT_STATUS_IS_OK(result)) {
2620 /* If this call fails - conn->cli can now be NULL ! */
2621 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2622 "for domain %s (error %s), trying anon\n",
2623 domain->name,
2624 nt_errstr(result) ));
2625 goto anonymous;
2627 result = cli_rpc_pipe_open_schannel_with_key
2628 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2629 DCERPC_AUTH_LEVEL_PRIVACY,
2630 domain->name, &p_creds, &conn->lsa_pipe);
2632 if (!NT_STATUS_IS_OK(result)) {
2633 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2634 "domain %s using schannel. Error was %s\n",
2635 domain->name, nt_errstr(result) ));
2636 goto anonymous;
2638 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2639 "schannel.\n", domain->name ));
2641 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2642 SEC_FLAG_MAXIMUM_ALLOWED,
2643 &conn->lsa_policy);
2644 if (NT_STATUS_IS_OK(result)) {
2645 goto done;
2648 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2649 "anonymous\n"));
2651 TALLOC_FREE(conn->lsa_pipe);
2653 anonymous:
2655 result = cli_rpc_pipe_open_noauth(conn->cli,
2656 &ndr_table_lsarpc,
2657 &conn->lsa_pipe);
2658 if (!NT_STATUS_IS_OK(result)) {
2659 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2660 goto done;
2663 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2664 SEC_FLAG_MAXIMUM_ALLOWED,
2665 &conn->lsa_policy);
2666 done:
2667 if (!NT_STATUS_IS_OK(result)) {
2668 invalidate_cm_connection(conn);
2669 return result;
2672 *cli = conn->lsa_pipe;
2673 *lsa_policy = conn->lsa_policy;
2674 return result;
2677 /****************************************************************************
2678 Open a LSA connection to a DC, suiteable for LSA lookup calls.
2679 ****************************************************************************/
2681 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
2682 TALLOC_CTX *mem_ctx,
2683 struct rpc_pipe_client **cli,
2684 struct policy_handle *lsa_policy)
2686 NTSTATUS status;
2688 if (domain->can_do_ncacn_ip_tcp) {
2689 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2690 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
2691 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
2692 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
2693 invalidate_cm_connection(&domain->conn);
2694 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2696 if (NT_STATUS_IS_OK(status)) {
2697 return status;
2701 * we tried twice to connect via ncan_ip_tcp and schannel and
2702 * failed - maybe it is a trusted domain we can't connect to ?
2703 * do not try tcp next time - gd
2705 domain->can_do_ncacn_ip_tcp = false;
2708 status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
2710 return status;
2713 /****************************************************************************
2714 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2715 session key stored in conn->netlogon_pipe->dc->sess_key.
2716 ****************************************************************************/
2718 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2719 struct rpc_pipe_client **cli)
2721 struct winbindd_cm_conn *conn;
2722 NTSTATUS result;
2724 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
2725 uint8_t mach_pwd[16];
2726 enum netr_SchannelType sec_chan_type;
2727 const char *account_name;
2728 struct rpc_pipe_client *netlogon_pipe = NULL;
2730 *cli = NULL;
2732 result = init_dc_connection_rpc(domain);
2733 if (!NT_STATUS_IS_OK(result)) {
2734 return result;
2737 conn = &domain->conn;
2739 if (rpccli_is_connected(conn->netlogon_pipe)) {
2740 *cli = conn->netlogon_pipe;
2741 return NT_STATUS_OK;
2744 TALLOC_FREE(conn->netlogon_pipe);
2746 result = cli_rpc_pipe_open_noauth(conn->cli,
2747 &ndr_table_netlogon,
2748 &netlogon_pipe);
2749 if (!NT_STATUS_IS_OK(result)) {
2750 return result;
2753 if ((!IS_DC) && (!domain->primary)) {
2754 /* Clear the schannel request bit and drop down */
2755 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2756 goto no_schannel;
2759 if (lp_client_schannel() != False) {
2760 neg_flags |= NETLOGON_NEG_SCHANNEL;
2763 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2764 &sec_chan_type))
2766 TALLOC_FREE(netlogon_pipe);
2767 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2770 result = rpccli_netlogon_setup_creds(
2771 netlogon_pipe,
2772 domain->dcname, /* server name. */
2773 domain->name, /* domain name */
2774 lp_netbios_name(), /* client name */
2775 account_name, /* machine account */
2776 mach_pwd, /* machine password */
2777 sec_chan_type, /* from get_trust_pw */
2778 &neg_flags);
2780 if (!NT_STATUS_IS_OK(result)) {
2781 TALLOC_FREE(netlogon_pipe);
2782 return result;
2785 if ((lp_client_schannel() == True) &&
2786 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2787 DEBUG(3, ("Server did not offer schannel\n"));
2788 TALLOC_FREE(netlogon_pipe);
2789 return NT_STATUS_ACCESS_DENIED;
2792 no_schannel:
2793 if ((lp_client_schannel() == False) ||
2794 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2796 * NetSamLogonEx only works for schannel
2798 domain->can_do_samlogon_ex = False;
2800 /* We're done - just keep the existing connection to NETLOGON
2801 * open */
2802 conn->netlogon_pipe = netlogon_pipe;
2803 *cli = conn->netlogon_pipe;
2804 return NT_STATUS_OK;
2807 /* Using the credentials from the first pipe, open a signed and sealed
2808 second netlogon pipe. The session key is stored in the schannel
2809 part of the new pipe auth struct.
2812 result = cli_rpc_pipe_open_schannel_with_key(
2813 conn->cli, &ndr_table_netlogon, NCACN_NP,
2814 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2815 &conn->netlogon_pipe);
2817 /* We can now close the initial netlogon pipe. */
2818 TALLOC_FREE(netlogon_pipe);
2820 if (!NT_STATUS_IS_OK(result)) {
2821 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2822 "was %s\n", nt_errstr(result)));
2824 invalidate_cm_connection(conn);
2825 return result;
2829 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2830 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2831 * supported). We used to only try SamLogonEx for AD, but
2832 * Samba DCs can also do it. And because we don't distinguish
2833 * between Samba and NT4, always try it once.
2835 domain->can_do_samlogon_ex = true;
2837 *cli = conn->netlogon_pipe;
2838 return NT_STATUS_OK;
2841 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2842 void *private_data,
2843 uint32_t msg_type,
2844 struct server_id server_id,
2845 DATA_BLOB *data)
2847 struct winbindd_domain *domain;
2848 char *freeit = NULL;
2849 char *addr;
2851 if ((data == NULL)
2852 || (data->data == NULL)
2853 || (data->length == 0)
2854 || (data->data[data->length-1] != '\0')) {
2855 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2856 "string\n"));
2857 return;
2860 addr = (char *)data->data;
2861 DEBUG(10, ("IP %s dropped\n", addr));
2863 if (!is_ipaddress(addr)) {
2864 char *slash;
2866 * Some code sends us ip addresses with the /netmask
2867 * suffix
2869 slash = strchr(addr, '/');
2870 if (slash == NULL) {
2871 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2872 addr));
2873 return;
2875 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2876 if (freeit == NULL) {
2877 DEBUG(1, ("talloc failed\n"));
2878 return;
2880 addr = freeit;
2881 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2884 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2885 char sockaddr[INET6_ADDRSTRLEN];
2887 if (!cli_state_is_connected(domain->conn.cli)) {
2888 continue;
2891 print_sockaddr(sockaddr, sizeof(sockaddr),
2892 smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
2894 if (strequal(sockaddr, addr)) {
2895 smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2898 TALLOC_FREE(freeit);