s3-passdb: use passdb headers where needed.
[Samba.git] / source3 / winbindd / winbindd_cm.c
blobbb333b39ee3d0280ba3df4f2cb54c4c3c83f143f
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"
77 #include "passdb.h"
79 #undef DBGC_CLASS
80 #define DBGC_CLASS DBGC_WINBIND
82 struct dc_name_ip {
83 fstring name;
84 struct sockaddr_storage ss;
87 extern struct winbindd_methods reconnect_methods;
88 extern bool override_logfile;
90 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
91 static void set_dc_type_and_flags( struct winbindd_domain *domain );
92 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
93 struct dc_name_ip **dcs, int *num_dcs);
95 /****************************************************************
96 Child failed to find DC's. Reschedule check.
97 ****************************************************************/
99 static void msg_failed_to_go_online(struct messaging_context *msg,
100 void *private_data,
101 uint32_t msg_type,
102 struct server_id server_id,
103 DATA_BLOB *data)
105 struct winbindd_domain *domain;
106 const char *domainname = (const char *)data->data;
108 if (data->data == NULL || data->length == 0) {
109 return;
112 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
114 for (domain = domain_list(); domain; domain = domain->next) {
115 if (domain->internal) {
116 continue;
119 if (strequal(domain->name, domainname)) {
120 if (domain->online) {
121 /* We're already online, ignore. */
122 DEBUG(5,("msg_fail_to_go_online: domain %s "
123 "already online.\n", domainname));
124 continue;
127 /* Reschedule the online check. */
128 set_domain_offline(domain);
129 break;
134 /****************************************************************
135 Actually cause a reconnect from a message.
136 ****************************************************************/
138 static void msg_try_to_go_online(struct messaging_context *msg,
139 void *private_data,
140 uint32_t msg_type,
141 struct server_id server_id,
142 DATA_BLOB *data)
144 struct winbindd_domain *domain;
145 const char *domainname = (const char *)data->data;
147 if (data->data == NULL || data->length == 0) {
148 return;
151 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
153 for (domain = domain_list(); domain; domain = domain->next) {
154 if (domain->internal) {
155 continue;
158 if (strequal(domain->name, domainname)) {
160 if (domain->online) {
161 /* We're already online, ignore. */
162 DEBUG(5,("msg_try_to_go_online: domain %s "
163 "already online.\n", domainname));
164 continue;
167 /* This call takes care of setting the online
168 flag to true if we connected, or re-adding
169 the offline handler if false. Bypasses online
170 check so always does network calls. */
172 init_dc_connection_network(domain);
173 break;
178 /****************************************************************
179 Fork a child to try and contact a DC. Do this as contacting a
180 DC requires blocking lookups and we don't want to block our
181 parent.
182 ****************************************************************/
184 static bool fork_child_dc_connect(struct winbindd_domain *domain)
186 struct dc_name_ip *dcs = NULL;
187 int num_dcs = 0;
188 TALLOC_CTX *mem_ctx = NULL;
189 pid_t parent_pid = sys_getpid();
190 char *lfile = NULL;
192 if (domain->dc_probe_pid != (pid_t)-1) {
194 * We might already have a DC probe
195 * child working, check.
197 if (process_exists_by_pid(domain->dc_probe_pid)) {
198 DEBUG(10,("fork_child_dc_connect: pid %u already "
199 "checking for DC's.\n",
200 (unsigned int)domain->dc_probe_pid));
201 return true;
203 domain->dc_probe_pid = (pid_t)-1;
206 domain->dc_probe_pid = sys_fork();
208 if (domain->dc_probe_pid == (pid_t)-1) {
209 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
210 return False;
213 if (domain->dc_probe_pid != (pid_t)0) {
214 /* Parent */
215 messaging_register(winbind_messaging_context(), NULL,
216 MSG_WINBIND_TRY_TO_GO_ONLINE,
217 msg_try_to_go_online);
218 messaging_register(winbind_messaging_context(), NULL,
219 MSG_WINBIND_FAILED_TO_GO_ONLINE,
220 msg_failed_to_go_online);
221 return True;
224 /* Child. */
226 /* Leave messages blocked - we will never process one. */
228 if (!override_logfile) {
229 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
230 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
231 _exit(1);
235 if (!winbindd_reinit_after_fork(lfile)) {
236 messaging_send_buf(winbind_messaging_context(),
237 pid_to_procid(parent_pid),
238 MSG_WINBIND_FAILED_TO_GO_ONLINE,
239 (uint8 *)domain->name,
240 strlen(domain->name)+1);
241 _exit(1);
243 SAFE_FREE(lfile);
245 mem_ctx = talloc_init("fork_child_dc_connect");
246 if (!mem_ctx) {
247 DEBUG(0,("talloc_init failed.\n"));
248 messaging_send_buf(winbind_messaging_context(),
249 pid_to_procid(parent_pid),
250 MSG_WINBIND_FAILED_TO_GO_ONLINE,
251 (uint8 *)domain->name,
252 strlen(domain->name)+1);
253 _exit(1);
256 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
257 /* Still offline ? Can't find DC's. */
258 messaging_send_buf(winbind_messaging_context(),
259 pid_to_procid(parent_pid),
260 MSG_WINBIND_FAILED_TO_GO_ONLINE,
261 (uint8 *)domain->name,
262 strlen(domain->name)+1);
263 _exit(0);
266 /* We got a DC. Send a message to our parent to get it to
267 try and do the same. */
269 messaging_send_buf(winbind_messaging_context(),
270 pid_to_procid(parent_pid),
271 MSG_WINBIND_TRY_TO_GO_ONLINE,
272 (uint8 *)domain->name,
273 strlen(domain->name)+1);
274 _exit(0);
277 /****************************************************************
278 Handler triggered if we're offline to try and detect a DC.
279 ****************************************************************/
281 static void check_domain_online_handler(struct event_context *ctx,
282 struct timed_event *te,
283 struct timeval now,
284 void *private_data)
286 struct winbindd_domain *domain =
287 (struct winbindd_domain *)private_data;
289 DEBUG(10,("check_domain_online_handler: called for domain "
290 "%s (online = %s)\n", domain->name,
291 domain->online ? "True" : "False" ));
293 TALLOC_FREE(domain->check_online_event);
295 /* Are we still in "startup" mode ? */
297 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
298 /* No longer in "startup" mode. */
299 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
300 domain->name ));
301 domain->startup = False;
304 /* We've been told to stay offline, so stay
305 that way. */
307 if (get_global_winbindd_state_offline()) {
308 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
309 domain->name ));
310 return;
313 /* Fork a child to test if it can contact a DC.
314 If it can then send ourselves a message to
315 cause a reconnect. */
317 fork_child_dc_connect(domain);
320 /****************************************************************
321 If we're still offline setup the timeout check.
322 ****************************************************************/
324 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
326 int wbr = lp_winbind_reconnect_delay();
328 if (domain->startup) {
329 domain->check_online_timeout = 10;
330 } else if (domain->check_online_timeout < wbr) {
331 domain->check_online_timeout = wbr;
335 /****************************************************************
336 Set domain offline and also add handler to put us back online
337 if we detect a DC.
338 ****************************************************************/
340 void set_domain_offline(struct winbindd_domain *domain)
342 DEBUG(10,("set_domain_offline: called for domain %s\n",
343 domain->name ));
345 TALLOC_FREE(domain->check_online_event);
347 if (domain->internal) {
348 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
349 domain->name ));
350 return;
353 domain->online = False;
355 /* Offline domains are always initialized. They're
356 re-initialized when they go back online. */
358 domain->initialized = True;
360 /* We only add the timeout handler that checks and
361 allows us to go back online when we've not
362 been told to remain offline. */
364 if (get_global_winbindd_state_offline()) {
365 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
366 domain->name ));
367 return;
370 /* If we're in startup mode, check again in 10 seconds, not in
371 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
373 calc_new_online_timeout_check(domain);
375 domain->check_online_event = event_add_timed(winbind_event_context(),
376 NULL,
377 timeval_current_ofs(domain->check_online_timeout,0),
378 check_domain_online_handler,
379 domain);
381 /* The above *has* to succeed for winbindd to work. */
382 if (!domain->check_online_event) {
383 smb_panic("set_domain_offline: failed to add online handler");
386 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
387 domain->name ));
389 /* Send an offline message to the idmap child when our
390 primary domain goes offline */
392 if ( domain->primary ) {
393 struct winbindd_child *idmap = idmap_child();
395 if ( idmap->pid != 0 ) {
396 messaging_send_buf(winbind_messaging_context(),
397 pid_to_procid(idmap->pid),
398 MSG_WINBIND_OFFLINE,
399 (uint8 *)domain->name,
400 strlen(domain->name)+1);
404 return;
407 /****************************************************************
408 Set domain online - if allowed.
409 ****************************************************************/
411 static void set_domain_online(struct winbindd_domain *domain)
413 DEBUG(10,("set_domain_online: called for domain %s\n",
414 domain->name ));
416 if (domain->internal) {
417 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
418 domain->name ));
419 return;
422 if (get_global_winbindd_state_offline()) {
423 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
424 domain->name ));
425 return;
428 winbindd_set_locator_kdc_envs(domain);
430 /* If we are waiting to get a krb5 ticket, trigger immediately. */
431 ccache_regain_all_now();
433 /* Ok, we're out of any startup mode now... */
434 domain->startup = False;
436 if (domain->online == False) {
437 /* We were offline - now we're online. We default to
438 using the MS-RPC backend if we started offline,
439 and if we're going online for the first time we
440 should really re-initialize the backends and the
441 checks to see if we're talking to an AD or NT domain.
444 domain->initialized = False;
446 /* 'reconnect_methods' is the MS-RPC backend. */
447 if (domain->backend == &reconnect_methods) {
448 domain->backend = NULL;
452 /* Ensure we have no online timeout checks. */
453 domain->check_online_timeout = 0;
454 TALLOC_FREE(domain->check_online_event);
456 /* Ensure we ignore any pending child messages. */
457 messaging_deregister(winbind_messaging_context(),
458 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
459 messaging_deregister(winbind_messaging_context(),
460 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
462 domain->online = True;
464 /* Send an online message to the idmap child when our
465 primary domain comes online */
467 if ( domain->primary ) {
468 struct winbindd_child *idmap = idmap_child();
470 if ( idmap->pid != 0 ) {
471 messaging_send_buf(winbind_messaging_context(),
472 pid_to_procid(idmap->pid),
473 MSG_WINBIND_ONLINE,
474 (uint8 *)domain->name,
475 strlen(domain->name)+1);
479 return;
482 /****************************************************************
483 Requested to set a domain online.
484 ****************************************************************/
486 void set_domain_online_request(struct winbindd_domain *domain)
488 struct timeval tev;
490 DEBUG(10,("set_domain_online_request: called for domain %s\n",
491 domain->name ));
493 if (get_global_winbindd_state_offline()) {
494 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
495 domain->name ));
496 return;
499 if (domain->internal) {
500 DEBUG(10, ("set_domain_online_request: Internal domains are "
501 "always online\n"));
502 return;
505 /* We've been told it's safe to go online and
506 try and connect to a DC. But I don't believe it
507 because network manager seems to lie.
508 Wait at least 5 seconds. Heuristics suck... */
511 GetTimeOfDay(&tev);
513 /* Go into "startup" mode again. */
514 domain->startup_time = time_mono(NULL);
515 domain->startup = True;
517 tev.tv_sec += 5;
519 if (!domain->check_online_event) {
520 /* If we've come from being globally offline we
521 don't have a check online event handler set.
522 We need to add one now we're trying to go
523 back online. */
525 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
526 domain->name ));
529 TALLOC_FREE(domain->check_online_event);
531 domain->check_online_event = event_add_timed(winbind_event_context(),
532 NULL,
533 tev,
534 check_domain_online_handler,
535 domain);
537 /* The above *has* to succeed for winbindd to work. */
538 if (!domain->check_online_event) {
539 smb_panic("set_domain_online_request: failed to add online handler");
543 /****************************************************************
544 Add -ve connection cache entries for domain and realm.
545 ****************************************************************/
547 static void winbind_add_failed_connection_entry(
548 const struct winbindd_domain *domain,
549 const char *server,
550 NTSTATUS result)
552 add_failed_connection_entry(domain->name, server, result);
553 /* If this was the saf name for the last thing we talked to,
554 remove it. */
555 saf_delete(domain->name);
556 if (*domain->alt_name) {
557 add_failed_connection_entry(domain->alt_name, server, result);
558 saf_delete(domain->alt_name);
560 winbindd_unset_locator_kdc_env(domain);
563 /* Choose between anonymous or authenticated connections. We need to use
564 an authenticated connection if DCs have the RestrictAnonymous registry
565 entry set > 0, or the "Additional restrictions for anonymous
566 connections" set in the win2k Local Security Policy.
568 Caller to free() result in domain, username, password
571 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
573 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
574 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
575 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
577 if (*username && **username) {
579 if (!*domain || !**domain)
580 *domain = smb_xstrdup(lp_workgroup());
582 if (!*password || !**password)
583 *password = smb_xstrdup("");
585 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
586 *domain, *username));
588 } else {
589 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
590 *username = smb_xstrdup("");
591 *domain = smb_xstrdup("");
592 *password = smb_xstrdup("");
596 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
597 fstring dcname,
598 struct sockaddr_storage *dc_ss)
600 struct winbindd_domain *our_domain = NULL;
601 struct rpc_pipe_client *netlogon_pipe = NULL;
602 NTSTATUS result;
603 WERROR werr;
604 TALLOC_CTX *mem_ctx;
605 unsigned int orig_timeout;
606 const char *tmp = NULL;
607 const char *p;
608 struct dcerpc_binding_handle *b;
610 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
611 * moment.... */
613 if (IS_DC) {
614 return False;
617 if (domain->primary) {
618 return False;
621 our_domain = find_our_domain();
623 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
624 return False;
627 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
628 if (!NT_STATUS_IS_OK(result)) {
629 talloc_destroy(mem_ctx);
630 return False;
633 b = netlogon_pipe->binding_handle;
635 /* This call can take a long time - allow the server to time out.
636 35 seconds should do it. */
638 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
640 if (our_domain->active_directory) {
641 struct netr_DsRGetDCNameInfo *domain_info = NULL;
643 result = dcerpc_netr_DsRGetDCName(b,
644 mem_ctx,
645 our_domain->dcname,
646 domain->name,
647 NULL,
648 NULL,
649 DS_RETURN_DNS_NAME,
650 &domain_info,
651 &werr);
652 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
653 tmp = talloc_strdup(
654 mem_ctx, domain_info->dc_unc);
655 if (tmp == NULL) {
656 DEBUG(0, ("talloc_strdup failed\n"));
657 talloc_destroy(mem_ctx);
658 return false;
660 if (strlen(domain->alt_name) == 0) {
661 fstrcpy(domain->alt_name,
662 domain_info->domain_name);
664 if (strlen(domain->forest_name) == 0) {
665 fstrcpy(domain->forest_name,
666 domain_info->forest_name);
669 } else {
670 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
671 our_domain->dcname,
672 domain->name,
673 &tmp,
674 &werr);
677 /* And restore our original timeout. */
678 rpccli_set_timeout(netlogon_pipe, orig_timeout);
680 if (!NT_STATUS_IS_OK(result)) {
681 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
682 nt_errstr(result)));
683 talloc_destroy(mem_ctx);
684 return false;
687 if (!W_ERROR_IS_OK(werr)) {
688 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
689 win_errstr(werr)));
690 talloc_destroy(mem_ctx);
691 return false;
694 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
695 p = strip_hostname(tmp);
697 fstrcpy(dcname, p);
699 talloc_destroy(mem_ctx);
701 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
703 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
704 return False;
707 return True;
711 * Helper function to assemble trust password and account name
713 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
714 char **machine_password,
715 char **machine_account,
716 char **machine_krb5_principal)
718 const char *account_name;
719 const char *name = NULL;
721 /* If we are a DC and this is not our own domain */
723 if (IS_DC) {
724 name = domain->name;
725 } else {
726 struct winbindd_domain *our_domain = find_our_domain();
728 if (!our_domain)
729 return NT_STATUS_INVALID_SERVER_STATE;
731 name = our_domain->name;
734 if (!get_trust_pw_clear(name, machine_password,
735 &account_name, NULL))
737 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
740 if ((machine_account != NULL) &&
741 (asprintf(machine_account, "%s$", account_name) == -1))
743 return NT_STATUS_NO_MEMORY;
746 /* For now assume our machine account only exists in our domain */
748 if (machine_krb5_principal != NULL)
750 struct winbindd_domain *our_domain = find_our_domain();
752 if (!our_domain) {
753 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
756 if (asprintf(machine_krb5_principal, "%s$@%s",
757 account_name, our_domain->alt_name) == -1)
759 return NT_STATUS_NO_MEMORY;
762 strupper_m(*machine_krb5_principal);
765 return NT_STATUS_OK;
768 /************************************************************************
769 Given a fd with a just-connected TCP connection to a DC, open a connection
770 to the pipe.
771 ************************************************************************/
773 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
774 const int sockfd,
775 const char *controller,
776 struct cli_state **cli,
777 bool *retry)
779 char *machine_password = NULL;
780 char *machine_krb5_principal = NULL;
781 char *machine_account = NULL;
782 char *ipc_username = NULL;
783 char *ipc_domain = NULL;
784 char *ipc_password = NULL;
786 struct named_mutex *mutex;
788 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
790 struct sockaddr peeraddr;
791 socklen_t peeraddr_len;
793 struct sockaddr_in *peeraddr_in =
794 (struct sockaddr_in *)(void *)&peeraddr;
796 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
797 controller, domain->name ));
799 *retry = True;
801 mutex = grab_named_mutex(talloc_tos(), controller,
802 WINBIND_SERVER_MUTEX_WAIT_TIME);
803 if (mutex == NULL) {
804 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
805 controller));
806 result = NT_STATUS_POSSIBLE_DEADLOCK;
807 goto done;
810 if ((*cli = cli_initialise()) == NULL) {
811 DEBUG(1, ("Could not cli_initialize\n"));
812 result = NT_STATUS_NO_MEMORY;
813 goto done;
816 (*cli)->timeout = 10000; /* 10 seconds */
817 (*cli)->fd = sockfd;
818 fstrcpy((*cli)->desthost, controller);
819 (*cli)->use_kerberos = True;
821 peeraddr_len = sizeof(peeraddr);
823 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
824 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
825 strerror(errno)));
826 result = NT_STATUS_UNSUCCESSFUL;
827 goto done;
830 if ((peeraddr_len != sizeof(struct sockaddr_in))
831 #ifdef HAVE_IPV6
832 && (peeraddr_len != sizeof(struct sockaddr_in6))
833 #endif
835 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
836 peeraddr_len));
837 result = NT_STATUS_UNSUCCESSFUL;
838 goto done;
841 if ((peeraddr_in->sin_family != PF_INET)
842 #ifdef HAVE_IPV6
843 && (peeraddr_in->sin_family != PF_INET6)
844 #endif
846 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
847 peeraddr_in->sin_family));
848 result = NT_STATUS_UNSUCCESSFUL;
849 goto done;
852 result = cli_negprot(*cli);
854 if (!NT_STATUS_IS_OK(result)) {
855 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
856 goto done;
859 if (!is_dc_trusted_domain_situation(domain->name) &&
860 (*cli)->protocol >= PROTOCOL_NT1 &&
861 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
863 ADS_STATUS ads_status;
865 result = get_trust_creds(domain, &machine_password,
866 &machine_account,
867 &machine_krb5_principal);
868 if (!NT_STATUS_IS_OK(result)) {
869 goto anon_fallback;
872 if (lp_security() == SEC_ADS) {
874 /* Try a krb5 session */
876 (*cli)->use_kerberos = True;
877 DEBUG(5, ("connecting to %s from %s with kerberos principal "
878 "[%s] and realm [%s]\n", controller, global_myname(),
879 machine_krb5_principal, domain->alt_name));
881 winbindd_set_locator_kdc_envs(domain);
883 ads_status = cli_session_setup_spnego(*cli,
884 machine_krb5_principal,
885 machine_password,
886 lp_workgroup(),
887 domain->alt_name);
889 if (!ADS_ERR_OK(ads_status)) {
890 DEBUG(4,("failed kerberos session setup with %s\n",
891 ads_errstr(ads_status)));
894 result = ads_ntstatus(ads_status);
895 if (NT_STATUS_IS_OK(result)) {
896 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
897 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
898 if (!NT_STATUS_IS_OK(result)) {
899 goto done;
901 goto session_setup_done;
905 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
906 (*cli)->use_kerberos = False;
908 DEBUG(5, ("connecting to %s from %s with username "
909 "[%s]\\[%s]\n", controller, global_myname(),
910 lp_workgroup(), machine_account));
912 ads_status = cli_session_setup_spnego(*cli,
913 machine_account,
914 machine_password,
915 lp_workgroup(),
916 NULL);
917 if (!ADS_ERR_OK(ads_status)) {
918 DEBUG(4, ("authenticated session setup failed with %s\n",
919 ads_errstr(ads_status)));
922 result = ads_ntstatus(ads_status);
923 if (NT_STATUS_IS_OK(result)) {
924 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
925 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
926 if (!NT_STATUS_IS_OK(result)) {
927 goto done;
929 goto session_setup_done;
933 /* Fall back to non-kerberos session setup with auth_user */
935 (*cli)->use_kerberos = False;
937 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
939 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
940 (strlen(ipc_username) > 0)) {
942 /* Only try authenticated if we have a username */
944 DEBUG(5, ("connecting to %s from %s with username "
945 "[%s]\\[%s]\n", controller, global_myname(),
946 ipc_domain, ipc_username));
948 if (NT_STATUS_IS_OK(cli_session_setup(
949 *cli, ipc_username,
950 ipc_password, strlen(ipc_password)+1,
951 ipc_password, strlen(ipc_password)+1,
952 ipc_domain))) {
953 /* Successful logon with given username. */
954 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
955 if (!NT_STATUS_IS_OK(result)) {
956 goto done;
958 goto session_setup_done;
959 } else {
960 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
961 ipc_domain, ipc_username ));
965 anon_fallback:
967 /* Fall back to anonymous connection, this might fail later */
968 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
969 "connection for DC %s\n",
970 controller ));
972 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
973 NULL, 0, ""))) {
974 DEBUG(5, ("Connected anonymously\n"));
975 result = cli_init_creds(*cli, "", "", "");
976 if (!NT_STATUS_IS_OK(result)) {
977 goto done;
979 goto session_setup_done;
982 result = cli_nt_error(*cli);
984 if (NT_STATUS_IS_OK(result))
985 result = NT_STATUS_UNSUCCESSFUL;
987 /* We can't session setup */
989 goto done;
991 session_setup_done:
993 /* cache the server name for later connections */
995 saf_store( domain->name, (*cli)->desthost );
996 if (domain->alt_name && (*cli)->use_kerberos) {
997 saf_store( domain->alt_name, (*cli)->desthost );
1000 winbindd_set_locator_kdc_envs(domain);
1002 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
1004 if (!NT_STATUS_IS_OK(result)) {
1005 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1006 goto done;
1009 TALLOC_FREE(mutex);
1010 *retry = False;
1012 /* set the domain if empty; needed for schannel connections */
1013 if ( !(*cli)->domain[0] ) {
1014 result = cli_set_domain((*cli), domain->name);
1015 if (!NT_STATUS_IS_OK(result)) {
1016 return result;
1020 result = NT_STATUS_OK;
1022 done:
1023 TALLOC_FREE(mutex);
1024 SAFE_FREE(machine_account);
1025 SAFE_FREE(machine_password);
1026 SAFE_FREE(machine_krb5_principal);
1027 SAFE_FREE(ipc_username);
1028 SAFE_FREE(ipc_domain);
1029 SAFE_FREE(ipc_password);
1031 if (!NT_STATUS_IS_OK(result)) {
1032 winbind_add_failed_connection_entry(domain, controller, result);
1033 if ((*cli) != NULL) {
1034 cli_shutdown(*cli);
1035 *cli = NULL;
1039 return result;
1042 /*******************************************************************
1043 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1044 array.
1046 Keeps the list unique by not adding duplicate entries.
1048 @param[in] mem_ctx talloc memory context to allocate from
1049 @param[in] domain_name domain of the DC
1050 @param[in] dcname name of the DC to add to the list
1051 @param[in] pss Internet address and port pair to add to the list
1052 @param[in,out] dcs array of dc_name_ip structures to add to
1053 @param[in,out] num_dcs number of dcs returned in the dcs array
1054 @return true if the list was added to, false otherwise
1055 *******************************************************************/
1057 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1058 const char *dcname, struct sockaddr_storage *pss,
1059 struct dc_name_ip **dcs, int *num)
1061 int i = 0;
1063 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1064 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1065 return False;
1068 /* Make sure there's no duplicates in the list */
1069 for (i=0; i<*num; i++)
1070 if (sockaddr_equal(
1071 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1072 (struct sockaddr *)(void *)pss))
1073 return False;
1075 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1077 if (*dcs == NULL)
1078 return False;
1080 fstrcpy((*dcs)[*num].name, dcname);
1081 (*dcs)[*num].ss = *pss;
1082 *num += 1;
1083 return True;
1086 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1087 struct sockaddr_storage *pss, uint16 port,
1088 struct sockaddr_storage **addrs, int *num)
1090 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1092 if (*addrs == NULL) {
1093 *num = 0;
1094 return False;
1097 (*addrs)[*num] = *pss;
1098 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1100 *num += 1;
1101 return True;
1104 /*******************************************************************
1105 convert an ip to a name
1106 *******************************************************************/
1108 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1109 const struct winbindd_domain *domain,
1110 struct sockaddr_storage *pss,
1111 fstring name )
1113 struct ip_service ip_list;
1114 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1115 NTSTATUS status;
1116 const char *dc_name;
1118 ip_list.ss = *pss;
1119 ip_list.port = 0;
1121 #ifdef HAVE_ADS
1122 /* For active directory servers, try to get the ldap server name.
1123 None of these failures should be considered critical for now */
1125 if (lp_security() == SEC_ADS) {
1126 ADS_STRUCT *ads;
1127 ADS_STATUS ads_status;
1128 char addr[INET6_ADDRSTRLEN];
1130 print_sockaddr(addr, sizeof(addr), pss);
1132 ads = ads_init(domain->alt_name, domain->name, addr);
1133 ads->auth.flags |= ADS_AUTH_NO_BIND;
1135 ads_status = ads_connect(ads);
1136 if (ADS_ERR_OK(ads_status)) {
1137 /* We got a cldap packet. */
1138 fstrcpy(name, ads->config.ldap_server_name);
1139 namecache_store(name, 0x20, 1, &ip_list);
1141 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1143 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1144 if (ads_closest_dc(ads)) {
1145 char *sitename = sitename_fetch(ads->config.realm);
1147 /* We're going to use this KDC for this realm/domain.
1148 If we are using sites, then force the krb5 libs
1149 to use this KDC. */
1151 create_local_private_krb5_conf_for_domain(domain->alt_name,
1152 domain->name,
1153 sitename,
1154 pss,
1155 name);
1157 SAFE_FREE(sitename);
1158 } else {
1159 /* use an off site KDC */
1160 create_local_private_krb5_conf_for_domain(domain->alt_name,
1161 domain->name,
1162 NULL,
1163 pss,
1164 name);
1166 winbindd_set_locator_kdc_envs(domain);
1168 /* Ensure we contact this DC also. */
1169 saf_store( domain->name, name);
1170 saf_store( domain->alt_name, name);
1173 ads_destroy( &ads );
1174 return True;
1177 ads_destroy( &ads );
1179 #endif
1181 status = nbt_getdc(winbind_messaging_context(), pss, domain->name,
1182 &domain->sid, nt_version, mem_ctx, &nt_version,
1183 &dc_name, NULL);
1184 if (NT_STATUS_IS_OK(status)) {
1185 fstrcpy(name, dc_name);
1186 namecache_store(name, 0x20, 1, &ip_list);
1187 return True;
1190 /* try node status request */
1192 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1193 namecache_store(name, 0x20, 1, &ip_list);
1194 return True;
1196 return False;
1199 /*******************************************************************
1200 Retrieve a list of IP addresses for domain controllers.
1202 The array is sorted in the preferred connection order.
1204 @param[in] mem_ctx talloc memory context to allocate from
1205 @param[in] domain domain to retrieve DCs for
1206 @param[out] dcs array of dcs that will be returned
1207 @param[out] num_dcs number of dcs returned in the dcs array
1208 @return always true
1209 *******************************************************************/
1211 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1212 struct dc_name_ip **dcs, int *num_dcs)
1214 fstring dcname;
1215 struct sockaddr_storage ss;
1216 struct ip_service *ip_list = NULL;
1217 int iplist_size = 0;
1218 int i;
1219 bool is_our_domain;
1220 enum security_types sec = (enum security_types)lp_security();
1222 is_our_domain = strequal(domain->name, lp_workgroup());
1224 /* If not our domain, get the preferred DC, by asking our primary DC */
1225 if ( !is_our_domain
1226 && get_dc_name_via_netlogon(domain, dcname, &ss)
1227 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1228 num_dcs) )
1230 char addr[INET6_ADDRSTRLEN];
1231 print_sockaddr(addr, sizeof(addr), &ss);
1232 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1233 dcname, addr));
1234 return True;
1237 if (sec == SEC_ADS) {
1238 char *sitename = NULL;
1240 /* We need to make sure we know the local site before
1241 doing any DNS queries, as this will restrict the
1242 get_sorted_dc_list() call below to only fetching
1243 DNS records for the correct site. */
1245 /* Find any DC to get the site record.
1246 We deliberately don't care about the
1247 return here. */
1249 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1251 sitename = sitename_fetch(domain->alt_name);
1252 if (sitename) {
1254 /* Do the site-specific AD dns lookup first. */
1255 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1256 &iplist_size, True);
1258 /* Add ips to the DC array. We don't look up the name
1259 of the DC in this function, but we fill in the char*
1260 of the ip now to make the failed connection cache
1261 work */
1262 for ( i=0; i<iplist_size; i++ ) {
1263 char addr[INET6_ADDRSTRLEN];
1264 print_sockaddr(addr, sizeof(addr),
1265 &ip_list[i].ss);
1266 add_one_dc_unique(mem_ctx,
1267 domain->name,
1268 addr,
1269 &ip_list[i].ss,
1270 dcs,
1271 num_dcs);
1274 SAFE_FREE(ip_list);
1275 SAFE_FREE(sitename);
1276 iplist_size = 0;
1279 /* Now we add DCs from the main AD DNS lookup. */
1280 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1281 &iplist_size, True);
1283 for ( i=0; i<iplist_size; i++ ) {
1284 char addr[INET6_ADDRSTRLEN];
1285 print_sockaddr(addr, sizeof(addr),
1286 &ip_list[i].ss);
1287 add_one_dc_unique(mem_ctx,
1288 domain->name,
1289 addr,
1290 &ip_list[i].ss,
1291 dcs,
1292 num_dcs);
1295 SAFE_FREE(ip_list);
1296 iplist_size = 0;
1299 /* Try standard netbios queries if no ADS */
1300 if (*num_dcs == 0) {
1301 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1302 False);
1304 for ( i=0; i<iplist_size; i++ ) {
1305 char addr[INET6_ADDRSTRLEN];
1306 print_sockaddr(addr, sizeof(addr),
1307 &ip_list[i].ss);
1308 add_one_dc_unique(mem_ctx,
1309 domain->name,
1310 addr,
1311 &ip_list[i].ss,
1312 dcs,
1313 num_dcs);
1316 SAFE_FREE(ip_list);
1317 iplist_size = 0;
1320 return True;
1323 /*******************************************************************
1324 Find and make a connection to a DC in the given domain.
1326 @param[in] mem_ctx talloc memory context to allocate from
1327 @param[in] domain domain to find a dc in
1328 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1329 @param[out] pss DC Internet address and port
1330 @param[out] fd fd of the open socket connected to the newly found dc
1331 @return true when a DC connection is made, false otherwise
1332 *******************************************************************/
1334 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1335 struct winbindd_domain *domain,
1336 fstring dcname, struct sockaddr_storage *pss, int *fd)
1338 struct dc_name_ip *dcs = NULL;
1339 int num_dcs = 0;
1341 const char **dcnames = NULL;
1342 int num_dcnames = 0;
1344 struct sockaddr_storage *addrs = NULL;
1345 int num_addrs = 0;
1347 int i;
1348 size_t fd_index;
1350 NTSTATUS status;
1352 *fd = -1;
1354 again:
1355 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1356 return False;
1358 for (i=0; i<num_dcs; i++) {
1360 if (!add_string_to_array(mem_ctx, dcs[i].name,
1361 &dcnames, &num_dcnames)) {
1362 return False;
1364 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1365 &addrs, &num_addrs)) {
1366 return False;
1370 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1371 return False;
1373 if ((addrs == NULL) || (dcnames == NULL))
1374 return False;
1376 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1377 num_addrs, 0, fd, &fd_index, NULL);
1378 if (!NT_STATUS_IS_OK(status)) {
1379 for (i=0; i<num_dcs; i++) {
1380 char ab[INET6_ADDRSTRLEN];
1381 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1382 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1383 "domain %s address %s. Error was %s\n",
1384 domain->name, ab, nt_errstr(status) ));
1385 winbind_add_failed_connection_entry(domain,
1386 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1388 return False;
1391 *pss = addrs[fd_index];
1393 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1394 /* Ok, we've got a name for the DC */
1395 fstrcpy(dcname, dcnames[fd_index]);
1396 return True;
1399 /* Try to figure out the name */
1400 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1401 return True;
1404 /* We can not continue without the DC's name */
1405 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1406 NT_STATUS_UNSUCCESSFUL);
1408 /* Throw away all arrays as we're doing this again. */
1409 TALLOC_FREE(dcs);
1410 num_dcs = 0;
1412 TALLOC_FREE(dcnames);
1413 num_dcnames = 0;
1415 TALLOC_FREE(addrs);
1416 num_addrs = 0;
1418 close(*fd);
1419 *fd = -1;
1421 goto again;
1424 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1426 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1427 domain_name);
1430 static void store_current_dc_in_gencache(const char *domain_name,
1431 const char *dc_name,
1432 struct cli_state *cli)
1434 char addr[INET6_ADDRSTRLEN];
1435 char *key = NULL;
1436 char *value = NULL;
1438 if (cli == NULL) {
1439 return;
1441 if (cli->fd == -1) {
1442 return;
1444 get_peer_addr(cli->fd, addr, sizeof(addr));
1446 key = current_dc_key(talloc_tos(), domain_name);
1447 if (key == NULL) {
1448 goto done;
1451 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1452 if (value == NULL) {
1453 goto done;
1456 gencache_set(key, value, 0x7fffffff);
1457 done:
1458 TALLOC_FREE(value);
1459 TALLOC_FREE(key);
1462 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1463 const char *domain_name,
1464 char **p_dc_name, char **p_dc_ip)
1466 char *key, *value, *p;
1467 bool ret = false;
1468 char *dc_name = NULL;
1469 char *dc_ip = NULL;
1471 key = current_dc_key(talloc_tos(), domain_name);
1472 if (key == NULL) {
1473 goto done;
1475 if (!gencache_get(key, &value, NULL)) {
1476 goto done;
1478 p = strchr(value, ' ');
1479 if (p == NULL) {
1480 goto done;
1482 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1483 if (dc_ip == NULL) {
1484 goto done;
1486 dc_name = talloc_strdup(mem_ctx, p+1);
1487 if (dc_name == NULL) {
1488 goto done;
1491 if (p_dc_ip != NULL) {
1492 *p_dc_ip = dc_ip;
1493 dc_ip = NULL;
1495 if (p_dc_name != NULL) {
1496 *p_dc_name = dc_name;
1497 dc_name = NULL;
1499 ret = true;
1500 done:
1501 TALLOC_FREE(dc_name);
1502 TALLOC_FREE(dc_ip);
1503 TALLOC_FREE(key);
1504 return ret;
1507 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1508 struct winbindd_cm_conn *new_conn)
1510 TALLOC_CTX *mem_ctx;
1511 NTSTATUS result;
1512 char *saf_servername = saf_fetch( domain->name );
1513 int retries;
1515 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1516 SAFE_FREE(saf_servername);
1517 set_domain_offline(domain);
1518 return NT_STATUS_NO_MEMORY;
1521 /* we have to check the server affinity cache here since
1522 later we select a DC based on response time and not preference */
1524 /* Check the negative connection cache
1525 before talking to it. It going down may have
1526 triggered the reconnection. */
1528 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1530 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1531 saf_servername, domain->name ));
1533 /* convert an ip address to a name */
1534 if (is_ipaddress( saf_servername ) ) {
1535 fstring saf_name;
1536 struct sockaddr_storage ss;
1538 if (!interpret_string_addr(&ss, saf_servername,
1539 AI_NUMERICHOST)) {
1540 return NT_STATUS_UNSUCCESSFUL;
1542 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1543 fstrcpy( domain->dcname, saf_name );
1544 } else {
1545 winbind_add_failed_connection_entry(
1546 domain, saf_servername,
1547 NT_STATUS_UNSUCCESSFUL);
1549 } else {
1550 fstrcpy( domain->dcname, saf_servername );
1553 SAFE_FREE( saf_servername );
1556 for (retries = 0; retries < 3; retries++) {
1557 int fd = -1;
1558 bool retry = False;
1560 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1562 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1563 domain->dcname, domain->name ));
1565 if (*domain->dcname
1566 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1567 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1569 NTSTATUS status;
1571 status = smbsock_connect(&domain->dcaddr, 0,
1572 NULL, -1, NULL, -1,
1573 &fd, NULL);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 fd = -1;
1579 if ((fd == -1)
1580 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1582 /* This is the one place where we will
1583 set the global winbindd offline state
1584 to true, if a "WINBINDD_OFFLINE" entry
1585 is found in the winbindd cache. */
1586 set_global_winbindd_state_offline();
1587 break;
1590 new_conn->cli = NULL;
1592 result = cm_prepare_connection(domain, fd, domain->dcname,
1593 &new_conn->cli, &retry);
1595 if (!retry)
1596 break;
1599 if (NT_STATUS_IS_OK(result)) {
1601 winbindd_set_locator_kdc_envs(domain);
1603 if (domain->online == False) {
1604 /* We're changing state from offline to online. */
1605 set_global_winbindd_state_online();
1607 set_domain_online(domain);
1610 * Much as I hate global state, this seems to be the point
1611 * where we can be certain that we have a proper connection to
1612 * a DC. wbinfo --dc-info needs that information, store it in
1613 * gencache with a looong timeout. This will need revisiting
1614 * once we start to connect to multiple DCs, wbcDcInfo is
1615 * already prepared for that.
1617 store_current_dc_in_gencache(domain->name, domain->dcname,
1618 new_conn->cli);
1619 } else {
1620 /* Ensure we setup the retry handler. */
1621 set_domain_offline(domain);
1624 talloc_destroy(mem_ctx);
1625 return result;
1628 /* Close down all open pipes on a connection. */
1630 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1632 NTSTATUS result;
1634 /* We're closing down a possibly dead
1635 connection. Don't have impossibly long (10s) timeouts. */
1637 if (conn->cli) {
1638 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1641 if (conn->samr_pipe != NULL) {
1642 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1643 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1644 talloc_tos(),
1645 &conn->sam_connect_handle,
1646 &result);
1648 TALLOC_FREE(conn->samr_pipe);
1649 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1650 if (conn->cli) {
1651 cli_set_timeout(conn->cli, 500);
1655 if (conn->lsa_pipe != NULL) {
1656 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1657 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1658 talloc_tos(),
1659 &conn->lsa_policy,
1660 &result);
1662 TALLOC_FREE(conn->lsa_pipe);
1663 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1664 if (conn->cli) {
1665 cli_set_timeout(conn->cli, 500);
1669 if (conn->lsa_pipe_tcp != NULL) {
1670 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1671 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1672 talloc_tos(),
1673 &conn->lsa_policy,
1674 &result);
1676 TALLOC_FREE(conn->lsa_pipe_tcp);
1677 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1678 if (conn->cli) {
1679 cli_set_timeout(conn->cli, 500);
1683 if (conn->netlogon_pipe != NULL) {
1684 TALLOC_FREE(conn->netlogon_pipe);
1685 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1686 if (conn->cli) {
1687 cli_set_timeout(conn->cli, 500);
1691 if (conn->cli) {
1692 cli_shutdown(conn->cli);
1695 conn->cli = NULL;
1698 void close_conns_after_fork(void)
1700 struct winbindd_domain *domain;
1702 for (domain = domain_list(); domain; domain = domain->next) {
1703 struct cli_state *cli = domain->conn.cli;
1706 * first close the low level SMB TCP connection
1707 * so that we don't generate any SMBclose
1708 * requests in invalidate_cm_connection()
1710 if (cli && cli->fd != -1) {
1711 close(domain->conn.cli->fd);
1712 domain->conn.cli->fd = -1;
1715 invalidate_cm_connection(&domain->conn);
1719 static bool connection_ok(struct winbindd_domain *domain)
1721 bool ok;
1723 ok = cli_state_is_connected(domain->conn.cli);
1724 if (!ok) {
1725 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1726 domain->dcname, domain->name));
1727 return False;
1730 if (domain->online == False) {
1731 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1732 return False;
1735 return True;
1738 /* Initialize a new connection up to the RPC BIND.
1739 Bypass online status check so always does network calls. */
1741 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1743 NTSTATUS result;
1745 /* Internal connections never use the network. */
1746 if (domain->internal) {
1747 domain->initialized = True;
1748 return NT_STATUS_OK;
1751 if (!winbindd_can_contact_domain(domain)) {
1752 invalidate_cm_connection(&domain->conn);
1753 domain->initialized = True;
1754 return NT_STATUS_OK;
1757 if (connection_ok(domain)) {
1758 if (!domain->initialized) {
1759 set_dc_type_and_flags(domain);
1761 return NT_STATUS_OK;
1764 invalidate_cm_connection(&domain->conn);
1766 result = cm_open_connection(domain, &domain->conn);
1768 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1769 set_dc_type_and_flags(domain);
1772 return result;
1775 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1777 if (domain->internal) {
1778 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1781 if (domain->initialized && !domain->online) {
1782 /* We check for online status elsewhere. */
1783 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1786 return init_dc_connection_network(domain);
1789 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1791 NTSTATUS status;
1793 status = init_dc_connection(domain);
1794 if (!NT_STATUS_IS_OK(status)) {
1795 return status;
1798 if (!domain->internal && domain->conn.cli == NULL) {
1799 /* happens for trusted domains without inbound trust */
1800 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1803 return NT_STATUS_OK;
1806 /******************************************************************************
1807 Set the trust flags (direction and forest location) for a domain
1808 ******************************************************************************/
1810 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1812 struct winbindd_domain *our_domain;
1813 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1814 WERROR werr;
1815 struct netr_DomainTrustList trusts;
1816 int i;
1817 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1818 NETR_TRUST_FLAG_OUTBOUND |
1819 NETR_TRUST_FLAG_INBOUND);
1820 struct rpc_pipe_client *cli;
1821 TALLOC_CTX *mem_ctx = NULL;
1822 struct dcerpc_binding_handle *b;
1824 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1826 /* Our primary domain doesn't need to worry about trust flags.
1827 Force it to go through the network setup */
1828 if ( domain->primary ) {
1829 return False;
1832 our_domain = find_our_domain();
1834 if ( !connection_ok(our_domain) ) {
1835 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1836 return False;
1839 /* This won't work unless our domain is AD */
1841 if ( !our_domain->active_directory ) {
1842 return False;
1845 /* Use DsEnumerateDomainTrusts to get us the trust direction
1846 and type */
1848 result = cm_connect_netlogon(our_domain, &cli);
1850 if (!NT_STATUS_IS_OK(result)) {
1851 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1852 "a connection to %s for PIPE_NETLOGON (%s)\n",
1853 domain->name, nt_errstr(result)));
1854 return False;
1857 b = cli->binding_handle;
1859 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1860 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1861 return False;
1864 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1865 cli->desthost,
1866 flags,
1867 &trusts,
1868 &werr);
1869 if (!NT_STATUS_IS_OK(result)) {
1870 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1871 "failed to query trusted domain list: %s\n",
1872 nt_errstr(result)));
1873 talloc_destroy(mem_ctx);
1874 return false;
1876 if (!W_ERROR_IS_OK(werr)) {
1877 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1878 "failed to query trusted domain list: %s\n",
1879 win_errstr(werr)));
1880 talloc_destroy(mem_ctx);
1881 return false;
1884 /* Now find the domain name and get the flags */
1886 for ( i=0; i<trusts.count; i++ ) {
1887 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1888 domain->domain_flags = trusts.array[i].trust_flags;
1889 domain->domain_type = trusts.array[i].trust_type;
1890 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1892 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1893 domain->active_directory = True;
1895 /* This flag is only set if the domain is *our*
1896 primary domain and the primary domain is in
1897 native mode */
1899 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1901 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1902 "native mode.\n", domain->name,
1903 domain->native_mode ? "" : "NOT "));
1905 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1906 "running active directory.\n", domain->name,
1907 domain->active_directory ? "" : "NOT "));
1910 domain->initialized = True;
1912 break;
1916 talloc_destroy( mem_ctx );
1918 return domain->initialized;
1921 /******************************************************************************
1922 We can 'sense' certain things about the DC by it's replies to certain
1923 questions.
1925 This tells us if this particular remote server is Active Directory, and if it
1926 is native mode.
1927 ******************************************************************************/
1929 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1931 NTSTATUS status, result;
1932 WERROR werr;
1933 TALLOC_CTX *mem_ctx = NULL;
1934 struct rpc_pipe_client *cli = NULL;
1935 struct policy_handle pol;
1936 union dssetup_DsRoleInfo info;
1937 union lsa_PolicyInformation *lsa_info = NULL;
1939 if (!connection_ok(domain)) {
1940 return;
1943 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1944 domain->name);
1945 if (!mem_ctx) {
1946 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1947 return;
1950 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1952 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
1953 &ndr_table_dssetup.syntax_id,
1954 &cli);
1956 if (!NT_STATUS_IS_OK(status)) {
1957 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1958 "PI_DSSETUP on domain %s: (%s)\n",
1959 domain->name, nt_errstr(status)));
1961 /* if this is just a non-AD domain we need to continue
1962 * identifying so that we can in the end return with
1963 * domain->initialized = True - gd */
1965 goto no_dssetup;
1968 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
1969 DS_ROLE_BASIC_INFORMATION,
1970 &info,
1971 &werr);
1972 TALLOC_FREE(cli);
1974 if (NT_STATUS_IS_OK(status)) {
1975 result = werror_to_ntstatus(werr);
1977 if (!NT_STATUS_IS_OK(status)) {
1978 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1979 "on domain %s failed: (%s)\n",
1980 domain->name, nt_errstr(status)));
1982 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1983 * every opcode on the DSSETUP pipe, continue with
1984 * no_dssetup mode here as well to get domain->initialized
1985 * set - gd */
1987 if (NT_STATUS_V(status) == DCERPC_FAULT_OP_RNG_ERROR) {
1988 goto no_dssetup;
1991 TALLOC_FREE(mem_ctx);
1992 return;
1995 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1996 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1997 domain->native_mode = True;
1998 } else {
1999 domain->native_mode = False;
2002 no_dssetup:
2003 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2004 &ndr_table_lsarpc.syntax_id, &cli);
2006 if (!NT_STATUS_IS_OK(status)) {
2007 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2008 "PI_LSARPC on domain %s: (%s)\n",
2009 domain->name, nt_errstr(status)));
2010 TALLOC_FREE(cli);
2011 TALLOC_FREE(mem_ctx);
2012 return;
2015 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2016 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2018 if (NT_STATUS_IS_OK(status)) {
2019 /* This particular query is exactly what Win2k clients use
2020 to determine that the DC is active directory */
2021 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2022 &pol,
2023 LSA_POLICY_INFO_DNS,
2024 &lsa_info,
2025 &result);
2028 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2029 domain->active_directory = True;
2031 if (lsa_info->dns.name.string) {
2032 fstrcpy(domain->name, lsa_info->dns.name.string);
2035 if (lsa_info->dns.dns_domain.string) {
2036 fstrcpy(domain->alt_name,
2037 lsa_info->dns.dns_domain.string);
2040 /* See if we can set some domain trust flags about
2041 ourself */
2043 if (lsa_info->dns.dns_forest.string) {
2044 fstrcpy(domain->forest_name,
2045 lsa_info->dns.dns_forest.string);
2047 if (strequal(domain->forest_name, domain->alt_name)) {
2048 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2052 if (lsa_info->dns.sid) {
2053 sid_copy(&domain->sid, lsa_info->dns.sid);
2055 } else {
2056 domain->active_directory = False;
2058 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2059 SEC_FLAG_MAXIMUM_ALLOWED,
2060 &pol);
2062 if (!NT_STATUS_IS_OK(status)) {
2063 goto done;
2066 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2067 &pol,
2068 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2069 &lsa_info,
2070 &result);
2071 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2073 if (lsa_info->account_domain.name.string) {
2074 fstrcpy(domain->name,
2075 lsa_info->account_domain.name.string);
2078 if (lsa_info->account_domain.sid) {
2079 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2083 done:
2085 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2086 domain->name, domain->native_mode ? "" : "NOT "));
2088 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2089 domain->name, domain->active_directory ? "" : "NOT "));
2091 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2092 domain->can_do_validation6 = domain->active_directory;
2094 TALLOC_FREE(cli);
2096 TALLOC_FREE(mem_ctx);
2098 domain->initialized = True;
2101 /**********************************************************************
2102 Set the domain_flags (trust attributes, domain operating modes, etc...
2103 ***********************************************************************/
2105 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2107 /* we always have to contact our primary domain */
2109 if ( domain->primary ) {
2110 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2111 "primary domain\n"));
2112 set_dc_type_and_flags_connect( domain );
2113 return;
2116 /* Use our DC to get the information if possible */
2118 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2119 /* Otherwise, fallback to contacting the
2120 domain directly */
2121 set_dc_type_and_flags_connect( domain );
2124 return;
2129 /**********************************************************************
2130 ***********************************************************************/
2132 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2133 struct netlogon_creds_CredentialState **ppdc)
2135 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2136 struct rpc_pipe_client *netlogon_pipe;
2138 if (lp_client_schannel() == False) {
2139 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2142 result = cm_connect_netlogon(domain, &netlogon_pipe);
2143 if (!NT_STATUS_IS_OK(result)) {
2144 return result;
2147 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2148 netlogon pipe. */
2150 if (!domain->conn.netlogon_pipe->dc) {
2151 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2154 *ppdc = domain->conn.netlogon_pipe->dc;
2155 return NT_STATUS_OK;
2158 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2159 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2161 struct winbindd_cm_conn *conn;
2162 NTSTATUS status, result;
2163 struct netlogon_creds_CredentialState *p_creds;
2164 char *machine_password = NULL;
2165 char *machine_account = NULL;
2166 char *domain_name = NULL;
2168 if (sid_check_is_domain(&domain->sid)) {
2169 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2172 status = init_dc_connection_rpc(domain);
2173 if (!NT_STATUS_IS_OK(status)) {
2174 return status;
2177 conn = &domain->conn;
2179 if (rpccli_is_connected(conn->samr_pipe)) {
2180 goto done;
2183 TALLOC_FREE(conn->samr_pipe);
2186 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2187 * sign and sealed pipe using the machine account password by
2188 * preference. If we can't - try schannel, if that fails, try
2189 * anonymous.
2192 if ((conn->cli->user_name[0] == '\0') ||
2193 (conn->cli->domain[0] == '\0') ||
2194 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2196 status = get_trust_creds(domain, &machine_password,
2197 &machine_account, NULL);
2198 if (!NT_STATUS_IS_OK(status)) {
2199 DEBUG(10, ("cm_connect_sam: No no user available for "
2200 "domain %s, trying schannel\n", conn->cli->domain));
2201 goto schannel;
2203 domain_name = domain->name;
2204 } else {
2205 machine_password = SMB_STRDUP(conn->cli->password);
2206 machine_account = SMB_STRDUP(conn->cli->user_name);
2207 domain_name = conn->cli->domain;
2210 if (!machine_password || !machine_account) {
2211 status = NT_STATUS_NO_MEMORY;
2212 goto done;
2215 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2216 authenticated SAMR pipe with sign & seal. */
2217 status = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2218 &ndr_table_samr.syntax_id,
2219 NCACN_NP,
2220 DCERPC_AUTH_LEVEL_PRIVACY,
2221 domain_name,
2222 machine_account,
2223 machine_password,
2224 &conn->samr_pipe);
2226 if (!NT_STATUS_IS_OK(status)) {
2227 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2228 "pipe for domain %s using NTLMSSP "
2229 "authenticated pipe: user %s\\%s. Error was "
2230 "%s\n", domain->name, domain_name,
2231 machine_account, nt_errstr(status)));
2232 goto schannel;
2235 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2236 "domain %s using NTLMSSP authenticated "
2237 "pipe: user %s\\%s\n", domain->name,
2238 domain_name, machine_account));
2240 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2241 conn->samr_pipe->desthost,
2242 SEC_FLAG_MAXIMUM_ALLOWED,
2243 &conn->sam_connect_handle,
2244 &result);
2245 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2246 goto open_domain;
2248 if (NT_STATUS_IS_OK(status)) {
2249 status = result;
2252 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2253 "failed for domain %s, error was %s. Trying schannel\n",
2254 domain->name, nt_errstr(status) ));
2255 TALLOC_FREE(conn->samr_pipe);
2257 schannel:
2259 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2261 status = cm_get_schannel_creds(domain, &p_creds);
2262 if (!NT_STATUS_IS_OK(status)) {
2263 /* If this call fails - conn->cli can now be NULL ! */
2264 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2265 "for domain %s (error %s), trying anon\n",
2266 domain->name,
2267 nt_errstr(status) ));
2268 goto anonymous;
2270 status = cli_rpc_pipe_open_schannel_with_key
2271 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2272 DCERPC_AUTH_LEVEL_PRIVACY,
2273 domain->name, &p_creds, &conn->samr_pipe);
2275 if (!NT_STATUS_IS_OK(status)) {
2276 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2277 "domain %s using schannel. Error was %s\n",
2278 domain->name, nt_errstr(status) ));
2279 goto anonymous;
2281 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2282 "schannel.\n", domain->name ));
2284 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2285 conn->samr_pipe->desthost,
2286 SEC_FLAG_MAXIMUM_ALLOWED,
2287 &conn->sam_connect_handle,
2288 &result);
2289 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2290 goto open_domain;
2292 if (NT_STATUS_IS_OK(status)) {
2293 status = result;
2295 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2296 "for domain %s, error was %s. Trying anonymous\n",
2297 domain->name, nt_errstr(status) ));
2298 TALLOC_FREE(conn->samr_pipe);
2300 anonymous:
2302 /* Finally fall back to anonymous. */
2303 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2304 &conn->samr_pipe);
2306 if (!NT_STATUS_IS_OK(status)) {
2307 goto done;
2310 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2311 conn->samr_pipe->desthost,
2312 SEC_FLAG_MAXIMUM_ALLOWED,
2313 &conn->sam_connect_handle,
2314 &result);
2315 if (!NT_STATUS_IS_OK(status)) {
2316 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2317 "for domain %s Error was %s\n",
2318 domain->name, nt_errstr(status) ));
2319 goto done;
2321 if (!NT_STATUS_IS_OK(result)) {
2322 status = result;
2323 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2324 "for domain %s Error was %s\n",
2325 domain->name, nt_errstr(result)));
2326 goto done;
2329 open_domain:
2330 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2331 mem_ctx,
2332 &conn->sam_connect_handle,
2333 SEC_FLAG_MAXIMUM_ALLOWED,
2334 &domain->sid,
2335 &conn->sam_domain_handle,
2336 &result);
2337 if (!NT_STATUS_IS_OK(status)) {
2338 goto done;
2341 status = result;
2342 done:
2344 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2346 * if we got access denied, we might just have no access rights
2347 * to talk to the remote samr server server (e.g. when we are a
2348 * PDC and we are connecting a w2k8 pdc via an interdomain
2349 * trust). In that case do not invalidate the whole connection
2350 * stack
2352 TALLOC_FREE(conn->samr_pipe);
2353 ZERO_STRUCT(conn->sam_domain_handle);
2354 return status;
2355 } else if (!NT_STATUS_IS_OK(status)) {
2356 invalidate_cm_connection(conn);
2357 return status;
2360 *cli = conn->samr_pipe;
2361 *sam_handle = conn->sam_domain_handle;
2362 SAFE_FREE(machine_password);
2363 SAFE_FREE(machine_account);
2364 return status;
2367 /**********************************************************************
2368 open an schanneld ncacn_ip_tcp connection to LSA
2369 ***********************************************************************/
2371 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2372 TALLOC_CTX *mem_ctx,
2373 struct rpc_pipe_client **cli)
2375 struct winbindd_cm_conn *conn;
2376 struct netlogon_creds_CredentialState *creds;
2377 NTSTATUS status;
2379 DEBUG(10,("cm_connect_lsa_tcp\n"));
2381 status = init_dc_connection_rpc(domain);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 return status;
2386 conn = &domain->conn;
2388 if (conn->lsa_pipe_tcp &&
2389 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2390 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2391 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2392 goto done;
2395 TALLOC_FREE(conn->lsa_pipe_tcp);
2397 status = cm_get_schannel_creds(domain, &creds);
2398 if (!NT_STATUS_IS_OK(status)) {
2399 goto done;
2402 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2403 &ndr_table_lsarpc.syntax_id,
2404 NCACN_IP_TCP,
2405 DCERPC_AUTH_LEVEL_PRIVACY,
2406 domain->name,
2407 &creds,
2408 &conn->lsa_pipe_tcp);
2409 if (!NT_STATUS_IS_OK(status)) {
2410 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2411 nt_errstr(status)));
2412 goto done;
2415 done:
2416 if (!NT_STATUS_IS_OK(status)) {
2417 TALLOC_FREE(conn->lsa_pipe_tcp);
2418 return status;
2421 *cli = conn->lsa_pipe_tcp;
2423 return status;
2426 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2427 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2429 struct winbindd_cm_conn *conn;
2430 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2431 struct netlogon_creds_CredentialState *p_creds;
2433 result = init_dc_connection_rpc(domain);
2434 if (!NT_STATUS_IS_OK(result))
2435 return result;
2437 conn = &domain->conn;
2439 if (rpccli_is_connected(conn->lsa_pipe)) {
2440 goto done;
2443 TALLOC_FREE(conn->lsa_pipe);
2445 if ((conn->cli->user_name[0] == '\0') ||
2446 (conn->cli->domain[0] == '\0') ||
2447 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2448 DEBUG(10, ("cm_connect_lsa: No no user available for "
2449 "domain %s, trying schannel\n", conn->cli->domain));
2450 goto schannel;
2453 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2454 * authenticated LSA pipe with sign & seal. */
2455 result = cli_rpc_pipe_open_spnego_ntlmssp
2456 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2457 DCERPC_AUTH_LEVEL_PRIVACY,
2458 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2459 &conn->lsa_pipe);
2461 if (!NT_STATUS_IS_OK(result)) {
2462 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2463 "domain %s using NTLMSSP authenticated pipe: user "
2464 "%s\\%s. Error was %s. Trying schannel.\n",
2465 domain->name, conn->cli->domain,
2466 conn->cli->user_name, nt_errstr(result)));
2467 goto schannel;
2470 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2471 "NTLMSSP authenticated pipe: user %s\\%s\n",
2472 domain->name, conn->cli->domain, conn->cli->user_name ));
2474 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2475 SEC_FLAG_MAXIMUM_ALLOWED,
2476 &conn->lsa_policy);
2477 if (NT_STATUS_IS_OK(result)) {
2478 goto done;
2481 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2482 "schannel\n"));
2484 TALLOC_FREE(conn->lsa_pipe);
2486 schannel:
2488 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2490 result = cm_get_schannel_creds(domain, &p_creds);
2491 if (!NT_STATUS_IS_OK(result)) {
2492 /* If this call fails - conn->cli can now be NULL ! */
2493 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2494 "for domain %s (error %s), trying anon\n",
2495 domain->name,
2496 nt_errstr(result) ));
2497 goto anonymous;
2499 result = cli_rpc_pipe_open_schannel_with_key
2500 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2501 DCERPC_AUTH_LEVEL_PRIVACY,
2502 domain->name, &p_creds, &conn->lsa_pipe);
2504 if (!NT_STATUS_IS_OK(result)) {
2505 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2506 "domain %s using schannel. Error was %s\n",
2507 domain->name, nt_errstr(result) ));
2508 goto anonymous;
2510 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2511 "schannel.\n", domain->name ));
2513 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2514 SEC_FLAG_MAXIMUM_ALLOWED,
2515 &conn->lsa_policy);
2516 if (NT_STATUS_IS_OK(result)) {
2517 goto done;
2520 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2521 "anonymous\n"));
2523 TALLOC_FREE(conn->lsa_pipe);
2525 anonymous:
2527 result = cli_rpc_pipe_open_noauth(conn->cli,
2528 &ndr_table_lsarpc.syntax_id,
2529 &conn->lsa_pipe);
2530 if (!NT_STATUS_IS_OK(result)) {
2531 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2532 goto done;
2535 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2536 SEC_FLAG_MAXIMUM_ALLOWED,
2537 &conn->lsa_policy);
2538 done:
2539 if (!NT_STATUS_IS_OK(result)) {
2540 invalidate_cm_connection(conn);
2541 return result;
2544 *cli = conn->lsa_pipe;
2545 *lsa_policy = conn->lsa_policy;
2546 return result;
2549 /****************************************************************************
2550 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2551 session key stored in conn->netlogon_pipe->dc->sess_key.
2552 ****************************************************************************/
2554 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2555 struct rpc_pipe_client **cli)
2557 struct winbindd_cm_conn *conn;
2558 NTSTATUS result;
2560 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2561 uint8 mach_pwd[16];
2562 enum netr_SchannelType sec_chan_type;
2563 const char *account_name;
2564 struct rpc_pipe_client *netlogon_pipe = NULL;
2566 *cli = NULL;
2568 result = init_dc_connection_rpc(domain);
2569 if (!NT_STATUS_IS_OK(result)) {
2570 return result;
2573 conn = &domain->conn;
2575 if (rpccli_is_connected(conn->netlogon_pipe)) {
2576 *cli = conn->netlogon_pipe;
2577 return NT_STATUS_OK;
2580 TALLOC_FREE(conn->netlogon_pipe);
2582 result = cli_rpc_pipe_open_noauth(conn->cli,
2583 &ndr_table_netlogon.syntax_id,
2584 &netlogon_pipe);
2585 if (!NT_STATUS_IS_OK(result)) {
2586 return result;
2589 if ((!IS_DC) && (!domain->primary)) {
2590 /* Clear the schannel request bit and drop down */
2591 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2592 goto no_schannel;
2595 if (lp_client_schannel() != False) {
2596 neg_flags |= NETLOGON_NEG_SCHANNEL;
2599 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2600 &sec_chan_type))
2602 TALLOC_FREE(netlogon_pipe);
2603 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2606 result = rpccli_netlogon_setup_creds(
2607 netlogon_pipe,
2608 domain->dcname, /* server name. */
2609 domain->name, /* domain name */
2610 global_myname(), /* client name */
2611 account_name, /* machine account */
2612 mach_pwd, /* machine password */
2613 sec_chan_type, /* from get_trust_pw */
2614 &neg_flags);
2616 if (!NT_STATUS_IS_OK(result)) {
2617 TALLOC_FREE(netlogon_pipe);
2618 return result;
2621 if ((lp_client_schannel() == True) &&
2622 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2623 DEBUG(3, ("Server did not offer schannel\n"));
2624 TALLOC_FREE(netlogon_pipe);
2625 return NT_STATUS_ACCESS_DENIED;
2628 no_schannel:
2629 if ((lp_client_schannel() == False) ||
2630 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2632 * NetSamLogonEx only works for schannel
2634 domain->can_do_samlogon_ex = False;
2636 /* We're done - just keep the existing connection to NETLOGON
2637 * open */
2638 conn->netlogon_pipe = netlogon_pipe;
2639 *cli = conn->netlogon_pipe;
2640 return NT_STATUS_OK;
2643 /* Using the credentials from the first pipe, open a signed and sealed
2644 second netlogon pipe. The session key is stored in the schannel
2645 part of the new pipe auth struct.
2648 result = cli_rpc_pipe_open_schannel_with_key(
2649 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2650 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2651 &conn->netlogon_pipe);
2653 /* We can now close the initial netlogon pipe. */
2654 TALLOC_FREE(netlogon_pipe);
2656 if (!NT_STATUS_IS_OK(result)) {
2657 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2658 "was %s\n", nt_errstr(result)));
2660 invalidate_cm_connection(conn);
2661 return result;
2665 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2666 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2667 * supported). We used to only try SamLogonEx for AD, but
2668 * Samba DCs can also do it. And because we don't distinguish
2669 * between Samba and NT4, always try it once.
2671 domain->can_do_samlogon_ex = true;
2673 *cli = conn->netlogon_pipe;
2674 return NT_STATUS_OK;
2677 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2678 void *private_data,
2679 uint32_t msg_type,
2680 struct server_id server_id,
2681 DATA_BLOB *data)
2683 struct winbindd_domain *domain;
2684 char *freeit = NULL;
2685 char *addr;
2687 if ((data == NULL)
2688 || (data->data == NULL)
2689 || (data->length == 0)
2690 || (data->data[data->length-1] != '\0')) {
2691 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2692 "string\n"));
2693 return;
2696 addr = (char *)data->data;
2697 DEBUG(10, ("IP %s dropped\n", addr));
2699 if (!is_ipaddress(addr)) {
2700 char *slash;
2702 * Some code sends us ip addresses with the /netmask
2703 * suffix
2705 slash = strchr(addr, '/');
2706 if (slash == NULL) {
2707 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2708 addr));
2709 return;
2711 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2712 if (freeit == NULL) {
2713 DEBUG(1, ("talloc failed\n"));
2714 return;
2716 addr = freeit;
2717 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2720 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2721 char sockaddr[INET6_ADDRSTRLEN];
2722 if (domain->conn.cli == NULL) {
2723 continue;
2725 if (domain->conn.cli->fd == -1) {
2726 continue;
2728 client_socket_addr(domain->conn.cli->fd, sockaddr,
2729 sizeof(sockaddr));
2730 if (strequal(sockaddr, addr)) {
2731 close(domain->conn.cli->fd);
2732 domain->conn.cli->fd = -1;
2735 TALLOC_FREE(freeit);