s3: Fix Coverity ID 2173: FORWARD_NULL
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob302df1e22d41e066343da33338912185a69db32d
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 HAVE_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 = NULL;
1435 char *value = NULL;
1437 if (cli == NULL) {
1438 return;
1440 if (cli->fd == -1) {
1441 return;
1443 get_peer_addr(cli->fd, addr, sizeof(addr));
1445 key = current_dc_key(talloc_tos(), domain_name);
1446 if (key == NULL) {
1447 goto done;
1450 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1451 if (value == NULL) {
1452 goto done;
1455 gencache_set(key, value, 0x7fffffff);
1456 done:
1457 TALLOC_FREE(value);
1458 TALLOC_FREE(key);
1461 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1462 const char *domain_name,
1463 char **p_dc_name, char **p_dc_ip)
1465 char *key, *value, *p;
1466 bool ret = false;
1467 char *dc_name = NULL;
1468 char *dc_ip = NULL;
1470 key = current_dc_key(talloc_tos(), domain_name);
1471 if (key == NULL) {
1472 goto done;
1474 if (!gencache_get(key, &value, NULL)) {
1475 goto done;
1477 p = strchr(value, ' ');
1478 if (p == NULL) {
1479 goto done;
1481 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1482 if (dc_ip == NULL) {
1483 goto done;
1485 dc_name = talloc_strdup(mem_ctx, p+1);
1486 if (dc_name == NULL) {
1487 goto done;
1490 if (p_dc_ip != NULL) {
1491 *p_dc_ip = dc_ip;
1492 dc_ip = NULL;
1494 if (p_dc_name != NULL) {
1495 *p_dc_name = dc_name;
1496 dc_name = NULL;
1498 ret = true;
1499 done:
1500 TALLOC_FREE(dc_name);
1501 TALLOC_FREE(dc_ip);
1502 TALLOC_FREE(key);
1503 return ret;
1506 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1507 struct winbindd_cm_conn *new_conn)
1509 TALLOC_CTX *mem_ctx;
1510 NTSTATUS result;
1511 char *saf_servername = saf_fetch( domain->name );
1512 int retries;
1514 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1515 SAFE_FREE(saf_servername);
1516 set_domain_offline(domain);
1517 return NT_STATUS_NO_MEMORY;
1520 /* we have to check the server affinity cache here since
1521 later we select a DC based on response time and not preference */
1523 /* Check the negative connection cache
1524 before talking to it. It going down may have
1525 triggered the reconnection. */
1527 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1529 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1530 saf_servername, domain->name ));
1532 /* convert an ip address to a name */
1533 if (is_ipaddress( saf_servername ) ) {
1534 fstring saf_name;
1535 struct sockaddr_storage ss;
1537 if (!interpret_string_addr(&ss, saf_servername,
1538 AI_NUMERICHOST)) {
1539 return NT_STATUS_UNSUCCESSFUL;
1541 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1542 fstrcpy( domain->dcname, saf_name );
1543 } else {
1544 winbind_add_failed_connection_entry(
1545 domain, saf_servername,
1546 NT_STATUS_UNSUCCESSFUL);
1548 } else {
1549 fstrcpy( domain->dcname, saf_servername );
1552 SAFE_FREE( saf_servername );
1555 for (retries = 0; retries < 3; retries++) {
1556 int fd = -1;
1557 bool retry = False;
1559 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1561 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1562 domain->dcname, domain->name ));
1564 if (*domain->dcname
1565 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1566 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1568 NTSTATUS status;
1570 status = smbsock_connect(&domain->dcaddr, 0,
1571 NULL, -1, NULL, -1,
1572 &fd, NULL);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 fd = -1;
1578 if ((fd == -1)
1579 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1581 /* This is the one place where we will
1582 set the global winbindd offline state
1583 to true, if a "WINBINDD_OFFLINE" entry
1584 is found in the winbindd cache. */
1585 set_global_winbindd_state_offline();
1586 break;
1589 new_conn->cli = NULL;
1591 result = cm_prepare_connection(domain, fd, domain->dcname,
1592 &new_conn->cli, &retry);
1594 if (!retry)
1595 break;
1598 if (NT_STATUS_IS_OK(result)) {
1600 winbindd_set_locator_kdc_envs(domain);
1602 if (domain->online == False) {
1603 /* We're changing state from offline to online. */
1604 set_global_winbindd_state_online();
1606 set_domain_online(domain);
1609 * Much as I hate global state, this seems to be the point
1610 * where we can be certain that we have a proper connection to
1611 * a DC. wbinfo --dc-info needs that information, store it in
1612 * gencache with a looong timeout. This will need revisiting
1613 * once we start to connect to multiple DCs, wbcDcInfo is
1614 * already prepared for that.
1616 store_current_dc_in_gencache(domain->name, domain->dcname,
1617 new_conn->cli);
1618 } else {
1619 /* Ensure we setup the retry handler. */
1620 set_domain_offline(domain);
1623 talloc_destroy(mem_ctx);
1624 return result;
1627 /* Close down all open pipes on a connection. */
1629 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1631 NTSTATUS result;
1633 /* We're closing down a possibly dead
1634 connection. Don't have impossibly long (10s) timeouts. */
1636 if (conn->cli) {
1637 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1640 if (conn->samr_pipe != NULL) {
1641 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1642 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1643 talloc_tos(),
1644 &conn->sam_connect_handle,
1645 &result);
1647 TALLOC_FREE(conn->samr_pipe);
1648 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1649 if (conn->cli) {
1650 cli_set_timeout(conn->cli, 500);
1654 if (conn->lsa_pipe != NULL) {
1655 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1656 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1657 talloc_tos(),
1658 &conn->lsa_policy,
1659 &result);
1661 TALLOC_FREE(conn->lsa_pipe);
1662 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1663 if (conn->cli) {
1664 cli_set_timeout(conn->cli, 500);
1668 if (conn->lsa_pipe_tcp != NULL) {
1669 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1670 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1671 talloc_tos(),
1672 &conn->lsa_policy,
1673 &result);
1675 TALLOC_FREE(conn->lsa_pipe_tcp);
1676 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1677 if (conn->cli) {
1678 cli_set_timeout(conn->cli, 500);
1682 if (conn->netlogon_pipe != NULL) {
1683 TALLOC_FREE(conn->netlogon_pipe);
1684 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1685 if (conn->cli) {
1686 cli_set_timeout(conn->cli, 500);
1690 if (conn->cli) {
1691 cli_shutdown(conn->cli);
1694 conn->cli = NULL;
1697 void close_conns_after_fork(void)
1699 struct winbindd_domain *domain;
1701 for (domain = domain_list(); domain; domain = domain->next) {
1702 struct cli_state *cli = domain->conn.cli;
1705 * first close the low level SMB TCP connection
1706 * so that we don't generate any SMBclose
1707 * requests in invalidate_cm_connection()
1709 if (cli && cli->fd != -1) {
1710 close(domain->conn.cli->fd);
1711 domain->conn.cli->fd = -1;
1714 invalidate_cm_connection(&domain->conn);
1718 static bool connection_ok(struct winbindd_domain *domain)
1720 bool ok;
1722 ok = cli_state_is_connected(domain->conn.cli);
1723 if (!ok) {
1724 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1725 domain->dcname, domain->name));
1726 return False;
1729 if (domain->online == False) {
1730 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1731 return False;
1734 return True;
1737 /* Initialize a new connection up to the RPC BIND.
1738 Bypass online status check so always does network calls. */
1740 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1742 NTSTATUS result;
1744 /* Internal connections never use the network. */
1745 if (domain->internal) {
1746 domain->initialized = True;
1747 return NT_STATUS_OK;
1750 if (!winbindd_can_contact_domain(domain)) {
1751 invalidate_cm_connection(&domain->conn);
1752 domain->initialized = True;
1753 return NT_STATUS_OK;
1756 if (connection_ok(domain)) {
1757 if (!domain->initialized) {
1758 set_dc_type_and_flags(domain);
1760 return NT_STATUS_OK;
1763 invalidate_cm_connection(&domain->conn);
1765 result = cm_open_connection(domain, &domain->conn);
1767 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1768 set_dc_type_and_flags(domain);
1771 return result;
1774 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1776 if (domain->internal) {
1777 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1780 if (domain->initialized && !domain->online) {
1781 /* We check for online status elsewhere. */
1782 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1785 return init_dc_connection_network(domain);
1788 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1790 NTSTATUS status;
1792 status = init_dc_connection(domain);
1793 if (!NT_STATUS_IS_OK(status)) {
1794 return status;
1797 if (!domain->internal && domain->conn.cli == NULL) {
1798 /* happens for trusted domains without inbound trust */
1799 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1802 return NT_STATUS_OK;
1805 /******************************************************************************
1806 Set the trust flags (direction and forest location) for a domain
1807 ******************************************************************************/
1809 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1811 struct winbindd_domain *our_domain;
1812 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1813 WERROR werr;
1814 struct netr_DomainTrustList trusts;
1815 int i;
1816 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1817 NETR_TRUST_FLAG_OUTBOUND |
1818 NETR_TRUST_FLAG_INBOUND);
1819 struct rpc_pipe_client *cli;
1820 TALLOC_CTX *mem_ctx = NULL;
1821 struct dcerpc_binding_handle *b;
1823 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1825 /* Our primary domain doesn't need to worry about trust flags.
1826 Force it to go through the network setup */
1827 if ( domain->primary ) {
1828 return False;
1831 our_domain = find_our_domain();
1833 if ( !connection_ok(our_domain) ) {
1834 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1835 return False;
1838 /* This won't work unless our domain is AD */
1840 if ( !our_domain->active_directory ) {
1841 return False;
1844 /* Use DsEnumerateDomainTrusts to get us the trust direction
1845 and type */
1847 result = cm_connect_netlogon(our_domain, &cli);
1849 if (!NT_STATUS_IS_OK(result)) {
1850 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1851 "a connection to %s for PIPE_NETLOGON (%s)\n",
1852 domain->name, nt_errstr(result)));
1853 return False;
1856 b = cli->binding_handle;
1858 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1859 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1860 return False;
1863 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1864 cli->desthost,
1865 flags,
1866 &trusts,
1867 &werr);
1868 if (!NT_STATUS_IS_OK(result)) {
1869 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1870 "failed to query trusted domain list: %s\n",
1871 nt_errstr(result)));
1872 talloc_destroy(mem_ctx);
1873 return false;
1875 if (!W_ERROR_IS_OK(werr)) {
1876 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1877 "failed to query trusted domain list: %s\n",
1878 win_errstr(werr)));
1879 talloc_destroy(mem_ctx);
1880 return false;
1883 /* Now find the domain name and get the flags */
1885 for ( i=0; i<trusts.count; i++ ) {
1886 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1887 domain->domain_flags = trusts.array[i].trust_flags;
1888 domain->domain_type = trusts.array[i].trust_type;
1889 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1891 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1892 domain->active_directory = True;
1894 /* This flag is only set if the domain is *our*
1895 primary domain and the primary domain is in
1896 native mode */
1898 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1900 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1901 "native mode.\n", domain->name,
1902 domain->native_mode ? "" : "NOT "));
1904 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1905 "running active directory.\n", domain->name,
1906 domain->active_directory ? "" : "NOT "));
1909 domain->initialized = True;
1911 break;
1915 talloc_destroy( mem_ctx );
1917 return domain->initialized;
1920 /******************************************************************************
1921 We can 'sense' certain things about the DC by it's replies to certain
1922 questions.
1924 This tells us if this particular remote server is Active Directory, and if it
1925 is native mode.
1926 ******************************************************************************/
1928 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1930 NTSTATUS status, result;
1931 WERROR werr;
1932 TALLOC_CTX *mem_ctx = NULL;
1933 struct rpc_pipe_client *cli = NULL;
1934 struct policy_handle pol;
1935 union dssetup_DsRoleInfo info;
1936 union lsa_PolicyInformation *lsa_info = NULL;
1938 if (!connection_ok(domain)) {
1939 return;
1942 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1943 domain->name);
1944 if (!mem_ctx) {
1945 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1946 return;
1949 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1951 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
1952 &ndr_table_dssetup.syntax_id,
1953 &cli);
1955 if (!NT_STATUS_IS_OK(status)) {
1956 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1957 "PI_DSSETUP on domain %s: (%s)\n",
1958 domain->name, nt_errstr(status)));
1960 /* if this is just a non-AD domain we need to continue
1961 * identifying so that we can in the end return with
1962 * domain->initialized = True - gd */
1964 goto no_dssetup;
1967 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
1968 DS_ROLE_BASIC_INFORMATION,
1969 &info,
1970 &werr);
1971 TALLOC_FREE(cli);
1973 if (NT_STATUS_IS_OK(status)) {
1974 result = werror_to_ntstatus(werr);
1976 if (!NT_STATUS_IS_OK(status)) {
1977 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1978 "on domain %s failed: (%s)\n",
1979 domain->name, nt_errstr(status)));
1981 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1982 * every opcode on the DSSETUP pipe, continue with
1983 * no_dssetup mode here as well to get domain->initialized
1984 * set - gd */
1986 if (NT_STATUS_V(status) == DCERPC_FAULT_OP_RNG_ERROR) {
1987 goto no_dssetup;
1990 TALLOC_FREE(mem_ctx);
1991 return;
1994 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1995 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1996 domain->native_mode = True;
1997 } else {
1998 domain->native_mode = False;
2001 no_dssetup:
2002 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2003 &ndr_table_lsarpc.syntax_id, &cli);
2005 if (!NT_STATUS_IS_OK(status)) {
2006 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2007 "PI_LSARPC on domain %s: (%s)\n",
2008 domain->name, nt_errstr(status)));
2009 TALLOC_FREE(cli);
2010 TALLOC_FREE(mem_ctx);
2011 return;
2014 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2015 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2017 if (NT_STATUS_IS_OK(status)) {
2018 /* This particular query is exactly what Win2k clients use
2019 to determine that the DC is active directory */
2020 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2021 &pol,
2022 LSA_POLICY_INFO_DNS,
2023 &lsa_info,
2024 &result);
2027 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2028 domain->active_directory = True;
2030 if (lsa_info->dns.name.string) {
2031 fstrcpy(domain->name, lsa_info->dns.name.string);
2034 if (lsa_info->dns.dns_domain.string) {
2035 fstrcpy(domain->alt_name,
2036 lsa_info->dns.dns_domain.string);
2039 /* See if we can set some domain trust flags about
2040 ourself */
2042 if (lsa_info->dns.dns_forest.string) {
2043 fstrcpy(domain->forest_name,
2044 lsa_info->dns.dns_forest.string);
2046 if (strequal(domain->forest_name, domain->alt_name)) {
2047 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2051 if (lsa_info->dns.sid) {
2052 sid_copy(&domain->sid, lsa_info->dns.sid);
2054 } else {
2055 domain->active_directory = False;
2057 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2058 SEC_FLAG_MAXIMUM_ALLOWED,
2059 &pol);
2061 if (!NT_STATUS_IS_OK(status)) {
2062 goto done;
2065 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2066 &pol,
2067 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2068 &lsa_info,
2069 &result);
2070 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2072 if (lsa_info->account_domain.name.string) {
2073 fstrcpy(domain->name,
2074 lsa_info->account_domain.name.string);
2077 if (lsa_info->account_domain.sid) {
2078 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2082 done:
2084 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2085 domain->name, domain->native_mode ? "" : "NOT "));
2087 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2088 domain->name, domain->active_directory ? "" : "NOT "));
2090 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2091 domain->can_do_validation6 = domain->active_directory;
2093 TALLOC_FREE(cli);
2095 TALLOC_FREE(mem_ctx);
2097 domain->initialized = True;
2100 /**********************************************************************
2101 Set the domain_flags (trust attributes, domain operating modes, etc...
2102 ***********************************************************************/
2104 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2106 /* we always have to contact our primary domain */
2108 if ( domain->primary ) {
2109 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2110 "primary domain\n"));
2111 set_dc_type_and_flags_connect( domain );
2112 return;
2115 /* Use our DC to get the information if possible */
2117 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2118 /* Otherwise, fallback to contacting the
2119 domain directly */
2120 set_dc_type_and_flags_connect( domain );
2123 return;
2128 /**********************************************************************
2129 ***********************************************************************/
2131 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2132 struct netlogon_creds_CredentialState **ppdc)
2134 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2135 struct rpc_pipe_client *netlogon_pipe;
2137 if (lp_client_schannel() == False) {
2138 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2141 result = cm_connect_netlogon(domain, &netlogon_pipe);
2142 if (!NT_STATUS_IS_OK(result)) {
2143 return result;
2146 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2147 netlogon pipe. */
2149 if (!domain->conn.netlogon_pipe->dc) {
2150 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2153 *ppdc = domain->conn.netlogon_pipe->dc;
2154 return NT_STATUS_OK;
2157 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2158 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2160 struct winbindd_cm_conn *conn;
2161 NTSTATUS status, result;
2162 struct netlogon_creds_CredentialState *p_creds;
2163 char *machine_password = NULL;
2164 char *machine_account = NULL;
2165 char *domain_name = NULL;
2167 if (sid_check_is_domain(&domain->sid)) {
2168 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2171 status = init_dc_connection_rpc(domain);
2172 if (!NT_STATUS_IS_OK(status)) {
2173 return status;
2176 conn = &domain->conn;
2178 if (rpccli_is_connected(conn->samr_pipe)) {
2179 goto done;
2182 TALLOC_FREE(conn->samr_pipe);
2185 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2186 * sign and sealed pipe using the machine account password by
2187 * preference. If we can't - try schannel, if that fails, try
2188 * anonymous.
2191 if ((conn->cli->user_name[0] == '\0') ||
2192 (conn->cli->domain[0] == '\0') ||
2193 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2195 status = get_trust_creds(domain, &machine_password,
2196 &machine_account, NULL);
2197 if (!NT_STATUS_IS_OK(status)) {
2198 DEBUG(10, ("cm_connect_sam: No no user available for "
2199 "domain %s, trying schannel\n", conn->cli->domain));
2200 goto schannel;
2202 domain_name = domain->name;
2203 } else {
2204 machine_password = SMB_STRDUP(conn->cli->password);
2205 machine_account = SMB_STRDUP(conn->cli->user_name);
2206 domain_name = conn->cli->domain;
2209 if (!machine_password || !machine_account) {
2210 status = NT_STATUS_NO_MEMORY;
2211 goto done;
2214 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2215 authenticated SAMR pipe with sign & seal. */
2216 status = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2217 &ndr_table_samr.syntax_id,
2218 NCACN_NP,
2219 DCERPC_AUTH_LEVEL_PRIVACY,
2220 domain_name,
2221 machine_account,
2222 machine_password,
2223 &conn->samr_pipe);
2225 if (!NT_STATUS_IS_OK(status)) {
2226 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2227 "pipe for domain %s using NTLMSSP "
2228 "authenticated pipe: user %s\\%s. Error was "
2229 "%s\n", domain->name, domain_name,
2230 machine_account, nt_errstr(status)));
2231 goto schannel;
2234 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2235 "domain %s using NTLMSSP authenticated "
2236 "pipe: user %s\\%s\n", domain->name,
2237 domain_name, machine_account));
2239 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2240 conn->samr_pipe->desthost,
2241 SEC_FLAG_MAXIMUM_ALLOWED,
2242 &conn->sam_connect_handle,
2243 &result);
2244 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2245 goto open_domain;
2247 if (NT_STATUS_IS_OK(status)) {
2248 status = result;
2251 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2252 "failed for domain %s, error was %s. Trying schannel\n",
2253 domain->name, nt_errstr(status) ));
2254 TALLOC_FREE(conn->samr_pipe);
2256 schannel:
2258 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2260 status = cm_get_schannel_creds(domain, &p_creds);
2261 if (!NT_STATUS_IS_OK(status)) {
2262 /* If this call fails - conn->cli can now be NULL ! */
2263 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2264 "for domain %s (error %s), trying anon\n",
2265 domain->name,
2266 nt_errstr(status) ));
2267 goto anonymous;
2269 status = cli_rpc_pipe_open_schannel_with_key
2270 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2271 DCERPC_AUTH_LEVEL_PRIVACY,
2272 domain->name, &p_creds, &conn->samr_pipe);
2274 if (!NT_STATUS_IS_OK(status)) {
2275 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2276 "domain %s using schannel. Error was %s\n",
2277 domain->name, nt_errstr(status) ));
2278 goto anonymous;
2280 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2281 "schannel.\n", domain->name ));
2283 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2284 conn->samr_pipe->desthost,
2285 SEC_FLAG_MAXIMUM_ALLOWED,
2286 &conn->sam_connect_handle,
2287 &result);
2288 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2289 goto open_domain;
2291 if (NT_STATUS_IS_OK(status)) {
2292 status = result;
2294 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2295 "for domain %s, error was %s. Trying anonymous\n",
2296 domain->name, nt_errstr(status) ));
2297 TALLOC_FREE(conn->samr_pipe);
2299 anonymous:
2301 /* Finally fall back to anonymous. */
2302 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2303 &conn->samr_pipe);
2305 if (!NT_STATUS_IS_OK(status)) {
2306 goto done;
2309 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2310 conn->samr_pipe->desthost,
2311 SEC_FLAG_MAXIMUM_ALLOWED,
2312 &conn->sam_connect_handle,
2313 &result);
2314 if (!NT_STATUS_IS_OK(status)) {
2315 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2316 "for domain %s Error was %s\n",
2317 domain->name, nt_errstr(status) ));
2318 goto done;
2320 if (!NT_STATUS_IS_OK(result)) {
2321 status = result;
2322 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2323 "for domain %s Error was %s\n",
2324 domain->name, nt_errstr(result)));
2325 goto done;
2328 open_domain:
2329 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2330 mem_ctx,
2331 &conn->sam_connect_handle,
2332 SEC_FLAG_MAXIMUM_ALLOWED,
2333 &domain->sid,
2334 &conn->sam_domain_handle,
2335 &result);
2336 if (!NT_STATUS_IS_OK(status)) {
2337 goto done;
2340 status = result;
2341 done:
2343 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2345 * if we got access denied, we might just have no access rights
2346 * to talk to the remote samr server server (e.g. when we are a
2347 * PDC and we are connecting a w2k8 pdc via an interdomain
2348 * trust). In that case do not invalidate the whole connection
2349 * stack
2351 TALLOC_FREE(conn->samr_pipe);
2352 ZERO_STRUCT(conn->sam_domain_handle);
2353 return status;
2354 } else if (!NT_STATUS_IS_OK(status)) {
2355 invalidate_cm_connection(conn);
2356 return status;
2359 *cli = conn->samr_pipe;
2360 *sam_handle = conn->sam_domain_handle;
2361 SAFE_FREE(machine_password);
2362 SAFE_FREE(machine_account);
2363 return status;
2366 /**********************************************************************
2367 open an schanneld ncacn_ip_tcp connection to LSA
2368 ***********************************************************************/
2370 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2371 TALLOC_CTX *mem_ctx,
2372 struct rpc_pipe_client **cli)
2374 struct winbindd_cm_conn *conn;
2375 struct netlogon_creds_CredentialState *creds;
2376 NTSTATUS status;
2378 DEBUG(10,("cm_connect_lsa_tcp\n"));
2380 status = init_dc_connection_rpc(domain);
2381 if (!NT_STATUS_IS_OK(status)) {
2382 return status;
2385 conn = &domain->conn;
2387 if (conn->lsa_pipe_tcp &&
2388 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2389 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2390 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2391 goto done;
2394 TALLOC_FREE(conn->lsa_pipe_tcp);
2396 status = cm_get_schannel_creds(domain, &creds);
2397 if (!NT_STATUS_IS_OK(status)) {
2398 goto done;
2401 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2402 &ndr_table_lsarpc.syntax_id,
2403 NCACN_IP_TCP,
2404 DCERPC_AUTH_LEVEL_PRIVACY,
2405 domain->name,
2406 &creds,
2407 &conn->lsa_pipe_tcp);
2408 if (!NT_STATUS_IS_OK(status)) {
2409 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2410 nt_errstr(status)));
2411 goto done;
2414 done:
2415 if (!NT_STATUS_IS_OK(status)) {
2416 TALLOC_FREE(conn->lsa_pipe_tcp);
2417 return status;
2420 *cli = conn->lsa_pipe_tcp;
2422 return status;
2425 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2426 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2428 struct winbindd_cm_conn *conn;
2429 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2430 struct netlogon_creds_CredentialState *p_creds;
2432 result = init_dc_connection_rpc(domain);
2433 if (!NT_STATUS_IS_OK(result))
2434 return result;
2436 conn = &domain->conn;
2438 if (rpccli_is_connected(conn->lsa_pipe)) {
2439 goto done;
2442 TALLOC_FREE(conn->lsa_pipe);
2444 if ((conn->cli->user_name[0] == '\0') ||
2445 (conn->cli->domain[0] == '\0') ||
2446 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2447 DEBUG(10, ("cm_connect_lsa: No no user available for "
2448 "domain %s, trying schannel\n", conn->cli->domain));
2449 goto schannel;
2452 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2453 * authenticated LSA pipe with sign & seal. */
2454 result = cli_rpc_pipe_open_spnego_ntlmssp
2455 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2456 DCERPC_AUTH_LEVEL_PRIVACY,
2457 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2458 &conn->lsa_pipe);
2460 if (!NT_STATUS_IS_OK(result)) {
2461 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2462 "domain %s using NTLMSSP authenticated pipe: user "
2463 "%s\\%s. Error was %s. Trying schannel.\n",
2464 domain->name, conn->cli->domain,
2465 conn->cli->user_name, nt_errstr(result)));
2466 goto schannel;
2469 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2470 "NTLMSSP authenticated pipe: user %s\\%s\n",
2471 domain->name, conn->cli->domain, conn->cli->user_name ));
2473 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2474 SEC_FLAG_MAXIMUM_ALLOWED,
2475 &conn->lsa_policy);
2476 if (NT_STATUS_IS_OK(result)) {
2477 goto done;
2480 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2481 "schannel\n"));
2483 TALLOC_FREE(conn->lsa_pipe);
2485 schannel:
2487 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2489 result = cm_get_schannel_creds(domain, &p_creds);
2490 if (!NT_STATUS_IS_OK(result)) {
2491 /* If this call fails - conn->cli can now be NULL ! */
2492 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2493 "for domain %s (error %s), trying anon\n",
2494 domain->name,
2495 nt_errstr(result) ));
2496 goto anonymous;
2498 result = cli_rpc_pipe_open_schannel_with_key
2499 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2500 DCERPC_AUTH_LEVEL_PRIVACY,
2501 domain->name, &p_creds, &conn->lsa_pipe);
2503 if (!NT_STATUS_IS_OK(result)) {
2504 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2505 "domain %s using schannel. Error was %s\n",
2506 domain->name, nt_errstr(result) ));
2507 goto anonymous;
2509 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2510 "schannel.\n", domain->name ));
2512 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2513 SEC_FLAG_MAXIMUM_ALLOWED,
2514 &conn->lsa_policy);
2515 if (NT_STATUS_IS_OK(result)) {
2516 goto done;
2519 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2520 "anonymous\n"));
2522 TALLOC_FREE(conn->lsa_pipe);
2524 anonymous:
2526 result = cli_rpc_pipe_open_noauth(conn->cli,
2527 &ndr_table_lsarpc.syntax_id,
2528 &conn->lsa_pipe);
2529 if (!NT_STATUS_IS_OK(result)) {
2530 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2531 goto done;
2534 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2535 SEC_FLAG_MAXIMUM_ALLOWED,
2536 &conn->lsa_policy);
2537 done:
2538 if (!NT_STATUS_IS_OK(result)) {
2539 invalidate_cm_connection(conn);
2540 return result;
2543 *cli = conn->lsa_pipe;
2544 *lsa_policy = conn->lsa_policy;
2545 return result;
2548 /****************************************************************************
2549 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2550 session key stored in conn->netlogon_pipe->dc->sess_key.
2551 ****************************************************************************/
2553 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2554 struct rpc_pipe_client **cli)
2556 struct winbindd_cm_conn *conn;
2557 NTSTATUS result;
2559 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2560 uint8 mach_pwd[16];
2561 enum netr_SchannelType sec_chan_type;
2562 const char *account_name;
2563 struct rpc_pipe_client *netlogon_pipe = NULL;
2565 *cli = NULL;
2567 result = init_dc_connection_rpc(domain);
2568 if (!NT_STATUS_IS_OK(result)) {
2569 return result;
2572 conn = &domain->conn;
2574 if (rpccli_is_connected(conn->netlogon_pipe)) {
2575 *cli = conn->netlogon_pipe;
2576 return NT_STATUS_OK;
2579 TALLOC_FREE(conn->netlogon_pipe);
2581 result = cli_rpc_pipe_open_noauth(conn->cli,
2582 &ndr_table_netlogon.syntax_id,
2583 &netlogon_pipe);
2584 if (!NT_STATUS_IS_OK(result)) {
2585 return result;
2588 if ((!IS_DC) && (!domain->primary)) {
2589 /* Clear the schannel request bit and drop down */
2590 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2591 goto no_schannel;
2594 if (lp_client_schannel() != False) {
2595 neg_flags |= NETLOGON_NEG_SCHANNEL;
2598 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2599 &sec_chan_type))
2601 TALLOC_FREE(netlogon_pipe);
2602 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2605 result = rpccli_netlogon_setup_creds(
2606 netlogon_pipe,
2607 domain->dcname, /* server name. */
2608 domain->name, /* domain name */
2609 global_myname(), /* client name */
2610 account_name, /* machine account */
2611 mach_pwd, /* machine password */
2612 sec_chan_type, /* from get_trust_pw */
2613 &neg_flags);
2615 if (!NT_STATUS_IS_OK(result)) {
2616 TALLOC_FREE(netlogon_pipe);
2617 return result;
2620 if ((lp_client_schannel() == True) &&
2621 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2622 DEBUG(3, ("Server did not offer schannel\n"));
2623 TALLOC_FREE(netlogon_pipe);
2624 return NT_STATUS_ACCESS_DENIED;
2627 no_schannel:
2628 if ((lp_client_schannel() == False) ||
2629 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2631 * NetSamLogonEx only works for schannel
2633 domain->can_do_samlogon_ex = False;
2635 /* We're done - just keep the existing connection to NETLOGON
2636 * open */
2637 conn->netlogon_pipe = netlogon_pipe;
2638 *cli = conn->netlogon_pipe;
2639 return NT_STATUS_OK;
2642 /* Using the credentials from the first pipe, open a signed and sealed
2643 second netlogon pipe. The session key is stored in the schannel
2644 part of the new pipe auth struct.
2647 result = cli_rpc_pipe_open_schannel_with_key(
2648 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2649 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2650 &conn->netlogon_pipe);
2652 /* We can now close the initial netlogon pipe. */
2653 TALLOC_FREE(netlogon_pipe);
2655 if (!NT_STATUS_IS_OK(result)) {
2656 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2657 "was %s\n", nt_errstr(result)));
2659 invalidate_cm_connection(conn);
2660 return result;
2664 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2665 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2666 * supported). We used to only try SamLogonEx for AD, but
2667 * Samba DCs can also do it. And because we don't distinguish
2668 * between Samba and NT4, always try it once.
2670 domain->can_do_samlogon_ex = true;
2672 *cli = conn->netlogon_pipe;
2673 return NT_STATUS_OK;
2676 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2677 void *private_data,
2678 uint32_t msg_type,
2679 struct server_id server_id,
2680 DATA_BLOB *data)
2682 struct winbindd_domain *domain;
2683 char *freeit = NULL;
2684 char *addr;
2686 if ((data == NULL)
2687 || (data->data == NULL)
2688 || (data->length == 0)
2689 || (data->data[data->length-1] != '\0')) {
2690 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2691 "string\n"));
2692 return;
2695 addr = (char *)data->data;
2696 DEBUG(10, ("IP %s dropped\n", addr));
2698 if (!is_ipaddress(addr)) {
2699 char *slash;
2701 * Some code sends us ip addresses with the /netmask
2702 * suffix
2704 slash = strchr(addr, '/');
2705 if (slash == NULL) {
2706 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2707 addr));
2708 return;
2710 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2711 if (freeit == NULL) {
2712 DEBUG(1, ("talloc failed\n"));
2713 return;
2715 addr = freeit;
2716 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2719 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2720 char sockaddr[INET6_ADDRSTRLEN];
2721 if (domain->conn.cli == NULL) {
2722 continue;
2724 if (domain->conn.cli->fd == -1) {
2725 continue;
2727 client_socket_addr(domain->conn.cli->fd, sockaddr,
2728 sizeof(sockaddr));
2729 if (strequal(sockaddr, addr)) {
2730 close(domain->conn.cli->fd);
2731 domain->conn.cli->fd = -1;
2734 TALLOC_FREE(freeit);