s3-rpc_client: Move client pipe functions to own header.
[Samba/gebeck_regimport.git] / source3 / winbindd / winbindd_cm.c
blobf221532824e030e1a769b7cc4a2a60b6708b2b06
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 "librpc/gen_ndr/messaging.h"
73 #include "libsmb/clidgram.h"
74 #include "ads.h"
75 #include "secrets.h"
76 #include "../libcli/security/security.h"
78 #undef DBGC_CLASS
79 #define DBGC_CLASS DBGC_WINBIND
81 struct dc_name_ip {
82 fstring name;
83 struct sockaddr_storage ss;
86 extern struct winbindd_methods reconnect_methods;
87 extern bool override_logfile;
89 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
90 static void set_dc_type_and_flags( struct winbindd_domain *domain );
91 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
92 struct dc_name_ip **dcs, int *num_dcs);
94 /****************************************************************
95 Child failed to find DC's. Reschedule check.
96 ****************************************************************/
98 static void msg_failed_to_go_online(struct messaging_context *msg,
99 void *private_data,
100 uint32_t msg_type,
101 struct server_id server_id,
102 DATA_BLOB *data)
104 struct winbindd_domain *domain;
105 const char *domainname = (const char *)data->data;
107 if (data->data == NULL || data->length == 0) {
108 return;
111 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
113 for (domain = domain_list(); domain; domain = domain->next) {
114 if (domain->internal) {
115 continue;
118 if (strequal(domain->name, domainname)) {
119 if (domain->online) {
120 /* We're already online, ignore. */
121 DEBUG(5,("msg_fail_to_go_online: domain %s "
122 "already online.\n", domainname));
123 continue;
126 /* Reschedule the online check. */
127 set_domain_offline(domain);
128 break;
133 /****************************************************************
134 Actually cause a reconnect from a message.
135 ****************************************************************/
137 static void msg_try_to_go_online(struct messaging_context *msg,
138 void *private_data,
139 uint32_t msg_type,
140 struct server_id server_id,
141 DATA_BLOB *data)
143 struct winbindd_domain *domain;
144 const char *domainname = (const char *)data->data;
146 if (data->data == NULL || data->length == 0) {
147 return;
150 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
152 for (domain = domain_list(); domain; domain = domain->next) {
153 if (domain->internal) {
154 continue;
157 if (strequal(domain->name, domainname)) {
159 if (domain->online) {
160 /* We're already online, ignore. */
161 DEBUG(5,("msg_try_to_go_online: domain %s "
162 "already online.\n", domainname));
163 continue;
166 /* This call takes care of setting the online
167 flag to true if we connected, or re-adding
168 the offline handler if false. Bypasses online
169 check so always does network calls. */
171 init_dc_connection_network(domain);
172 break;
177 /****************************************************************
178 Fork a child to try and contact a DC. Do this as contacting a
179 DC requires blocking lookups and we don't want to block our
180 parent.
181 ****************************************************************/
183 static bool fork_child_dc_connect(struct winbindd_domain *domain)
185 struct dc_name_ip *dcs = NULL;
186 int num_dcs = 0;
187 TALLOC_CTX *mem_ctx = NULL;
188 pid_t parent_pid = sys_getpid();
189 char *lfile = NULL;
191 if (domain->dc_probe_pid != (pid_t)-1) {
193 * We might already have a DC probe
194 * child working, check.
196 if (process_exists_by_pid(domain->dc_probe_pid)) {
197 DEBUG(10,("fork_child_dc_connect: pid %u already "
198 "checking for DC's.\n",
199 (unsigned int)domain->dc_probe_pid));
200 return true;
202 domain->dc_probe_pid = (pid_t)-1;
205 domain->dc_probe_pid = sys_fork();
207 if (domain->dc_probe_pid == (pid_t)-1) {
208 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
209 return False;
212 if (domain->dc_probe_pid != (pid_t)0) {
213 /* Parent */
214 messaging_register(winbind_messaging_context(), NULL,
215 MSG_WINBIND_TRY_TO_GO_ONLINE,
216 msg_try_to_go_online);
217 messaging_register(winbind_messaging_context(), NULL,
218 MSG_WINBIND_FAILED_TO_GO_ONLINE,
219 msg_failed_to_go_online);
220 return True;
223 /* Child. */
225 /* Leave messages blocked - we will never process one. */
227 if (!override_logfile) {
228 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
229 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
230 _exit(1);
234 if (!winbindd_reinit_after_fork(lfile)) {
235 messaging_send_buf(winbind_messaging_context(),
236 pid_to_procid(parent_pid),
237 MSG_WINBIND_FAILED_TO_GO_ONLINE,
238 (uint8 *)domain->name,
239 strlen(domain->name)+1);
240 _exit(1);
242 SAFE_FREE(lfile);
244 mem_ctx = talloc_init("fork_child_dc_connect");
245 if (!mem_ctx) {
246 DEBUG(0,("talloc_init failed.\n"));
247 messaging_send_buf(winbind_messaging_context(),
248 pid_to_procid(parent_pid),
249 MSG_WINBIND_FAILED_TO_GO_ONLINE,
250 (uint8 *)domain->name,
251 strlen(domain->name)+1);
252 _exit(1);
255 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
256 /* Still offline ? Can't find DC's. */
257 messaging_send_buf(winbind_messaging_context(),
258 pid_to_procid(parent_pid),
259 MSG_WINBIND_FAILED_TO_GO_ONLINE,
260 (uint8 *)domain->name,
261 strlen(domain->name)+1);
262 _exit(0);
265 /* We got a DC. Send a message to our parent to get it to
266 try and do the same. */
268 messaging_send_buf(winbind_messaging_context(),
269 pid_to_procid(parent_pid),
270 MSG_WINBIND_TRY_TO_GO_ONLINE,
271 (uint8 *)domain->name,
272 strlen(domain->name)+1);
273 _exit(0);
276 /****************************************************************
277 Handler triggered if we're offline to try and detect a DC.
278 ****************************************************************/
280 static void check_domain_online_handler(struct event_context *ctx,
281 struct timed_event *te,
282 struct timeval now,
283 void *private_data)
285 struct winbindd_domain *domain =
286 (struct winbindd_domain *)private_data;
288 DEBUG(10,("check_domain_online_handler: called for domain "
289 "%s (online = %s)\n", domain->name,
290 domain->online ? "True" : "False" ));
292 TALLOC_FREE(domain->check_online_event);
294 /* Are we still in "startup" mode ? */
296 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
297 /* No longer in "startup" mode. */
298 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
299 domain->name ));
300 domain->startup = False;
303 /* We've been told to stay offline, so stay
304 that way. */
306 if (get_global_winbindd_state_offline()) {
307 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
308 domain->name ));
309 return;
312 /* Fork a child to test if it can contact a DC.
313 If it can then send ourselves a message to
314 cause a reconnect. */
316 fork_child_dc_connect(domain);
319 /****************************************************************
320 If we're still offline setup the timeout check.
321 ****************************************************************/
323 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
325 int wbr = lp_winbind_reconnect_delay();
327 if (domain->startup) {
328 domain->check_online_timeout = 10;
329 } else if (domain->check_online_timeout < wbr) {
330 domain->check_online_timeout = wbr;
334 /****************************************************************
335 Set domain offline and also add handler to put us back online
336 if we detect a DC.
337 ****************************************************************/
339 void set_domain_offline(struct winbindd_domain *domain)
341 DEBUG(10,("set_domain_offline: called for domain %s\n",
342 domain->name ));
344 TALLOC_FREE(domain->check_online_event);
346 if (domain->internal) {
347 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
348 domain->name ));
349 return;
352 domain->online = False;
354 /* Offline domains are always initialized. They're
355 re-initialized when they go back online. */
357 domain->initialized = True;
359 /* We only add the timeout handler that checks and
360 allows us to go back online when we've not
361 been told to remain offline. */
363 if (get_global_winbindd_state_offline()) {
364 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
365 domain->name ));
366 return;
369 /* If we're in startup mode, check again in 10 seconds, not in
370 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
372 calc_new_online_timeout_check(domain);
374 domain->check_online_event = event_add_timed(winbind_event_context(),
375 NULL,
376 timeval_current_ofs(domain->check_online_timeout,0),
377 check_domain_online_handler,
378 domain);
380 /* The above *has* to succeed for winbindd to work. */
381 if (!domain->check_online_event) {
382 smb_panic("set_domain_offline: failed to add online handler");
385 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
386 domain->name ));
388 /* Send an offline message to the idmap child when our
389 primary domain goes offline */
391 if ( domain->primary ) {
392 struct winbindd_child *idmap = idmap_child();
394 if ( idmap->pid != 0 ) {
395 messaging_send_buf(winbind_messaging_context(),
396 pid_to_procid(idmap->pid),
397 MSG_WINBIND_OFFLINE,
398 (uint8 *)domain->name,
399 strlen(domain->name)+1);
403 return;
406 /****************************************************************
407 Set domain online - if allowed.
408 ****************************************************************/
410 static void set_domain_online(struct winbindd_domain *domain)
412 DEBUG(10,("set_domain_online: called for domain %s\n",
413 domain->name ));
415 if (domain->internal) {
416 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
417 domain->name ));
418 return;
421 if (get_global_winbindd_state_offline()) {
422 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
423 domain->name ));
424 return;
427 winbindd_set_locator_kdc_envs(domain);
429 /* If we are waiting to get a krb5 ticket, trigger immediately. */
430 ccache_regain_all_now();
432 /* Ok, we're out of any startup mode now... */
433 domain->startup = False;
435 if (domain->online == False) {
436 /* We were offline - now we're online. We default to
437 using the MS-RPC backend if we started offline,
438 and if we're going online for the first time we
439 should really re-initialize the backends and the
440 checks to see if we're talking to an AD or NT domain.
443 domain->initialized = False;
445 /* 'reconnect_methods' is the MS-RPC backend. */
446 if (domain->backend == &reconnect_methods) {
447 domain->backend = NULL;
451 /* Ensure we have no online timeout checks. */
452 domain->check_online_timeout = 0;
453 TALLOC_FREE(domain->check_online_event);
455 /* Ensure we ignore any pending child messages. */
456 messaging_deregister(winbind_messaging_context(),
457 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
458 messaging_deregister(winbind_messaging_context(),
459 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
461 domain->online = True;
463 /* Send an online message to the idmap child when our
464 primary domain comes online */
466 if ( domain->primary ) {
467 struct winbindd_child *idmap = idmap_child();
469 if ( idmap->pid != 0 ) {
470 messaging_send_buf(winbind_messaging_context(),
471 pid_to_procid(idmap->pid),
472 MSG_WINBIND_ONLINE,
473 (uint8 *)domain->name,
474 strlen(domain->name)+1);
478 return;
481 /****************************************************************
482 Requested to set a domain online.
483 ****************************************************************/
485 void set_domain_online_request(struct winbindd_domain *domain)
487 struct timeval tev;
489 DEBUG(10,("set_domain_online_request: called for domain %s\n",
490 domain->name ));
492 if (get_global_winbindd_state_offline()) {
493 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
494 domain->name ));
495 return;
498 if (domain->internal) {
499 DEBUG(10, ("set_domain_online_request: Internal domains are "
500 "always online\n"));
501 return;
504 /* We've been told it's safe to go online and
505 try and connect to a DC. But I don't believe it
506 because network manager seems to lie.
507 Wait at least 5 seconds. Heuristics suck... */
510 GetTimeOfDay(&tev);
512 /* Go into "startup" mode again. */
513 domain->startup_time = time_mono(NULL);
514 domain->startup = True;
516 tev.tv_sec += 5;
518 if (!domain->check_online_event) {
519 /* If we've come from being globally offline we
520 don't have a check online event handler set.
521 We need to add one now we're trying to go
522 back online. */
524 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
525 domain->name ));
528 TALLOC_FREE(domain->check_online_event);
530 domain->check_online_event = event_add_timed(winbind_event_context(),
531 NULL,
532 tev,
533 check_domain_online_handler,
534 domain);
536 /* The above *has* to succeed for winbindd to work. */
537 if (!domain->check_online_event) {
538 smb_panic("set_domain_online_request: failed to add online handler");
542 /****************************************************************
543 Add -ve connection cache entries for domain and realm.
544 ****************************************************************/
546 static void winbind_add_failed_connection_entry(
547 const struct winbindd_domain *domain,
548 const char *server,
549 NTSTATUS result)
551 add_failed_connection_entry(domain->name, server, result);
552 /* If this was the saf name for the last thing we talked to,
553 remove it. */
554 saf_delete(domain->name);
555 if (*domain->alt_name) {
556 add_failed_connection_entry(domain->alt_name, server, result);
557 saf_delete(domain->alt_name);
559 winbindd_unset_locator_kdc_env(domain);
562 /* Choose between anonymous or authenticated connections. We need to use
563 an authenticated connection if DCs have the RestrictAnonymous registry
564 entry set > 0, or the "Additional restrictions for anonymous
565 connections" set in the win2k Local Security Policy.
567 Caller to free() result in domain, username, password
570 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
572 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
573 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
574 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
576 if (*username && **username) {
578 if (!*domain || !**domain)
579 *domain = smb_xstrdup(lp_workgroup());
581 if (!*password || !**password)
582 *password = smb_xstrdup("");
584 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
585 *domain, *username));
587 } else {
588 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
589 *username = smb_xstrdup("");
590 *domain = smb_xstrdup("");
591 *password = smb_xstrdup("");
595 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
596 fstring dcname,
597 struct sockaddr_storage *dc_ss)
599 struct winbindd_domain *our_domain = NULL;
600 struct rpc_pipe_client *netlogon_pipe = NULL;
601 NTSTATUS result;
602 WERROR werr;
603 TALLOC_CTX *mem_ctx;
604 unsigned int orig_timeout;
605 const char *tmp = NULL;
606 const char *p;
607 struct dcerpc_binding_handle *b;
609 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
610 * moment.... */
612 if (IS_DC) {
613 return False;
616 if (domain->primary) {
617 return False;
620 our_domain = find_our_domain();
622 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
623 return False;
626 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
627 if (!NT_STATUS_IS_OK(result)) {
628 talloc_destroy(mem_ctx);
629 return False;
632 b = netlogon_pipe->binding_handle;
634 /* This call can take a long time - allow the server to time out.
635 35 seconds should do it. */
637 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
639 if (our_domain->active_directory) {
640 struct netr_DsRGetDCNameInfo *domain_info = NULL;
642 result = dcerpc_netr_DsRGetDCName(b,
643 mem_ctx,
644 our_domain->dcname,
645 domain->name,
646 NULL,
647 NULL,
648 DS_RETURN_DNS_NAME,
649 &domain_info,
650 &werr);
651 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
652 tmp = talloc_strdup(
653 mem_ctx, domain_info->dc_unc);
654 if (tmp == NULL) {
655 DEBUG(0, ("talloc_strdup failed\n"));
656 talloc_destroy(mem_ctx);
657 return false;
659 if (strlen(domain->alt_name) == 0) {
660 fstrcpy(domain->alt_name,
661 domain_info->domain_name);
663 if (strlen(domain->forest_name) == 0) {
664 fstrcpy(domain->forest_name,
665 domain_info->forest_name);
668 } else {
669 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
670 our_domain->dcname,
671 domain->name,
672 &tmp,
673 &werr);
676 /* And restore our original timeout. */
677 rpccli_set_timeout(netlogon_pipe, orig_timeout);
679 if (!NT_STATUS_IS_OK(result)) {
680 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
681 nt_errstr(result)));
682 talloc_destroy(mem_ctx);
683 return false;
686 if (!W_ERROR_IS_OK(werr)) {
687 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
688 win_errstr(werr)));
689 talloc_destroy(mem_ctx);
690 return false;
693 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
694 p = strip_hostname(tmp);
696 fstrcpy(dcname, p);
698 talloc_destroy(mem_ctx);
700 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
702 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
703 return False;
706 return True;
710 * Helper function to assemble trust password and account name
712 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
713 char **machine_password,
714 char **machine_account,
715 char **machine_krb5_principal)
717 const char *account_name;
718 const char *name = NULL;
720 /* If we are a DC and this is not our own domain */
722 if (IS_DC) {
723 name = domain->name;
724 } else {
725 struct winbindd_domain *our_domain = find_our_domain();
727 if (!our_domain)
728 return NT_STATUS_INVALID_SERVER_STATE;
730 name = our_domain->name;
733 if (!get_trust_pw_clear(name, machine_password,
734 &account_name, NULL))
736 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
739 if ((machine_account != NULL) &&
740 (asprintf(machine_account, "%s$", account_name) == -1))
742 return NT_STATUS_NO_MEMORY;
745 /* For now assume our machine account only exists in our domain */
747 if (machine_krb5_principal != NULL)
749 struct winbindd_domain *our_domain = find_our_domain();
751 if (!our_domain) {
752 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
755 if (asprintf(machine_krb5_principal, "%s$@%s",
756 account_name, our_domain->alt_name) == -1)
758 return NT_STATUS_NO_MEMORY;
761 strupper_m(*machine_krb5_principal);
764 return NT_STATUS_OK;
767 /************************************************************************
768 Given a fd with a just-connected TCP connection to a DC, open a connection
769 to the pipe.
770 ************************************************************************/
772 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
773 const int sockfd,
774 const char *controller,
775 struct cli_state **cli,
776 bool *retry)
778 char *machine_password = NULL;
779 char *machine_krb5_principal = NULL;
780 char *machine_account = NULL;
781 char *ipc_username = NULL;
782 char *ipc_domain = NULL;
783 char *ipc_password = NULL;
785 struct named_mutex *mutex;
787 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
789 struct sockaddr peeraddr;
790 socklen_t peeraddr_len;
792 struct sockaddr_in *peeraddr_in =
793 (struct sockaddr_in *)(void *)&peeraddr;
795 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
796 controller, domain->name ));
798 *retry = True;
800 mutex = grab_named_mutex(talloc_tos(), controller,
801 WINBIND_SERVER_MUTEX_WAIT_TIME);
802 if (mutex == NULL) {
803 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
804 controller));
805 result = NT_STATUS_POSSIBLE_DEADLOCK;
806 goto done;
809 if ((*cli = cli_initialise()) == NULL) {
810 DEBUG(1, ("Could not cli_initialize\n"));
811 result = NT_STATUS_NO_MEMORY;
812 goto done;
815 (*cli)->timeout = 10000; /* 10 seconds */
816 (*cli)->fd = sockfd;
817 fstrcpy((*cli)->desthost, controller);
818 (*cli)->use_kerberos = True;
820 peeraddr_len = sizeof(peeraddr);
822 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
823 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
824 strerror(errno)));
825 result = NT_STATUS_UNSUCCESSFUL;
826 goto done;
829 if ((peeraddr_len != sizeof(struct sockaddr_in))
830 #ifdef HAVE_IPV6
831 && (peeraddr_len != sizeof(struct sockaddr_in6))
832 #endif
834 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
835 peeraddr_len));
836 result = NT_STATUS_UNSUCCESSFUL;
837 goto done;
840 if ((peeraddr_in->sin_family != PF_INET)
841 #ifdef HAVE_IPV6
842 && (peeraddr_in->sin_family != PF_INET6)
843 #endif
845 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
846 peeraddr_in->sin_family));
847 result = NT_STATUS_UNSUCCESSFUL;
848 goto done;
851 result = cli_negprot(*cli);
853 if (!NT_STATUS_IS_OK(result)) {
854 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
855 goto done;
858 if (!is_dc_trusted_domain_situation(domain->name) &&
859 (*cli)->protocol >= PROTOCOL_NT1 &&
860 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
862 ADS_STATUS ads_status;
864 result = get_trust_creds(domain, &machine_password,
865 &machine_account,
866 &machine_krb5_principal);
867 if (!NT_STATUS_IS_OK(result)) {
868 goto anon_fallback;
871 if (lp_security() == SEC_ADS) {
873 /* Try a krb5 session */
875 (*cli)->use_kerberos = True;
876 DEBUG(5, ("connecting to %s from %s with kerberos principal "
877 "[%s] and realm [%s]\n", controller, global_myname(),
878 machine_krb5_principal, domain->alt_name));
880 winbindd_set_locator_kdc_envs(domain);
882 ads_status = cli_session_setup_spnego(*cli,
883 machine_krb5_principal,
884 machine_password,
885 lp_workgroup(),
886 domain->alt_name);
888 if (!ADS_ERR_OK(ads_status)) {
889 DEBUG(4,("failed kerberos session setup with %s\n",
890 ads_errstr(ads_status)));
893 result = ads_ntstatus(ads_status);
894 if (NT_STATUS_IS_OK(result)) {
895 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
896 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
897 if (!NT_STATUS_IS_OK(result)) {
898 goto done;
900 goto session_setup_done;
904 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
905 (*cli)->use_kerberos = False;
907 DEBUG(5, ("connecting to %s from %s with username "
908 "[%s]\\[%s]\n", controller, global_myname(),
909 lp_workgroup(), machine_account));
911 ads_status = cli_session_setup_spnego(*cli,
912 machine_account,
913 machine_password,
914 lp_workgroup(),
915 NULL);
916 if (!ADS_ERR_OK(ads_status)) {
917 DEBUG(4, ("authenticated session setup failed with %s\n",
918 ads_errstr(ads_status)));
921 result = ads_ntstatus(ads_status);
922 if (NT_STATUS_IS_OK(result)) {
923 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
924 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
925 if (!NT_STATUS_IS_OK(result)) {
926 goto done;
928 goto session_setup_done;
932 /* Fall back to non-kerberos session setup with auth_user */
934 (*cli)->use_kerberos = False;
936 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
938 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
939 (strlen(ipc_username) > 0)) {
941 /* Only try authenticated if we have a username */
943 DEBUG(5, ("connecting to %s from %s with username "
944 "[%s]\\[%s]\n", controller, global_myname(),
945 ipc_domain, ipc_username));
947 if (NT_STATUS_IS_OK(cli_session_setup(
948 *cli, ipc_username,
949 ipc_password, strlen(ipc_password)+1,
950 ipc_password, strlen(ipc_password)+1,
951 ipc_domain))) {
952 /* Successful logon with given username. */
953 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
954 if (!NT_STATUS_IS_OK(result)) {
955 goto done;
957 goto session_setup_done;
958 } else {
959 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
960 ipc_domain, ipc_username ));
964 anon_fallback:
966 /* Fall back to anonymous connection, this might fail later */
967 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
968 "connection for DC %s\n",
969 controller ));
971 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
972 NULL, 0, ""))) {
973 DEBUG(5, ("Connected anonymously\n"));
974 result = cli_init_creds(*cli, "", "", "");
975 if (!NT_STATUS_IS_OK(result)) {
976 goto done;
978 goto session_setup_done;
981 result = cli_nt_error(*cli);
983 if (NT_STATUS_IS_OK(result))
984 result = NT_STATUS_UNSUCCESSFUL;
986 /* We can't session setup */
988 goto done;
990 session_setup_done:
992 /* cache the server name for later connections */
994 saf_store( domain->name, (*cli)->desthost );
995 if (domain->alt_name && (*cli)->use_kerberos) {
996 saf_store( domain->alt_name, (*cli)->desthost );
999 winbindd_set_locator_kdc_envs(domain);
1001 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
1003 if (!NT_STATUS_IS_OK(result)) {
1004 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1005 goto done;
1008 TALLOC_FREE(mutex);
1009 *retry = False;
1011 /* set the domain if empty; needed for schannel connections */
1012 if ( !(*cli)->domain[0] ) {
1013 result = cli_set_domain((*cli), domain->name);
1014 if (!NT_STATUS_IS_OK(result)) {
1015 return result;
1019 result = NT_STATUS_OK;
1021 done:
1022 TALLOC_FREE(mutex);
1023 SAFE_FREE(machine_account);
1024 SAFE_FREE(machine_password);
1025 SAFE_FREE(machine_krb5_principal);
1026 SAFE_FREE(ipc_username);
1027 SAFE_FREE(ipc_domain);
1028 SAFE_FREE(ipc_password);
1030 if (!NT_STATUS_IS_OK(result)) {
1031 winbind_add_failed_connection_entry(domain, controller, result);
1032 if ((*cli) != NULL) {
1033 cli_shutdown(*cli);
1034 *cli = NULL;
1038 return result;
1041 /*******************************************************************
1042 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1043 array.
1045 Keeps the list unique by not adding duplicate entries.
1047 @param[in] mem_ctx talloc memory context to allocate from
1048 @param[in] domain_name domain of the DC
1049 @param[in] dcname name of the DC to add to the list
1050 @param[in] pss Internet address and port pair to add to the list
1051 @param[in,out] dcs array of dc_name_ip structures to add to
1052 @param[in,out] num_dcs number of dcs returned in the dcs array
1053 @return true if the list was added to, false otherwise
1054 *******************************************************************/
1056 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1057 const char *dcname, struct sockaddr_storage *pss,
1058 struct dc_name_ip **dcs, int *num)
1060 int i = 0;
1062 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1063 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1064 return False;
1067 /* Make sure there's no duplicates in the list */
1068 for (i=0; i<*num; i++)
1069 if (sockaddr_equal(
1070 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1071 (struct sockaddr *)(void *)pss))
1072 return False;
1074 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1076 if (*dcs == NULL)
1077 return False;
1079 fstrcpy((*dcs)[*num].name, dcname);
1080 (*dcs)[*num].ss = *pss;
1081 *num += 1;
1082 return True;
1085 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1086 struct sockaddr_storage *pss, uint16 port,
1087 struct sockaddr_storage **addrs, int *num)
1089 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1091 if (*addrs == NULL) {
1092 *num = 0;
1093 return False;
1096 (*addrs)[*num] = *pss;
1097 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1099 *num += 1;
1100 return True;
1103 /*******************************************************************
1104 convert an ip to a name
1105 *******************************************************************/
1107 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1108 const struct winbindd_domain *domain,
1109 struct sockaddr_storage *pss,
1110 fstring name )
1112 struct ip_service ip_list;
1113 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1114 NTSTATUS status;
1115 const char *dc_name;
1117 ip_list.ss = *pss;
1118 ip_list.port = 0;
1120 #ifdef WITH_ADS
1121 /* For active directory servers, try to get the ldap server name.
1122 None of these failures should be considered critical for now */
1124 if (lp_security() == SEC_ADS) {
1125 ADS_STRUCT *ads;
1126 ADS_STATUS ads_status;
1127 char addr[INET6_ADDRSTRLEN];
1129 print_sockaddr(addr, sizeof(addr), pss);
1131 ads = ads_init(domain->alt_name, domain->name, addr);
1132 ads->auth.flags |= ADS_AUTH_NO_BIND;
1134 ads_status = ads_connect(ads);
1135 if (ADS_ERR_OK(ads_status)) {
1136 /* We got a cldap packet. */
1137 fstrcpy(name, ads->config.ldap_server_name);
1138 namecache_store(name, 0x20, 1, &ip_list);
1140 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1142 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1143 if (ads_closest_dc(ads)) {
1144 char *sitename = sitename_fetch(ads->config.realm);
1146 /* We're going to use this KDC for this realm/domain.
1147 If we are using sites, then force the krb5 libs
1148 to use this KDC. */
1150 create_local_private_krb5_conf_for_domain(domain->alt_name,
1151 domain->name,
1152 sitename,
1153 pss,
1154 name);
1156 SAFE_FREE(sitename);
1157 } else {
1158 /* use an off site KDC */
1159 create_local_private_krb5_conf_for_domain(domain->alt_name,
1160 domain->name,
1161 NULL,
1162 pss,
1163 name);
1165 winbindd_set_locator_kdc_envs(domain);
1167 /* Ensure we contact this DC also. */
1168 saf_store( domain->name, name);
1169 saf_store( domain->alt_name, name);
1172 ads_destroy( &ads );
1173 return True;
1176 ads_destroy( &ads );
1178 #endif
1180 status = nbt_getdc(winbind_messaging_context(), pss, domain->name,
1181 &domain->sid, nt_version, mem_ctx, &nt_version,
1182 &dc_name, NULL);
1183 if (NT_STATUS_IS_OK(status)) {
1184 fstrcpy(name, dc_name);
1185 namecache_store(name, 0x20, 1, &ip_list);
1186 return True;
1189 /* try node status request */
1191 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1192 namecache_store(name, 0x20, 1, &ip_list);
1193 return True;
1195 return False;
1198 /*******************************************************************
1199 Retrieve a list of IP addresses for domain controllers.
1201 The array is sorted in the preferred connection order.
1203 @param[in] mem_ctx talloc memory context to allocate from
1204 @param[in] domain domain to retrieve DCs for
1205 @param[out] dcs array of dcs that will be returned
1206 @param[out] num_dcs number of dcs returned in the dcs array
1207 @return always true
1208 *******************************************************************/
1210 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1211 struct dc_name_ip **dcs, int *num_dcs)
1213 fstring dcname;
1214 struct sockaddr_storage ss;
1215 struct ip_service *ip_list = NULL;
1216 int iplist_size = 0;
1217 int i;
1218 bool is_our_domain;
1219 enum security_types sec = (enum security_types)lp_security();
1221 is_our_domain = strequal(domain->name, lp_workgroup());
1223 /* If not our domain, get the preferred DC, by asking our primary DC */
1224 if ( !is_our_domain
1225 && get_dc_name_via_netlogon(domain, dcname, &ss)
1226 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1227 num_dcs) )
1229 char addr[INET6_ADDRSTRLEN];
1230 print_sockaddr(addr, sizeof(addr), &ss);
1231 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1232 dcname, addr));
1233 return True;
1236 if (sec == SEC_ADS) {
1237 char *sitename = NULL;
1239 /* We need to make sure we know the local site before
1240 doing any DNS queries, as this will restrict the
1241 get_sorted_dc_list() call below to only fetching
1242 DNS records for the correct site. */
1244 /* Find any DC to get the site record.
1245 We deliberately don't care about the
1246 return here. */
1248 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1250 sitename = sitename_fetch(domain->alt_name);
1251 if (sitename) {
1253 /* Do the site-specific AD dns lookup first. */
1254 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1255 &iplist_size, True);
1257 /* Add ips to the DC array. We don't look up the name
1258 of the DC in this function, but we fill in the char*
1259 of the ip now to make the failed connection cache
1260 work */
1261 for ( i=0; i<iplist_size; i++ ) {
1262 char addr[INET6_ADDRSTRLEN];
1263 print_sockaddr(addr, sizeof(addr),
1264 &ip_list[i].ss);
1265 add_one_dc_unique(mem_ctx,
1266 domain->name,
1267 addr,
1268 &ip_list[i].ss,
1269 dcs,
1270 num_dcs);
1273 SAFE_FREE(ip_list);
1274 SAFE_FREE(sitename);
1275 iplist_size = 0;
1278 /* Now we add DCs from the main AD DNS lookup. */
1279 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1280 &iplist_size, True);
1282 for ( i=0; i<iplist_size; i++ ) {
1283 char addr[INET6_ADDRSTRLEN];
1284 print_sockaddr(addr, sizeof(addr),
1285 &ip_list[i].ss);
1286 add_one_dc_unique(mem_ctx,
1287 domain->name,
1288 addr,
1289 &ip_list[i].ss,
1290 dcs,
1291 num_dcs);
1294 SAFE_FREE(ip_list);
1295 iplist_size = 0;
1298 /* Try standard netbios queries if no ADS */
1299 if (*num_dcs == 0) {
1300 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1301 False);
1303 for ( i=0; i<iplist_size; i++ ) {
1304 char addr[INET6_ADDRSTRLEN];
1305 print_sockaddr(addr, sizeof(addr),
1306 &ip_list[i].ss);
1307 add_one_dc_unique(mem_ctx,
1308 domain->name,
1309 addr,
1310 &ip_list[i].ss,
1311 dcs,
1312 num_dcs);
1315 SAFE_FREE(ip_list);
1316 iplist_size = 0;
1319 return True;
1322 /*******************************************************************
1323 Find and make a connection to a DC in the given domain.
1325 @param[in] mem_ctx talloc memory context to allocate from
1326 @param[in] domain domain to find a dc in
1327 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1328 @param[out] pss DC Internet address and port
1329 @param[out] fd fd of the open socket connected to the newly found dc
1330 @return true when a DC connection is made, false otherwise
1331 *******************************************************************/
1333 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1334 struct winbindd_domain *domain,
1335 fstring dcname, struct sockaddr_storage *pss, int *fd)
1337 struct dc_name_ip *dcs = NULL;
1338 int num_dcs = 0;
1340 const char **dcnames = NULL;
1341 int num_dcnames = 0;
1343 struct sockaddr_storage *addrs = NULL;
1344 int num_addrs = 0;
1346 int i;
1347 size_t fd_index;
1349 NTSTATUS status;
1351 *fd = -1;
1353 again:
1354 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1355 return False;
1357 for (i=0; i<num_dcs; i++) {
1359 if (!add_string_to_array(mem_ctx, dcs[i].name,
1360 &dcnames, &num_dcnames)) {
1361 return False;
1363 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1364 &addrs, &num_addrs)) {
1365 return False;
1369 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1370 return False;
1372 if ((addrs == NULL) || (dcnames == NULL))
1373 return False;
1375 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1376 num_addrs, 0, fd, &fd_index, NULL);
1377 if (!NT_STATUS_IS_OK(status)) {
1378 for (i=0; i<num_dcs; i++) {
1379 char ab[INET6_ADDRSTRLEN];
1380 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1381 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1382 "domain %s address %s. Error was %s\n",
1383 domain->name, ab, nt_errstr(status) ));
1384 winbind_add_failed_connection_entry(domain,
1385 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1387 return False;
1390 *pss = addrs[fd_index];
1392 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1393 /* Ok, we've got a name for the DC */
1394 fstrcpy(dcname, dcnames[fd_index]);
1395 return True;
1398 /* Try to figure out the name */
1399 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1400 return True;
1403 /* We can not continue without the DC's name */
1404 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1405 NT_STATUS_UNSUCCESSFUL);
1407 /* Throw away all arrays as we're doing this again. */
1408 TALLOC_FREE(dcs);
1409 num_dcs = 0;
1411 TALLOC_FREE(dcnames);
1412 num_dcnames = 0;
1414 TALLOC_FREE(addrs);
1415 num_addrs = 0;
1417 close(*fd);
1418 *fd = -1;
1420 goto again;
1423 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1425 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1426 domain_name);
1429 static void store_current_dc_in_gencache(const char *domain_name,
1430 const char *dc_name,
1431 struct cli_state *cli)
1433 char addr[INET6_ADDRSTRLEN];
1434 char *key, *value;
1436 if (cli == NULL) {
1437 return;
1439 if (cli->fd == -1) {
1440 return;
1442 get_peer_addr(cli->fd, addr, sizeof(addr));
1444 key = current_dc_key(talloc_tos(), domain_name);
1445 if (key == NULL) {
1446 goto done;
1449 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1450 if (value == NULL) {
1451 goto done;
1454 gencache_set(key, value, 0x7fffffff);
1455 done:
1456 TALLOC_FREE(value);
1457 TALLOC_FREE(key);
1460 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1461 const char *domain_name,
1462 char **p_dc_name, char **p_dc_ip)
1464 char *key, *value, *p;
1465 bool ret = false;
1466 char *dc_name = NULL;
1467 char *dc_ip = NULL;
1469 key = current_dc_key(talloc_tos(), domain_name);
1470 if (key == NULL) {
1471 goto done;
1473 if (!gencache_get(key, &value, NULL)) {
1474 goto done;
1476 p = strchr(value, ' ');
1477 if (p == NULL) {
1478 goto done;
1480 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1481 if (dc_ip == NULL) {
1482 goto done;
1484 dc_name = talloc_strdup(mem_ctx, p+1);
1485 if (dc_name == NULL) {
1486 goto done;
1489 if (p_dc_ip != NULL) {
1490 *p_dc_ip = dc_ip;
1491 dc_ip = NULL;
1493 if (p_dc_name != NULL) {
1494 *p_dc_name = dc_name;
1495 dc_name = NULL;
1497 ret = true;
1498 done:
1499 TALLOC_FREE(dc_name);
1500 TALLOC_FREE(dc_ip);
1501 TALLOC_FREE(key);
1502 return ret;
1505 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1506 struct winbindd_cm_conn *new_conn)
1508 TALLOC_CTX *mem_ctx;
1509 NTSTATUS result;
1510 char *saf_servername = saf_fetch( domain->name );
1511 int retries;
1513 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1514 SAFE_FREE(saf_servername);
1515 set_domain_offline(domain);
1516 return NT_STATUS_NO_MEMORY;
1519 /* we have to check the server affinity cache here since
1520 later we select a DC based on response time and not preference */
1522 /* Check the negative connection cache
1523 before talking to it. It going down may have
1524 triggered the reconnection. */
1526 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1528 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1529 saf_servername, domain->name ));
1531 /* convert an ip address to a name */
1532 if (is_ipaddress( saf_servername ) ) {
1533 fstring saf_name;
1534 struct sockaddr_storage ss;
1536 if (!interpret_string_addr(&ss, saf_servername,
1537 AI_NUMERICHOST)) {
1538 return NT_STATUS_UNSUCCESSFUL;
1540 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1541 fstrcpy( domain->dcname, saf_name );
1542 } else {
1543 winbind_add_failed_connection_entry(
1544 domain, saf_servername,
1545 NT_STATUS_UNSUCCESSFUL);
1547 } else {
1548 fstrcpy( domain->dcname, saf_servername );
1551 SAFE_FREE( saf_servername );
1554 for (retries = 0; retries < 3; retries++) {
1555 int fd = -1;
1556 bool retry = False;
1558 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1560 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1561 domain->dcname, domain->name ));
1563 if (*domain->dcname
1564 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1565 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1567 NTSTATUS status;
1569 status = smbsock_connect(&domain->dcaddr, 0,
1570 NULL, -1, NULL, -1,
1571 &fd, NULL);
1572 if (!NT_STATUS_IS_OK(status)) {
1573 fd = -1;
1577 if ((fd == -1)
1578 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1580 /* This is the one place where we will
1581 set the global winbindd offline state
1582 to true, if a "WINBINDD_OFFLINE" entry
1583 is found in the winbindd cache. */
1584 set_global_winbindd_state_offline();
1585 break;
1588 new_conn->cli = NULL;
1590 result = cm_prepare_connection(domain, fd, domain->dcname,
1591 &new_conn->cli, &retry);
1593 if (!retry)
1594 break;
1597 if (NT_STATUS_IS_OK(result)) {
1599 winbindd_set_locator_kdc_envs(domain);
1601 if (domain->online == False) {
1602 /* We're changing state from offline to online. */
1603 set_global_winbindd_state_online();
1605 set_domain_online(domain);
1608 * Much as I hate global state, this seems to be the point
1609 * where we can be certain that we have a proper connection to
1610 * a DC. wbinfo --dc-info needs that information, store it in
1611 * gencache with a looong timeout. This will need revisiting
1612 * once we start to connect to multiple DCs, wbcDcInfo is
1613 * already prepared for that.
1615 store_current_dc_in_gencache(domain->name, domain->dcname,
1616 new_conn->cli);
1617 } else {
1618 /* Ensure we setup the retry handler. */
1619 set_domain_offline(domain);
1622 talloc_destroy(mem_ctx);
1623 return result;
1626 /* Close down all open pipes on a connection. */
1628 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1630 NTSTATUS result;
1632 /* We're closing down a possibly dead
1633 connection. Don't have impossibly long (10s) timeouts. */
1635 if (conn->cli) {
1636 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1639 if (conn->samr_pipe != NULL) {
1640 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1641 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1642 talloc_tos(),
1643 &conn->sam_connect_handle,
1644 &result);
1646 TALLOC_FREE(conn->samr_pipe);
1647 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1648 if (conn->cli) {
1649 cli_set_timeout(conn->cli, 500);
1653 if (conn->lsa_pipe != NULL) {
1654 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1655 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1656 talloc_tos(),
1657 &conn->lsa_policy,
1658 &result);
1660 TALLOC_FREE(conn->lsa_pipe);
1661 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1662 if (conn->cli) {
1663 cli_set_timeout(conn->cli, 500);
1667 if (conn->lsa_pipe_tcp != NULL) {
1668 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1669 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1670 talloc_tos(),
1671 &conn->lsa_policy,
1672 &result);
1674 TALLOC_FREE(conn->lsa_pipe_tcp);
1675 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1676 if (conn->cli) {
1677 cli_set_timeout(conn->cli, 500);
1681 if (conn->netlogon_pipe != NULL) {
1682 TALLOC_FREE(conn->netlogon_pipe);
1683 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1684 if (conn->cli) {
1685 cli_set_timeout(conn->cli, 500);
1689 if (conn->cli) {
1690 cli_shutdown(conn->cli);
1693 conn->cli = NULL;
1696 void close_conns_after_fork(void)
1698 struct winbindd_domain *domain;
1700 for (domain = domain_list(); domain; domain = domain->next) {
1701 struct cli_state *cli = domain->conn.cli;
1704 * first close the low level SMB TCP connection
1705 * so that we don't generate any SMBclose
1706 * requests in invalidate_cm_connection()
1708 if (cli && cli->fd != -1) {
1709 close(domain->conn.cli->fd);
1710 domain->conn.cli->fd = -1;
1713 invalidate_cm_connection(&domain->conn);
1717 static bool connection_ok(struct winbindd_domain *domain)
1719 bool ok;
1721 ok = cli_state_is_connected(domain->conn.cli);
1722 if (!ok) {
1723 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1724 domain->dcname, domain->name));
1725 return False;
1728 if (domain->online == False) {
1729 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1730 return False;
1733 return True;
1736 /* Initialize a new connection up to the RPC BIND.
1737 Bypass online status check so always does network calls. */
1739 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1741 NTSTATUS result;
1743 /* Internal connections never use the network. */
1744 if (domain->internal) {
1745 domain->initialized = True;
1746 return NT_STATUS_OK;
1749 if (!winbindd_can_contact_domain(domain)) {
1750 invalidate_cm_connection(&domain->conn);
1751 domain->initialized = True;
1752 return NT_STATUS_OK;
1755 if (connection_ok(domain)) {
1756 if (!domain->initialized) {
1757 set_dc_type_and_flags(domain);
1759 return NT_STATUS_OK;
1762 invalidate_cm_connection(&domain->conn);
1764 result = cm_open_connection(domain, &domain->conn);
1766 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1767 set_dc_type_and_flags(domain);
1770 return result;
1773 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1775 if (domain->internal) {
1776 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1779 if (domain->initialized && !domain->online) {
1780 /* We check for online status elsewhere. */
1781 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1784 return init_dc_connection_network(domain);
1787 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1789 NTSTATUS status;
1791 status = init_dc_connection(domain);
1792 if (!NT_STATUS_IS_OK(status)) {
1793 return status;
1796 if (!domain->internal && domain->conn.cli == NULL) {
1797 /* happens for trusted domains without inbound trust */
1798 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1801 return NT_STATUS_OK;
1804 /******************************************************************************
1805 Set the trust flags (direction and forest location) for a domain
1806 ******************************************************************************/
1808 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1810 struct winbindd_domain *our_domain;
1811 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1812 WERROR werr;
1813 struct netr_DomainTrustList trusts;
1814 int i;
1815 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1816 NETR_TRUST_FLAG_OUTBOUND |
1817 NETR_TRUST_FLAG_INBOUND);
1818 struct rpc_pipe_client *cli;
1819 TALLOC_CTX *mem_ctx = NULL;
1820 struct dcerpc_binding_handle *b;
1822 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1824 /* Our primary domain doesn't need to worry about trust flags.
1825 Force it to go through the network setup */
1826 if ( domain->primary ) {
1827 return False;
1830 our_domain = find_our_domain();
1832 if ( !connection_ok(our_domain) ) {
1833 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1834 return False;
1837 /* This won't work unless our domain is AD */
1839 if ( !our_domain->active_directory ) {
1840 return False;
1843 /* Use DsEnumerateDomainTrusts to get us the trust direction
1844 and type */
1846 result = cm_connect_netlogon(our_domain, &cli);
1848 if (!NT_STATUS_IS_OK(result)) {
1849 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1850 "a connection to %s for PIPE_NETLOGON (%s)\n",
1851 domain->name, nt_errstr(result)));
1852 return False;
1855 b = cli->binding_handle;
1857 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1858 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1859 return False;
1862 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1863 cli->desthost,
1864 flags,
1865 &trusts,
1866 &werr);
1867 if (!NT_STATUS_IS_OK(result)) {
1868 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1869 "failed to query trusted domain list: %s\n",
1870 nt_errstr(result)));
1871 talloc_destroy(mem_ctx);
1872 return false;
1874 if (!W_ERROR_IS_OK(werr)) {
1875 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1876 "failed to query trusted domain list: %s\n",
1877 win_errstr(werr)));
1878 talloc_destroy(mem_ctx);
1879 return false;
1882 /* Now find the domain name and get the flags */
1884 for ( i=0; i<trusts.count; i++ ) {
1885 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1886 domain->domain_flags = trusts.array[i].trust_flags;
1887 domain->domain_type = trusts.array[i].trust_type;
1888 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1890 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1891 domain->active_directory = True;
1893 /* This flag is only set if the domain is *our*
1894 primary domain and the primary domain is in
1895 native mode */
1897 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1899 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1900 "native mode.\n", domain->name,
1901 domain->native_mode ? "" : "NOT "));
1903 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1904 "running active directory.\n", domain->name,
1905 domain->active_directory ? "" : "NOT "));
1908 domain->initialized = True;
1910 break;
1914 talloc_destroy( mem_ctx );
1916 return domain->initialized;
1919 /******************************************************************************
1920 We can 'sense' certain things about the DC by it's replies to certain
1921 questions.
1923 This tells us if this particular remote server is Active Directory, and if it
1924 is native mode.
1925 ******************************************************************************/
1927 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1929 NTSTATUS status, result;
1930 WERROR werr;
1931 TALLOC_CTX *mem_ctx = NULL;
1932 struct rpc_pipe_client *cli = NULL;
1933 struct policy_handle pol;
1934 union dssetup_DsRoleInfo info;
1935 union lsa_PolicyInformation *lsa_info = NULL;
1937 if (!connection_ok(domain)) {
1938 return;
1941 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1942 domain->name);
1943 if (!mem_ctx) {
1944 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1945 return;
1948 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1950 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
1951 &ndr_table_dssetup.syntax_id,
1952 &cli);
1954 if (!NT_STATUS_IS_OK(status)) {
1955 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1956 "PI_DSSETUP on domain %s: (%s)\n",
1957 domain->name, nt_errstr(status)));
1959 /* if this is just a non-AD domain we need to continue
1960 * identifying so that we can in the end return with
1961 * domain->initialized = True - gd */
1963 goto no_dssetup;
1966 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
1967 DS_ROLE_BASIC_INFORMATION,
1968 &info,
1969 &werr);
1970 TALLOC_FREE(cli);
1972 if (NT_STATUS_IS_OK(status)) {
1973 result = werror_to_ntstatus(werr);
1975 if (!NT_STATUS_IS_OK(status)) {
1976 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1977 "on domain %s failed: (%s)\n",
1978 domain->name, nt_errstr(status)));
1980 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1981 * every opcode on the DSSETUP pipe, continue with
1982 * no_dssetup mode here as well to get domain->initialized
1983 * set - gd */
1985 if (NT_STATUS_V(status) == DCERPC_FAULT_OP_RNG_ERROR) {
1986 goto no_dssetup;
1989 TALLOC_FREE(mem_ctx);
1990 return;
1993 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1994 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1995 domain->native_mode = True;
1996 } else {
1997 domain->native_mode = False;
2000 no_dssetup:
2001 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2002 &ndr_table_lsarpc.syntax_id, &cli);
2004 if (!NT_STATUS_IS_OK(status)) {
2005 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2006 "PI_LSARPC on domain %s: (%s)\n",
2007 domain->name, nt_errstr(status)));
2008 TALLOC_FREE(cli);
2009 TALLOC_FREE(mem_ctx);
2010 return;
2013 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2014 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2016 if (NT_STATUS_IS_OK(status)) {
2017 /* This particular query is exactly what Win2k clients use
2018 to determine that the DC is active directory */
2019 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2020 &pol,
2021 LSA_POLICY_INFO_DNS,
2022 &lsa_info,
2023 &result);
2026 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2027 domain->active_directory = True;
2029 if (lsa_info->dns.name.string) {
2030 fstrcpy(domain->name, lsa_info->dns.name.string);
2033 if (lsa_info->dns.dns_domain.string) {
2034 fstrcpy(domain->alt_name,
2035 lsa_info->dns.dns_domain.string);
2038 /* See if we can set some domain trust flags about
2039 ourself */
2041 if (lsa_info->dns.dns_forest.string) {
2042 fstrcpy(domain->forest_name,
2043 lsa_info->dns.dns_forest.string);
2045 if (strequal(domain->forest_name, domain->alt_name)) {
2046 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2050 if (lsa_info->dns.sid) {
2051 sid_copy(&domain->sid, lsa_info->dns.sid);
2053 } else {
2054 domain->active_directory = False;
2056 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2057 SEC_FLAG_MAXIMUM_ALLOWED,
2058 &pol);
2060 if (!NT_STATUS_IS_OK(status)) {
2061 goto done;
2064 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2065 &pol,
2066 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2067 &lsa_info,
2068 &result);
2069 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2071 if (lsa_info->account_domain.name.string) {
2072 fstrcpy(domain->name,
2073 lsa_info->account_domain.name.string);
2076 if (lsa_info->account_domain.sid) {
2077 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2081 done:
2083 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2084 domain->name, domain->native_mode ? "" : "NOT "));
2086 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2087 domain->name, domain->active_directory ? "" : "NOT "));
2089 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2090 domain->can_do_validation6 = domain->active_directory;
2092 TALLOC_FREE(cli);
2094 TALLOC_FREE(mem_ctx);
2096 domain->initialized = True;
2099 /**********************************************************************
2100 Set the domain_flags (trust attributes, domain operating modes, etc...
2101 ***********************************************************************/
2103 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2105 /* we always have to contact our primary domain */
2107 if ( domain->primary ) {
2108 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2109 "primary domain\n"));
2110 set_dc_type_and_flags_connect( domain );
2111 return;
2114 /* Use our DC to get the information if possible */
2116 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2117 /* Otherwise, fallback to contacting the
2118 domain directly */
2119 set_dc_type_and_flags_connect( domain );
2122 return;
2127 /**********************************************************************
2128 ***********************************************************************/
2130 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2131 struct netlogon_creds_CredentialState **ppdc)
2133 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2134 struct rpc_pipe_client *netlogon_pipe;
2136 if (lp_client_schannel() == False) {
2137 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2140 result = cm_connect_netlogon(domain, &netlogon_pipe);
2141 if (!NT_STATUS_IS_OK(result)) {
2142 return result;
2145 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2146 netlogon pipe. */
2148 if (!domain->conn.netlogon_pipe->dc) {
2149 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2152 *ppdc = domain->conn.netlogon_pipe->dc;
2153 return NT_STATUS_OK;
2156 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2157 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2159 struct winbindd_cm_conn *conn;
2160 NTSTATUS status, result;
2161 struct netlogon_creds_CredentialState *p_creds;
2162 char *machine_password = NULL;
2163 char *machine_account = NULL;
2164 char *domain_name = NULL;
2166 if (sid_check_is_domain(&domain->sid)) {
2167 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2170 status = init_dc_connection_rpc(domain);
2171 if (!NT_STATUS_IS_OK(status)) {
2172 return status;
2175 conn = &domain->conn;
2177 if (rpccli_is_connected(conn->samr_pipe)) {
2178 goto done;
2181 TALLOC_FREE(conn->samr_pipe);
2184 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2185 * sign and sealed pipe using the machine account password by
2186 * preference. If we can't - try schannel, if that fails, try
2187 * anonymous.
2190 if ((conn->cli->user_name[0] == '\0') ||
2191 (conn->cli->domain[0] == '\0') ||
2192 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2194 status = get_trust_creds(domain, &machine_password,
2195 &machine_account, NULL);
2196 if (!NT_STATUS_IS_OK(status)) {
2197 DEBUG(10, ("cm_connect_sam: No no user available for "
2198 "domain %s, trying schannel\n", conn->cli->domain));
2199 goto schannel;
2201 domain_name = domain->name;
2202 } else {
2203 machine_password = SMB_STRDUP(conn->cli->password);
2204 machine_account = SMB_STRDUP(conn->cli->user_name);
2205 domain_name = conn->cli->domain;
2208 if (!machine_password || !machine_account) {
2209 status = NT_STATUS_NO_MEMORY;
2210 goto done;
2213 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2214 authenticated SAMR pipe with sign & seal. */
2215 status = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2216 &ndr_table_samr.syntax_id,
2217 NCACN_NP,
2218 DCERPC_AUTH_LEVEL_PRIVACY,
2219 domain_name,
2220 machine_account,
2221 machine_password,
2222 &conn->samr_pipe);
2224 if (!NT_STATUS_IS_OK(status)) {
2225 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2226 "pipe for domain %s using NTLMSSP "
2227 "authenticated pipe: user %s\\%s. Error was "
2228 "%s\n", domain->name, domain_name,
2229 machine_account, nt_errstr(status)));
2230 goto schannel;
2233 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2234 "domain %s using NTLMSSP authenticated "
2235 "pipe: user %s\\%s\n", domain->name,
2236 domain_name, machine_account));
2238 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2239 conn->samr_pipe->desthost,
2240 SEC_FLAG_MAXIMUM_ALLOWED,
2241 &conn->sam_connect_handle,
2242 &result);
2243 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2244 goto open_domain;
2246 if (NT_STATUS_IS_OK(status)) {
2247 status = result;
2250 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2251 "failed for domain %s, error was %s. Trying schannel\n",
2252 domain->name, nt_errstr(status) ));
2253 TALLOC_FREE(conn->samr_pipe);
2255 schannel:
2257 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2259 status = cm_get_schannel_creds(domain, &p_creds);
2260 if (!NT_STATUS_IS_OK(status)) {
2261 /* If this call fails - conn->cli can now be NULL ! */
2262 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2263 "for domain %s (error %s), trying anon\n",
2264 domain->name,
2265 nt_errstr(status) ));
2266 goto anonymous;
2268 status = cli_rpc_pipe_open_schannel_with_key
2269 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2270 DCERPC_AUTH_LEVEL_PRIVACY,
2271 domain->name, &p_creds, &conn->samr_pipe);
2273 if (!NT_STATUS_IS_OK(status)) {
2274 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2275 "domain %s using schannel. Error was %s\n",
2276 domain->name, nt_errstr(status) ));
2277 goto anonymous;
2279 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2280 "schannel.\n", domain->name ));
2282 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2283 conn->samr_pipe->desthost,
2284 SEC_FLAG_MAXIMUM_ALLOWED,
2285 &conn->sam_connect_handle,
2286 &result);
2287 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2288 goto open_domain;
2290 if (NT_STATUS_IS_OK(status)) {
2291 status = result;
2293 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2294 "for domain %s, error was %s. Trying anonymous\n",
2295 domain->name, nt_errstr(status) ));
2296 TALLOC_FREE(conn->samr_pipe);
2298 anonymous:
2300 /* Finally fall back to anonymous. */
2301 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2302 &conn->samr_pipe);
2304 if (!NT_STATUS_IS_OK(status)) {
2305 goto done;
2308 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2309 conn->samr_pipe->desthost,
2310 SEC_FLAG_MAXIMUM_ALLOWED,
2311 &conn->sam_connect_handle,
2312 &result);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2315 "for domain %s Error was %s\n",
2316 domain->name, nt_errstr(status) ));
2317 goto done;
2319 if (!NT_STATUS_IS_OK(result)) {
2320 status = result;
2321 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2322 "for domain %s Error was %s\n",
2323 domain->name, nt_errstr(result)));
2324 goto done;
2327 open_domain:
2328 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2329 mem_ctx,
2330 &conn->sam_connect_handle,
2331 SEC_FLAG_MAXIMUM_ALLOWED,
2332 &domain->sid,
2333 &conn->sam_domain_handle,
2334 &result);
2335 if (!NT_STATUS_IS_OK(status)) {
2336 goto done;
2339 status = result;
2340 done:
2342 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2344 * if we got access denied, we might just have no access rights
2345 * to talk to the remote samr server server (e.g. when we are a
2346 * PDC and we are connecting a w2k8 pdc via an interdomain
2347 * trust). In that case do not invalidate the whole connection
2348 * stack
2350 TALLOC_FREE(conn->samr_pipe);
2351 ZERO_STRUCT(conn->sam_domain_handle);
2352 return status;
2353 } else if (!NT_STATUS_IS_OK(status)) {
2354 invalidate_cm_connection(conn);
2355 return status;
2358 *cli = conn->samr_pipe;
2359 *sam_handle = conn->sam_domain_handle;
2360 SAFE_FREE(machine_password);
2361 SAFE_FREE(machine_account);
2362 return status;
2365 /**********************************************************************
2366 open an schanneld ncacn_ip_tcp connection to LSA
2367 ***********************************************************************/
2369 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2370 TALLOC_CTX *mem_ctx,
2371 struct rpc_pipe_client **cli)
2373 struct winbindd_cm_conn *conn;
2374 struct netlogon_creds_CredentialState *creds;
2375 NTSTATUS status;
2377 DEBUG(10,("cm_connect_lsa_tcp\n"));
2379 status = init_dc_connection_rpc(domain);
2380 if (!NT_STATUS_IS_OK(status)) {
2381 return status;
2384 conn = &domain->conn;
2386 if (conn->lsa_pipe_tcp &&
2387 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2388 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2389 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2390 goto done;
2393 TALLOC_FREE(conn->lsa_pipe_tcp);
2395 status = cm_get_schannel_creds(domain, &creds);
2396 if (!NT_STATUS_IS_OK(status)) {
2397 goto done;
2400 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2401 &ndr_table_lsarpc.syntax_id,
2402 NCACN_IP_TCP,
2403 DCERPC_AUTH_LEVEL_PRIVACY,
2404 domain->name,
2405 &creds,
2406 &conn->lsa_pipe_tcp);
2407 if (!NT_STATUS_IS_OK(status)) {
2408 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2409 nt_errstr(status)));
2410 goto done;
2413 done:
2414 if (!NT_STATUS_IS_OK(status)) {
2415 TALLOC_FREE(conn->lsa_pipe_tcp);
2416 return status;
2419 *cli = conn->lsa_pipe_tcp;
2421 return status;
2424 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2425 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2427 struct winbindd_cm_conn *conn;
2428 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2429 struct netlogon_creds_CredentialState *p_creds;
2431 result = init_dc_connection_rpc(domain);
2432 if (!NT_STATUS_IS_OK(result))
2433 return result;
2435 conn = &domain->conn;
2437 if (rpccli_is_connected(conn->lsa_pipe)) {
2438 goto done;
2441 TALLOC_FREE(conn->lsa_pipe);
2443 if ((conn->cli->user_name[0] == '\0') ||
2444 (conn->cli->domain[0] == '\0') ||
2445 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2446 DEBUG(10, ("cm_connect_lsa: No no user available for "
2447 "domain %s, trying schannel\n", conn->cli->domain));
2448 goto schannel;
2451 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2452 * authenticated LSA pipe with sign & seal. */
2453 result = cli_rpc_pipe_open_spnego_ntlmssp
2454 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2455 DCERPC_AUTH_LEVEL_PRIVACY,
2456 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2457 &conn->lsa_pipe);
2459 if (!NT_STATUS_IS_OK(result)) {
2460 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2461 "domain %s using NTLMSSP authenticated pipe: user "
2462 "%s\\%s. Error was %s. Trying schannel.\n",
2463 domain->name, conn->cli->domain,
2464 conn->cli->user_name, nt_errstr(result)));
2465 goto schannel;
2468 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2469 "NTLMSSP authenticated pipe: user %s\\%s\n",
2470 domain->name, conn->cli->domain, conn->cli->user_name ));
2472 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2473 SEC_FLAG_MAXIMUM_ALLOWED,
2474 &conn->lsa_policy);
2475 if (NT_STATUS_IS_OK(result)) {
2476 goto done;
2479 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2480 "schannel\n"));
2482 TALLOC_FREE(conn->lsa_pipe);
2484 schannel:
2486 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2488 result = cm_get_schannel_creds(domain, &p_creds);
2489 if (!NT_STATUS_IS_OK(result)) {
2490 /* If this call fails - conn->cli can now be NULL ! */
2491 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2492 "for domain %s (error %s), trying anon\n",
2493 domain->name,
2494 nt_errstr(result) ));
2495 goto anonymous;
2497 result = cli_rpc_pipe_open_schannel_with_key
2498 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2499 DCERPC_AUTH_LEVEL_PRIVACY,
2500 domain->name, &p_creds, &conn->lsa_pipe);
2502 if (!NT_STATUS_IS_OK(result)) {
2503 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2504 "domain %s using schannel. Error was %s\n",
2505 domain->name, nt_errstr(result) ));
2506 goto anonymous;
2508 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2509 "schannel.\n", domain->name ));
2511 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2512 SEC_FLAG_MAXIMUM_ALLOWED,
2513 &conn->lsa_policy);
2514 if (NT_STATUS_IS_OK(result)) {
2515 goto done;
2518 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2519 "anonymous\n"));
2521 TALLOC_FREE(conn->lsa_pipe);
2523 anonymous:
2525 result = cli_rpc_pipe_open_noauth(conn->cli,
2526 &ndr_table_lsarpc.syntax_id,
2527 &conn->lsa_pipe);
2528 if (!NT_STATUS_IS_OK(result)) {
2529 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2530 goto done;
2533 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2534 SEC_FLAG_MAXIMUM_ALLOWED,
2535 &conn->lsa_policy);
2536 done:
2537 if (!NT_STATUS_IS_OK(result)) {
2538 invalidate_cm_connection(conn);
2539 return result;
2542 *cli = conn->lsa_pipe;
2543 *lsa_policy = conn->lsa_policy;
2544 return result;
2547 /****************************************************************************
2548 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2549 session key stored in conn->netlogon_pipe->dc->sess_key.
2550 ****************************************************************************/
2552 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2553 struct rpc_pipe_client **cli)
2555 struct winbindd_cm_conn *conn;
2556 NTSTATUS result;
2558 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2559 uint8 mach_pwd[16];
2560 enum netr_SchannelType sec_chan_type;
2561 const char *account_name;
2562 struct rpc_pipe_client *netlogon_pipe = NULL;
2564 *cli = NULL;
2566 result = init_dc_connection_rpc(domain);
2567 if (!NT_STATUS_IS_OK(result)) {
2568 return result;
2571 conn = &domain->conn;
2573 if (rpccli_is_connected(conn->netlogon_pipe)) {
2574 *cli = conn->netlogon_pipe;
2575 return NT_STATUS_OK;
2578 TALLOC_FREE(conn->netlogon_pipe);
2580 result = cli_rpc_pipe_open_noauth(conn->cli,
2581 &ndr_table_netlogon.syntax_id,
2582 &netlogon_pipe);
2583 if (!NT_STATUS_IS_OK(result)) {
2584 return result;
2587 if ((!IS_DC) && (!domain->primary)) {
2588 /* Clear the schannel request bit and drop down */
2589 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2590 goto no_schannel;
2593 if (lp_client_schannel() != False) {
2594 neg_flags |= NETLOGON_NEG_SCHANNEL;
2597 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2598 &sec_chan_type))
2600 TALLOC_FREE(netlogon_pipe);
2601 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2604 result = rpccli_netlogon_setup_creds(
2605 netlogon_pipe,
2606 domain->dcname, /* server name. */
2607 domain->name, /* domain name */
2608 global_myname(), /* client name */
2609 account_name, /* machine account */
2610 mach_pwd, /* machine password */
2611 sec_chan_type, /* from get_trust_pw */
2612 &neg_flags);
2614 if (!NT_STATUS_IS_OK(result)) {
2615 TALLOC_FREE(netlogon_pipe);
2616 return result;
2619 if ((lp_client_schannel() == True) &&
2620 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2621 DEBUG(3, ("Server did not offer schannel\n"));
2622 TALLOC_FREE(netlogon_pipe);
2623 return NT_STATUS_ACCESS_DENIED;
2626 no_schannel:
2627 if ((lp_client_schannel() == False) ||
2628 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2630 * NetSamLogonEx only works for schannel
2632 domain->can_do_samlogon_ex = False;
2634 /* We're done - just keep the existing connection to NETLOGON
2635 * open */
2636 conn->netlogon_pipe = netlogon_pipe;
2637 *cli = conn->netlogon_pipe;
2638 return NT_STATUS_OK;
2641 /* Using the credentials from the first pipe, open a signed and sealed
2642 second netlogon pipe. The session key is stored in the schannel
2643 part of the new pipe auth struct.
2646 result = cli_rpc_pipe_open_schannel_with_key(
2647 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2648 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2649 &conn->netlogon_pipe);
2651 /* We can now close the initial netlogon pipe. */
2652 TALLOC_FREE(netlogon_pipe);
2654 if (!NT_STATUS_IS_OK(result)) {
2655 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2656 "was %s\n", nt_errstr(result)));
2658 invalidate_cm_connection(conn);
2659 return result;
2663 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2664 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2665 * supported). We used to only try SamLogonEx for AD, but
2666 * Samba DCs can also do it. And because we don't distinguish
2667 * between Samba and NT4, always try it once.
2669 domain->can_do_samlogon_ex = true;
2671 *cli = conn->netlogon_pipe;
2672 return NT_STATUS_OK;
2675 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2676 void *private_data,
2677 uint32_t msg_type,
2678 struct server_id server_id,
2679 DATA_BLOB *data)
2681 struct winbindd_domain *domain;
2683 if ((data == NULL)
2684 || (data->data == NULL)
2685 || (data->length == 0)
2686 || (data->data[data->length-1] != '\0')
2687 || !is_ipaddress((char *)data->data)) {
2688 DEBUG(1, ("invalid msg_ip_dropped message\n"));
2689 return;
2691 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2692 char sockaddr[INET6_ADDRSTRLEN];
2693 if (domain->conn.cli == NULL) {
2694 continue;
2696 if (domain->conn.cli->fd == -1) {
2697 continue;
2699 client_socket_addr(domain->conn.cli->fd, sockaddr,
2700 sizeof(sockaddr));
2701 if (strequal(sockaddr, (char *)data->data)) {
2702 close(domain->conn.cli->fd);
2703 domain->conn.cli->fd = -1;