s3: Close the winbind client fds after forking
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob06d954fe9522aa249685f798a6bc68d0afba441d
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
34 selection etc
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
46 implementation. -tpot
51 TODO:
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
57 various sam handles.
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "libsmb/clidgram.h"
73 #include "ads.h"
74 #include "secrets.h"
75 #include "../libcli/security/security.h"
76 #include "passdb.h"
77 #include "messages.h"
78 #include "ntdomain.h"
80 #undef DBGC_CLASS
81 #define DBGC_CLASS DBGC_WINBIND
83 struct dc_name_ip {
84 fstring name;
85 struct sockaddr_storage ss;
88 extern struct winbindd_methods reconnect_methods;
89 extern bool override_logfile;
91 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
92 static void set_dc_type_and_flags( struct winbindd_domain *domain );
93 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
94 struct dc_name_ip **dcs, int *num_dcs);
96 /****************************************************************
97 Child failed to find DC's. Reschedule check.
98 ****************************************************************/
100 static void msg_failed_to_go_online(struct messaging_context *msg,
101 void *private_data,
102 uint32_t msg_type,
103 struct server_id server_id,
104 DATA_BLOB *data)
106 struct winbindd_domain *domain;
107 const char *domainname = (const char *)data->data;
109 if (data->data == NULL || data->length == 0) {
110 return;
113 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
115 for (domain = domain_list(); domain; domain = domain->next) {
116 if (domain->internal) {
117 continue;
120 if (strequal(domain->name, domainname)) {
121 if (domain->online) {
122 /* We're already online, ignore. */
123 DEBUG(5,("msg_fail_to_go_online: domain %s "
124 "already online.\n", domainname));
125 continue;
128 /* Reschedule the online check. */
129 set_domain_offline(domain);
130 break;
135 /****************************************************************
136 Actually cause a reconnect from a message.
137 ****************************************************************/
139 static void msg_try_to_go_online(struct messaging_context *msg,
140 void *private_data,
141 uint32_t msg_type,
142 struct server_id server_id,
143 DATA_BLOB *data)
145 struct winbindd_domain *domain;
146 const char *domainname = (const char *)data->data;
148 if (data->data == NULL || data->length == 0) {
149 return;
152 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
154 for (domain = domain_list(); domain; domain = domain->next) {
155 if (domain->internal) {
156 continue;
159 if (strequal(domain->name, domainname)) {
161 if (domain->online) {
162 /* We're already online, ignore. */
163 DEBUG(5,("msg_try_to_go_online: domain %s "
164 "already online.\n", domainname));
165 continue;
168 /* This call takes care of setting the online
169 flag to true if we connected, or re-adding
170 the offline handler if false. Bypasses online
171 check so always does network calls. */
173 init_dc_connection_network(domain);
174 break;
179 /****************************************************************
180 Fork a child to try and contact a DC. Do this as contacting a
181 DC requires blocking lookups and we don't want to block our
182 parent.
183 ****************************************************************/
185 static bool fork_child_dc_connect(struct winbindd_domain *domain)
187 struct dc_name_ip *dcs = NULL;
188 int num_dcs = 0;
189 TALLOC_CTX *mem_ctx = NULL;
190 pid_t parent_pid = sys_getpid();
191 char *lfile = NULL;
193 if (domain->dc_probe_pid != (pid_t)-1) {
195 * We might already have a DC probe
196 * child working, check.
198 if (process_exists_by_pid(domain->dc_probe_pid)) {
199 DEBUG(10,("fork_child_dc_connect: pid %u already "
200 "checking for DC's.\n",
201 (unsigned int)domain->dc_probe_pid));
202 return true;
204 domain->dc_probe_pid = (pid_t)-1;
207 domain->dc_probe_pid = sys_fork();
209 if (domain->dc_probe_pid == (pid_t)-1) {
210 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
211 return False;
214 if (domain->dc_probe_pid != (pid_t)0) {
215 /* Parent */
216 messaging_register(winbind_messaging_context(), NULL,
217 MSG_WINBIND_TRY_TO_GO_ONLINE,
218 msg_try_to_go_online);
219 messaging_register(winbind_messaging_context(), NULL,
220 MSG_WINBIND_FAILED_TO_GO_ONLINE,
221 msg_failed_to_go_online);
222 return True;
225 /* Child. */
227 /* Leave messages blocked - we will never process one. */
229 if (!override_logfile) {
230 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
231 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
232 _exit(1);
236 if (!winbindd_reinit_after_fork(lfile)) {
237 messaging_send_buf(winbind_messaging_context(),
238 pid_to_procid(parent_pid),
239 MSG_WINBIND_FAILED_TO_GO_ONLINE,
240 (uint8 *)domain->name,
241 strlen(domain->name)+1);
242 _exit(1);
244 SAFE_FREE(lfile);
246 mem_ctx = talloc_init("fork_child_dc_connect");
247 if (!mem_ctx) {
248 DEBUG(0,("talloc_init failed.\n"));
249 messaging_send_buf(winbind_messaging_context(),
250 pid_to_procid(parent_pid),
251 MSG_WINBIND_FAILED_TO_GO_ONLINE,
252 (uint8 *)domain->name,
253 strlen(domain->name)+1);
254 _exit(1);
257 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
258 /* Still offline ? Can't find DC's. */
259 messaging_send_buf(winbind_messaging_context(),
260 pid_to_procid(parent_pid),
261 MSG_WINBIND_FAILED_TO_GO_ONLINE,
262 (uint8 *)domain->name,
263 strlen(domain->name)+1);
264 _exit(0);
267 /* We got a DC. Send a message to our parent to get it to
268 try and do the same. */
270 messaging_send_buf(winbind_messaging_context(),
271 pid_to_procid(parent_pid),
272 MSG_WINBIND_TRY_TO_GO_ONLINE,
273 (uint8 *)domain->name,
274 strlen(domain->name)+1);
275 _exit(0);
278 /****************************************************************
279 Handler triggered if we're offline to try and detect a DC.
280 ****************************************************************/
282 static void check_domain_online_handler(struct event_context *ctx,
283 struct timed_event *te,
284 struct timeval now,
285 void *private_data)
287 struct winbindd_domain *domain =
288 (struct winbindd_domain *)private_data;
290 DEBUG(10,("check_domain_online_handler: called for domain "
291 "%s (online = %s)\n", domain->name,
292 domain->online ? "True" : "False" ));
294 TALLOC_FREE(domain->check_online_event);
296 /* Are we still in "startup" mode ? */
298 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
299 /* No longer in "startup" mode. */
300 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
301 domain->name ));
302 domain->startup = False;
305 /* We've been told to stay offline, so stay
306 that way. */
308 if (get_global_winbindd_state_offline()) {
309 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
310 domain->name ));
311 return;
314 /* Fork a child to test if it can contact a DC.
315 If it can then send ourselves a message to
316 cause a reconnect. */
318 fork_child_dc_connect(domain);
321 /****************************************************************
322 If we're still offline setup the timeout check.
323 ****************************************************************/
325 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
327 int wbr = lp_winbind_reconnect_delay();
329 if (domain->startup) {
330 domain->check_online_timeout = 10;
331 } else if (domain->check_online_timeout < wbr) {
332 domain->check_online_timeout = wbr;
336 /****************************************************************
337 Set domain offline and also add handler to put us back online
338 if we detect a DC.
339 ****************************************************************/
341 void set_domain_offline(struct winbindd_domain *domain)
343 DEBUG(10,("set_domain_offline: called for domain %s\n",
344 domain->name ));
346 TALLOC_FREE(domain->check_online_event);
348 if (domain->internal) {
349 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
350 domain->name ));
351 return;
354 domain->online = False;
356 /* Offline domains are always initialized. They're
357 re-initialized when they go back online. */
359 domain->initialized = True;
361 /* We only add the timeout handler that checks and
362 allows us to go back online when we've not
363 been told to remain offline. */
365 if (get_global_winbindd_state_offline()) {
366 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
367 domain->name ));
368 return;
371 /* If we're in startup mode, check again in 10 seconds, not in
372 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
374 calc_new_online_timeout_check(domain);
376 domain->check_online_event = event_add_timed(winbind_event_context(),
377 NULL,
378 timeval_current_ofs(domain->check_online_timeout,0),
379 check_domain_online_handler,
380 domain);
382 /* The above *has* to succeed for winbindd to work. */
383 if (!domain->check_online_event) {
384 smb_panic("set_domain_offline: failed to add online handler");
387 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
388 domain->name ));
390 /* Send an offline message to the idmap child when our
391 primary domain goes offline */
393 if ( domain->primary ) {
394 struct winbindd_child *idmap = idmap_child();
396 if ( idmap->pid != 0 ) {
397 messaging_send_buf(winbind_messaging_context(),
398 pid_to_procid(idmap->pid),
399 MSG_WINBIND_OFFLINE,
400 (uint8 *)domain->name,
401 strlen(domain->name)+1);
405 return;
408 /****************************************************************
409 Set domain online - if allowed.
410 ****************************************************************/
412 static void set_domain_online(struct winbindd_domain *domain)
414 DEBUG(10,("set_domain_online: called for domain %s\n",
415 domain->name ));
417 if (domain->internal) {
418 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
419 domain->name ));
420 return;
423 if (get_global_winbindd_state_offline()) {
424 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
425 domain->name ));
426 return;
429 winbindd_set_locator_kdc_envs(domain);
431 /* If we are waiting to get a krb5 ticket, trigger immediately. */
432 ccache_regain_all_now();
434 /* Ok, we're out of any startup mode now... */
435 domain->startup = False;
437 if (domain->online == False) {
438 /* We were offline - now we're online. We default to
439 using the MS-RPC backend if we started offline,
440 and if we're going online for the first time we
441 should really re-initialize the backends and the
442 checks to see if we're talking to an AD or NT domain.
445 domain->initialized = False;
447 /* 'reconnect_methods' is the MS-RPC backend. */
448 if (domain->backend == &reconnect_methods) {
449 domain->backend = NULL;
453 /* Ensure we have no online timeout checks. */
454 domain->check_online_timeout = 0;
455 TALLOC_FREE(domain->check_online_event);
457 /* Ensure we ignore any pending child messages. */
458 messaging_deregister(winbind_messaging_context(),
459 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
460 messaging_deregister(winbind_messaging_context(),
461 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
463 domain->online = True;
465 /* Send an online message to the idmap child when our
466 primary domain comes online */
468 if ( domain->primary ) {
469 struct winbindd_child *idmap = idmap_child();
471 if ( idmap->pid != 0 ) {
472 messaging_send_buf(winbind_messaging_context(),
473 pid_to_procid(idmap->pid),
474 MSG_WINBIND_ONLINE,
475 (uint8 *)domain->name,
476 strlen(domain->name)+1);
480 return;
483 /****************************************************************
484 Requested to set a domain online.
485 ****************************************************************/
487 void set_domain_online_request(struct winbindd_domain *domain)
489 struct timeval tev;
491 DEBUG(10,("set_domain_online_request: called for domain %s\n",
492 domain->name ));
494 if (get_global_winbindd_state_offline()) {
495 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
496 domain->name ));
497 return;
500 if (domain->internal) {
501 DEBUG(10, ("set_domain_online_request: Internal domains are "
502 "always online\n"));
503 return;
506 /* We've been told it's safe to go online and
507 try and connect to a DC. But I don't believe it
508 because network manager seems to lie.
509 Wait at least 5 seconds. Heuristics suck... */
512 GetTimeOfDay(&tev);
514 /* Go into "startup" mode again. */
515 domain->startup_time = time_mono(NULL);
516 domain->startup = True;
518 tev.tv_sec += 5;
520 if (!domain->check_online_event) {
521 /* If we've come from being globally offline we
522 don't have a check online event handler set.
523 We need to add one now we're trying to go
524 back online. */
526 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
527 domain->name ));
530 TALLOC_FREE(domain->check_online_event);
532 domain->check_online_event = event_add_timed(winbind_event_context(),
533 NULL,
534 tev,
535 check_domain_online_handler,
536 domain);
538 /* The above *has* to succeed for winbindd to work. */
539 if (!domain->check_online_event) {
540 smb_panic("set_domain_online_request: failed to add online handler");
544 /****************************************************************
545 Add -ve connection cache entries for domain and realm.
546 ****************************************************************/
548 static void winbind_add_failed_connection_entry(
549 const struct winbindd_domain *domain,
550 const char *server,
551 NTSTATUS result)
553 add_failed_connection_entry(domain->name, server, result);
554 /* If this was the saf name for the last thing we talked to,
555 remove it. */
556 saf_delete(domain->name);
557 if (*domain->alt_name) {
558 add_failed_connection_entry(domain->alt_name, server, result);
559 saf_delete(domain->alt_name);
561 winbindd_unset_locator_kdc_env(domain);
564 /* Choose between anonymous or authenticated connections. We need to use
565 an authenticated connection if DCs have the RestrictAnonymous registry
566 entry set > 0, or the "Additional restrictions for anonymous
567 connections" set in the win2k Local Security Policy.
569 Caller to free() result in domain, username, password
572 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
574 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
575 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
576 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
578 if (*username && **username) {
580 if (!*domain || !**domain)
581 *domain = smb_xstrdup(lp_workgroup());
583 if (!*password || !**password)
584 *password = smb_xstrdup("");
586 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
587 *domain, *username));
589 } else {
590 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
591 *username = smb_xstrdup("");
592 *domain = smb_xstrdup("");
593 *password = smb_xstrdup("");
597 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
598 fstring dcname,
599 struct sockaddr_storage *dc_ss)
601 struct winbindd_domain *our_domain = NULL;
602 struct rpc_pipe_client *netlogon_pipe = NULL;
603 NTSTATUS result;
604 WERROR werr;
605 TALLOC_CTX *mem_ctx;
606 unsigned int orig_timeout;
607 const char *tmp = NULL;
608 const char *p;
609 struct dcerpc_binding_handle *b;
611 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
612 * moment.... */
614 if (IS_DC) {
615 return False;
618 if (domain->primary) {
619 return False;
622 our_domain = find_our_domain();
624 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
625 return False;
628 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
629 if (!NT_STATUS_IS_OK(result)) {
630 talloc_destroy(mem_ctx);
631 return False;
634 b = netlogon_pipe->binding_handle;
636 /* This call can take a long time - allow the server to time out.
637 35 seconds should do it. */
639 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
641 if (our_domain->active_directory) {
642 struct netr_DsRGetDCNameInfo *domain_info = NULL;
644 result = dcerpc_netr_DsRGetDCName(b,
645 mem_ctx,
646 our_domain->dcname,
647 domain->name,
648 NULL,
649 NULL,
650 DS_RETURN_DNS_NAME,
651 &domain_info,
652 &werr);
653 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
654 tmp = talloc_strdup(
655 mem_ctx, domain_info->dc_unc);
656 if (tmp == NULL) {
657 DEBUG(0, ("talloc_strdup failed\n"));
658 talloc_destroy(mem_ctx);
659 return false;
661 if (strlen(domain->alt_name) == 0) {
662 fstrcpy(domain->alt_name,
663 domain_info->domain_name);
665 if (strlen(domain->forest_name) == 0) {
666 fstrcpy(domain->forest_name,
667 domain_info->forest_name);
670 } else {
671 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
672 our_domain->dcname,
673 domain->name,
674 &tmp,
675 &werr);
678 /* And restore our original timeout. */
679 rpccli_set_timeout(netlogon_pipe, orig_timeout);
681 if (!NT_STATUS_IS_OK(result)) {
682 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
683 nt_errstr(result)));
684 talloc_destroy(mem_ctx);
685 return false;
688 if (!W_ERROR_IS_OK(werr)) {
689 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
690 win_errstr(werr)));
691 talloc_destroy(mem_ctx);
692 return false;
695 /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
696 p = strip_hostname(tmp);
698 fstrcpy(dcname, p);
700 talloc_destroy(mem_ctx);
702 DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
704 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
705 return False;
708 return True;
712 * Helper function to assemble trust password and account name
714 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
715 char **machine_password,
716 char **machine_account,
717 char **machine_krb5_principal)
719 const char *account_name;
720 const char *name = NULL;
722 /* If we are a DC and this is not our own domain */
724 if (IS_DC) {
725 name = domain->name;
726 } else {
727 struct winbindd_domain *our_domain = find_our_domain();
729 if (!our_domain)
730 return NT_STATUS_INVALID_SERVER_STATE;
732 name = our_domain->name;
735 if (!get_trust_pw_clear(name, machine_password,
736 &account_name, NULL))
738 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
741 if ((machine_account != NULL) &&
742 (asprintf(machine_account, "%s$", account_name) == -1))
744 return NT_STATUS_NO_MEMORY;
747 /* For now assume our machine account only exists in our domain */
749 if (machine_krb5_principal != NULL)
751 struct winbindd_domain *our_domain = find_our_domain();
753 if (!our_domain) {
754 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
757 if (asprintf(machine_krb5_principal, "%s$@%s",
758 account_name, our_domain->alt_name) == -1)
760 return NT_STATUS_NO_MEMORY;
763 strupper_m(*machine_krb5_principal);
766 return NT_STATUS_OK;
769 /************************************************************************
770 Given a fd with a just-connected TCP connection to a DC, open a connection
771 to the pipe.
772 ************************************************************************/
774 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
775 const int sockfd,
776 const char *controller,
777 struct cli_state **cli,
778 bool *retry)
780 char *machine_password = NULL;
781 char *machine_krb5_principal = NULL;
782 char *machine_account = NULL;
783 char *ipc_username = NULL;
784 char *ipc_domain = NULL;
785 char *ipc_password = NULL;
787 struct named_mutex *mutex;
789 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
791 struct sockaddr peeraddr;
792 socklen_t peeraddr_len;
794 struct sockaddr_in *peeraddr_in =
795 (struct sockaddr_in *)(void *)&peeraddr;
797 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
798 controller, domain->name ));
800 *retry = True;
802 mutex = grab_named_mutex(talloc_tos(), controller,
803 WINBIND_SERVER_MUTEX_WAIT_TIME);
804 if (mutex == NULL) {
805 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
806 controller));
807 result = NT_STATUS_POSSIBLE_DEADLOCK;
808 goto done;
811 if ((*cli = cli_initialise()) == NULL) {
812 DEBUG(1, ("Could not cli_initialize\n"));
813 result = NT_STATUS_NO_MEMORY;
814 goto done;
817 (*cli)->timeout = 10000; /* 10 seconds */
818 (*cli)->fd = sockfd;
819 (*cli)->desthost = talloc_strdup((*cli), controller);
820 if ((*cli)->desthost == NULL) {
821 result = NT_STATUS_NO_MEMORY;
822 goto done;
825 (*cli)->use_kerberos = True;
827 peeraddr_len = sizeof(peeraddr);
829 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
830 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
831 strerror(errno)));
832 result = NT_STATUS_UNSUCCESSFUL;
833 goto done;
836 if ((peeraddr_len != sizeof(struct sockaddr_in))
837 #ifdef HAVE_IPV6
838 && (peeraddr_len != sizeof(struct sockaddr_in6))
839 #endif
841 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
842 peeraddr_len));
843 result = NT_STATUS_UNSUCCESSFUL;
844 goto done;
847 if ((peeraddr_in->sin_family != PF_INET)
848 #ifdef HAVE_IPV6
849 && (peeraddr_in->sin_family != PF_INET6)
850 #endif
852 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
853 peeraddr_in->sin_family));
854 result = NT_STATUS_UNSUCCESSFUL;
855 goto done;
858 result = cli_negprot(*cli);
860 if (!NT_STATUS_IS_OK(result)) {
861 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
862 goto done;
865 if (!is_dc_trusted_domain_situation(domain->name) &&
866 (*cli)->protocol >= PROTOCOL_NT1 &&
867 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
869 ADS_STATUS ads_status;
871 result = get_trust_creds(domain, &machine_password,
872 &machine_account,
873 &machine_krb5_principal);
874 if (!NT_STATUS_IS_OK(result)) {
875 goto anon_fallback;
878 if (lp_security() == SEC_ADS) {
880 /* Try a krb5 session */
882 (*cli)->use_kerberos = True;
883 DEBUG(5, ("connecting to %s from %s with kerberos principal "
884 "[%s] and realm [%s]\n", controller, global_myname(),
885 machine_krb5_principal, domain->alt_name));
887 winbindd_set_locator_kdc_envs(domain);
889 ads_status = cli_session_setup_spnego(*cli,
890 machine_krb5_principal,
891 machine_password,
892 lp_workgroup(),
893 domain->alt_name);
895 if (!ADS_ERR_OK(ads_status)) {
896 DEBUG(4,("failed kerberos session setup with %s\n",
897 ads_errstr(ads_status)));
900 result = ads_ntstatus(ads_status);
901 if (NT_STATUS_IS_OK(result)) {
902 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
903 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
904 if (!NT_STATUS_IS_OK(result)) {
905 goto done;
907 goto session_setup_done;
911 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
912 (*cli)->use_kerberos = False;
914 DEBUG(5, ("connecting to %s from %s with username "
915 "[%s]\\[%s]\n", controller, global_myname(),
916 lp_workgroup(), machine_account));
918 ads_status = cli_session_setup_spnego(*cli,
919 machine_account,
920 machine_password,
921 lp_workgroup(),
922 NULL);
923 if (!ADS_ERR_OK(ads_status)) {
924 DEBUG(4, ("authenticated session setup failed with %s\n",
925 ads_errstr(ads_status)));
928 result = ads_ntstatus(ads_status);
929 if (NT_STATUS_IS_OK(result)) {
930 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
931 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
932 if (!NT_STATUS_IS_OK(result)) {
933 goto done;
935 goto session_setup_done;
939 /* Fall back to non-kerberos session setup with auth_user */
941 (*cli)->use_kerberos = False;
943 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
945 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
946 (strlen(ipc_username) > 0)) {
948 /* Only try authenticated if we have a username */
950 DEBUG(5, ("connecting to %s from %s with username "
951 "[%s]\\[%s]\n", controller, global_myname(),
952 ipc_domain, ipc_username));
954 if (NT_STATUS_IS_OK(cli_session_setup(
955 *cli, ipc_username,
956 ipc_password, strlen(ipc_password)+1,
957 ipc_password, strlen(ipc_password)+1,
958 ipc_domain))) {
959 /* Successful logon with given username. */
960 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
961 if (!NT_STATUS_IS_OK(result)) {
962 goto done;
964 goto session_setup_done;
965 } else {
966 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
967 ipc_domain, ipc_username ));
971 anon_fallback:
973 /* Fall back to anonymous connection, this might fail later */
974 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
975 "connection for DC %s\n",
976 controller ));
978 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
979 NULL, 0, ""))) {
980 DEBUG(5, ("Connected anonymously\n"));
981 result = cli_init_creds(*cli, "", "", "");
982 if (!NT_STATUS_IS_OK(result)) {
983 goto done;
985 goto session_setup_done;
988 result = cli_nt_error(*cli);
990 if (NT_STATUS_IS_OK(result))
991 result = NT_STATUS_UNSUCCESSFUL;
993 /* We can't session setup */
995 goto done;
997 session_setup_done:
999 /* cache the server name for later connections */
1001 saf_store( domain->name, (*cli)->desthost );
1002 if (domain->alt_name && (*cli)->use_kerberos) {
1003 saf_store( domain->alt_name, (*cli)->desthost );
1006 winbindd_set_locator_kdc_envs(domain);
1008 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
1010 if (!NT_STATUS_IS_OK(result)) {
1011 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1012 goto done;
1015 TALLOC_FREE(mutex);
1016 *retry = False;
1018 /* set the domain if empty; needed for schannel connections */
1019 if ( !(*cli)->domain[0] ) {
1020 result = cli_set_domain((*cli), domain->name);
1021 if (!NT_STATUS_IS_OK(result)) {
1022 return result;
1026 result = NT_STATUS_OK;
1028 done:
1029 TALLOC_FREE(mutex);
1030 SAFE_FREE(machine_account);
1031 SAFE_FREE(machine_password);
1032 SAFE_FREE(machine_krb5_principal);
1033 SAFE_FREE(ipc_username);
1034 SAFE_FREE(ipc_domain);
1035 SAFE_FREE(ipc_password);
1037 if (!NT_STATUS_IS_OK(result)) {
1038 winbind_add_failed_connection_entry(domain, controller, result);
1039 if ((*cli) != NULL) {
1040 cli_shutdown(*cli);
1041 *cli = NULL;
1045 return result;
1048 /*******************************************************************
1049 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1050 array.
1052 Keeps the list unique by not adding duplicate entries.
1054 @param[in] mem_ctx talloc memory context to allocate from
1055 @param[in] domain_name domain of the DC
1056 @param[in] dcname name of the DC to add to the list
1057 @param[in] pss Internet address and port pair to add to the list
1058 @param[in,out] dcs array of dc_name_ip structures to add to
1059 @param[in,out] num_dcs number of dcs returned in the dcs array
1060 @return true if the list was added to, false otherwise
1061 *******************************************************************/
1063 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1064 const char *dcname, struct sockaddr_storage *pss,
1065 struct dc_name_ip **dcs, int *num)
1067 int i = 0;
1069 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1070 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1071 return False;
1074 /* Make sure there's no duplicates in the list */
1075 for (i=0; i<*num; i++)
1076 if (sockaddr_equal(
1077 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1078 (struct sockaddr *)(void *)pss))
1079 return False;
1081 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1083 if (*dcs == NULL)
1084 return False;
1086 fstrcpy((*dcs)[*num].name, dcname);
1087 (*dcs)[*num].ss = *pss;
1088 *num += 1;
1089 return True;
1092 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1093 struct sockaddr_storage *pss, uint16 port,
1094 struct sockaddr_storage **addrs, int *num)
1096 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1098 if (*addrs == NULL) {
1099 *num = 0;
1100 return False;
1103 (*addrs)[*num] = *pss;
1104 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1106 *num += 1;
1107 return True;
1110 /*******************************************************************
1111 convert an ip to a name
1112 *******************************************************************/
1114 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1115 const struct winbindd_domain *domain,
1116 struct sockaddr_storage *pss,
1117 fstring name )
1119 struct ip_service ip_list;
1120 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1121 NTSTATUS status;
1122 const char *dc_name;
1124 ip_list.ss = *pss;
1125 ip_list.port = 0;
1127 #ifdef HAVE_ADS
1128 /* For active directory servers, try to get the ldap server name.
1129 None of these failures should be considered critical for now */
1131 if (lp_security() == SEC_ADS) {
1132 ADS_STRUCT *ads;
1133 ADS_STATUS ads_status;
1134 char addr[INET6_ADDRSTRLEN];
1136 print_sockaddr(addr, sizeof(addr), pss);
1138 ads = ads_init(domain->alt_name, domain->name, addr);
1139 ads->auth.flags |= ADS_AUTH_NO_BIND;
1141 ads_status = ads_connect(ads);
1142 if (ADS_ERR_OK(ads_status)) {
1143 /* We got a cldap packet. */
1144 fstrcpy(name, ads->config.ldap_server_name);
1145 namecache_store(name, 0x20, 1, &ip_list);
1147 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1149 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1150 if (ads_closest_dc(ads)) {
1151 char *sitename = sitename_fetch(ads->config.realm);
1153 /* We're going to use this KDC for this realm/domain.
1154 If we are using sites, then force the krb5 libs
1155 to use this KDC. */
1157 create_local_private_krb5_conf_for_domain(domain->alt_name,
1158 domain->name,
1159 sitename,
1160 pss,
1161 name);
1163 SAFE_FREE(sitename);
1164 } else {
1165 /* use an off site KDC */
1166 create_local_private_krb5_conf_for_domain(domain->alt_name,
1167 domain->name,
1168 NULL,
1169 pss,
1170 name);
1172 winbindd_set_locator_kdc_envs(domain);
1174 /* Ensure we contact this DC also. */
1175 saf_store( domain->name, name);
1176 saf_store( domain->alt_name, name);
1179 ads_destroy( &ads );
1180 return True;
1183 ads_destroy( &ads );
1185 #endif
1187 status = nbt_getdc(winbind_messaging_context(), pss, domain->name,
1188 &domain->sid, nt_version, mem_ctx, &nt_version,
1189 &dc_name, NULL);
1190 if (NT_STATUS_IS_OK(status)) {
1191 fstrcpy(name, dc_name);
1192 namecache_store(name, 0x20, 1, &ip_list);
1193 return True;
1196 /* try node status request */
1198 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1199 namecache_store(name, 0x20, 1, &ip_list);
1200 return True;
1202 return False;
1205 /*******************************************************************
1206 Retrieve a list of IP addresses for domain controllers.
1208 The array is sorted in the preferred connection order.
1210 @param[in] mem_ctx talloc memory context to allocate from
1211 @param[in] domain domain to retrieve DCs for
1212 @param[out] dcs array of dcs that will be returned
1213 @param[out] num_dcs number of dcs returned in the dcs array
1214 @return always true
1215 *******************************************************************/
1217 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1218 struct dc_name_ip **dcs, int *num_dcs)
1220 fstring dcname;
1221 struct sockaddr_storage ss;
1222 struct ip_service *ip_list = NULL;
1223 int iplist_size = 0;
1224 int i;
1225 bool is_our_domain;
1226 enum security_types sec = (enum security_types)lp_security();
1228 is_our_domain = strequal(domain->name, lp_workgroup());
1230 /* If not our domain, get the preferred DC, by asking our primary DC */
1231 if ( !is_our_domain
1232 && get_dc_name_via_netlogon(domain, dcname, &ss)
1233 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1234 num_dcs) )
1236 char addr[INET6_ADDRSTRLEN];
1237 print_sockaddr(addr, sizeof(addr), &ss);
1238 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1239 dcname, addr));
1240 return True;
1243 if (sec == SEC_ADS) {
1244 char *sitename = NULL;
1246 /* We need to make sure we know the local site before
1247 doing any DNS queries, as this will restrict the
1248 get_sorted_dc_list() call below to only fetching
1249 DNS records for the correct site. */
1251 /* Find any DC to get the site record.
1252 We deliberately don't care about the
1253 return here. */
1255 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1257 sitename = sitename_fetch(domain->alt_name);
1258 if (sitename) {
1260 /* Do the site-specific AD dns lookup first. */
1261 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1262 &iplist_size, True);
1264 /* Add ips to the DC array. We don't look up the name
1265 of the DC in this function, but we fill in the char*
1266 of the ip now to make the failed connection cache
1267 work */
1268 for ( i=0; i<iplist_size; i++ ) {
1269 char addr[INET6_ADDRSTRLEN];
1270 print_sockaddr(addr, sizeof(addr),
1271 &ip_list[i].ss);
1272 add_one_dc_unique(mem_ctx,
1273 domain->name,
1274 addr,
1275 &ip_list[i].ss,
1276 dcs,
1277 num_dcs);
1280 SAFE_FREE(ip_list);
1281 SAFE_FREE(sitename);
1282 iplist_size = 0;
1285 /* Now we add DCs from the main AD DNS lookup. */
1286 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1287 &iplist_size, True);
1289 for ( i=0; i<iplist_size; i++ ) {
1290 char addr[INET6_ADDRSTRLEN];
1291 print_sockaddr(addr, sizeof(addr),
1292 &ip_list[i].ss);
1293 add_one_dc_unique(mem_ctx,
1294 domain->name,
1295 addr,
1296 &ip_list[i].ss,
1297 dcs,
1298 num_dcs);
1301 SAFE_FREE(ip_list);
1302 iplist_size = 0;
1305 /* Try standard netbios queries if no ADS */
1306 if (*num_dcs == 0) {
1307 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1308 False);
1310 for ( i=0; i<iplist_size; i++ ) {
1311 char addr[INET6_ADDRSTRLEN];
1312 print_sockaddr(addr, sizeof(addr),
1313 &ip_list[i].ss);
1314 add_one_dc_unique(mem_ctx,
1315 domain->name,
1316 addr,
1317 &ip_list[i].ss,
1318 dcs,
1319 num_dcs);
1322 SAFE_FREE(ip_list);
1323 iplist_size = 0;
1326 return True;
1329 /*******************************************************************
1330 Find and make a connection to a DC in the given domain.
1332 @param[in] mem_ctx talloc memory context to allocate from
1333 @param[in] domain domain to find a dc in
1334 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1335 @param[out] pss DC Internet address and port
1336 @param[out] fd fd of the open socket connected to the newly found dc
1337 @return true when a DC connection is made, false otherwise
1338 *******************************************************************/
1340 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1341 struct winbindd_domain *domain,
1342 fstring dcname, struct sockaddr_storage *pss, int *fd)
1344 struct dc_name_ip *dcs = NULL;
1345 int num_dcs = 0;
1347 const char **dcnames = NULL;
1348 int num_dcnames = 0;
1350 struct sockaddr_storage *addrs = NULL;
1351 int num_addrs = 0;
1353 int i;
1354 size_t fd_index;
1356 NTSTATUS status;
1358 *fd = -1;
1360 again:
1361 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1362 return False;
1364 for (i=0; i<num_dcs; i++) {
1366 if (!add_string_to_array(mem_ctx, dcs[i].name,
1367 &dcnames, &num_dcnames)) {
1368 return False;
1370 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1371 &addrs, &num_addrs)) {
1372 return False;
1376 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1377 return False;
1379 if ((addrs == NULL) || (dcnames == NULL))
1380 return False;
1382 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1383 num_addrs, 0, 10, fd, &fd_index, NULL);
1384 if (!NT_STATUS_IS_OK(status)) {
1385 for (i=0; i<num_dcs; i++) {
1386 char ab[INET6_ADDRSTRLEN];
1387 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1388 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1389 "domain %s address %s. Error was %s\n",
1390 domain->name, ab, nt_errstr(status) ));
1391 winbind_add_failed_connection_entry(domain,
1392 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1394 return False;
1397 *pss = addrs[fd_index];
1399 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1400 /* Ok, we've got a name for the DC */
1401 fstrcpy(dcname, dcnames[fd_index]);
1402 return True;
1405 /* Try to figure out the name */
1406 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1407 return True;
1410 /* We can not continue without the DC's name */
1411 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1412 NT_STATUS_UNSUCCESSFUL);
1414 /* Throw away all arrays as we're doing this again. */
1415 TALLOC_FREE(dcs);
1416 num_dcs = 0;
1418 TALLOC_FREE(dcnames);
1419 num_dcnames = 0;
1421 TALLOC_FREE(addrs);
1422 num_addrs = 0;
1424 close(*fd);
1425 *fd = -1;
1427 goto again;
1430 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1432 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1433 domain_name);
1436 static void store_current_dc_in_gencache(const char *domain_name,
1437 const char *dc_name,
1438 struct cli_state *cli)
1440 char addr[INET6_ADDRSTRLEN];
1441 char *key = NULL;
1442 char *value = NULL;
1444 if (cli == NULL) {
1445 return;
1447 if (cli->fd == -1) {
1448 return;
1450 get_peer_addr(cli->fd, addr, sizeof(addr));
1452 key = current_dc_key(talloc_tos(), domain_name);
1453 if (key == NULL) {
1454 goto done;
1457 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1458 if (value == NULL) {
1459 goto done;
1462 gencache_set(key, value, 0x7fffffff);
1463 done:
1464 TALLOC_FREE(value);
1465 TALLOC_FREE(key);
1468 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1469 const char *domain_name,
1470 char **p_dc_name, char **p_dc_ip)
1472 char *key, *value, *p;
1473 bool ret = false;
1474 char *dc_name = NULL;
1475 char *dc_ip = NULL;
1477 key = current_dc_key(talloc_tos(), domain_name);
1478 if (key == NULL) {
1479 goto done;
1481 if (!gencache_get(key, &value, NULL)) {
1482 goto done;
1484 p = strchr(value, ' ');
1485 if (p == NULL) {
1486 goto done;
1488 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1489 if (dc_ip == NULL) {
1490 goto done;
1492 dc_name = talloc_strdup(mem_ctx, p+1);
1493 if (dc_name == NULL) {
1494 goto done;
1497 if (p_dc_ip != NULL) {
1498 *p_dc_ip = dc_ip;
1499 dc_ip = NULL;
1501 if (p_dc_name != NULL) {
1502 *p_dc_name = dc_name;
1503 dc_name = NULL;
1505 ret = true;
1506 done:
1507 TALLOC_FREE(dc_name);
1508 TALLOC_FREE(dc_ip);
1509 TALLOC_FREE(key);
1510 return ret;
1513 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1514 struct winbindd_cm_conn *new_conn)
1516 TALLOC_CTX *mem_ctx;
1517 NTSTATUS result;
1518 char *saf_servername = saf_fetch( domain->name );
1519 int retries;
1521 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1522 SAFE_FREE(saf_servername);
1523 set_domain_offline(domain);
1524 return NT_STATUS_NO_MEMORY;
1527 /* we have to check the server affinity cache here since
1528 later we select a DC based on response time and not preference */
1530 /* Check the negative connection cache
1531 before talking to it. It going down may have
1532 triggered the reconnection. */
1534 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1536 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1537 saf_servername, domain->name ));
1539 /* convert an ip address to a name */
1540 if (is_ipaddress( saf_servername ) ) {
1541 fstring saf_name;
1542 struct sockaddr_storage ss;
1544 if (!interpret_string_addr(&ss, saf_servername,
1545 AI_NUMERICHOST)) {
1546 return NT_STATUS_UNSUCCESSFUL;
1548 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1549 fstrcpy( domain->dcname, saf_name );
1550 } else {
1551 winbind_add_failed_connection_entry(
1552 domain, saf_servername,
1553 NT_STATUS_UNSUCCESSFUL);
1555 } else {
1556 fstrcpy( domain->dcname, saf_servername );
1559 SAFE_FREE( saf_servername );
1562 for (retries = 0; retries < 3; retries++) {
1563 int fd = -1;
1564 bool retry = False;
1566 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1568 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1569 domain->dcname, domain->name ));
1571 if (*domain->dcname
1572 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1573 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1575 NTSTATUS status;
1577 status = smbsock_connect(&domain->dcaddr, 0,
1578 NULL, -1, NULL, -1,
1579 &fd, NULL, 10);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 fd = -1;
1585 if ((fd == -1)
1586 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1588 /* This is the one place where we will
1589 set the global winbindd offline state
1590 to true, if a "WINBINDD_OFFLINE" entry
1591 is found in the winbindd cache. */
1592 set_global_winbindd_state_offline();
1593 break;
1596 new_conn->cli = NULL;
1598 result = cm_prepare_connection(domain, fd, domain->dcname,
1599 &new_conn->cli, &retry);
1601 if (!retry)
1602 break;
1605 if (NT_STATUS_IS_OK(result)) {
1607 winbindd_set_locator_kdc_envs(domain);
1609 if (domain->online == False) {
1610 /* We're changing state from offline to online. */
1611 set_global_winbindd_state_online();
1613 set_domain_online(domain);
1616 * Much as I hate global state, this seems to be the point
1617 * where we can be certain that we have a proper connection to
1618 * a DC. wbinfo --dc-info needs that information, store it in
1619 * gencache with a looong timeout. This will need revisiting
1620 * once we start to connect to multiple DCs, wbcDcInfo is
1621 * already prepared for that.
1623 store_current_dc_in_gencache(domain->name, domain->dcname,
1624 new_conn->cli);
1625 } else {
1626 /* Ensure we setup the retry handler. */
1627 set_domain_offline(domain);
1630 talloc_destroy(mem_ctx);
1631 return result;
1634 /* Close down all open pipes on a connection. */
1636 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1638 NTSTATUS result;
1640 /* We're closing down a possibly dead
1641 connection. Don't have impossibly long (10s) timeouts. */
1643 if (conn->cli) {
1644 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1647 if (conn->samr_pipe != NULL) {
1648 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1649 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1650 talloc_tos(),
1651 &conn->sam_connect_handle,
1652 &result);
1654 TALLOC_FREE(conn->samr_pipe);
1655 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1656 if (conn->cli) {
1657 cli_set_timeout(conn->cli, 500);
1661 if (conn->lsa_pipe != NULL) {
1662 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1663 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1664 talloc_tos(),
1665 &conn->lsa_policy,
1666 &result);
1668 TALLOC_FREE(conn->lsa_pipe);
1669 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1670 if (conn->cli) {
1671 cli_set_timeout(conn->cli, 500);
1675 if (conn->lsa_pipe_tcp != NULL) {
1676 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1677 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1678 talloc_tos(),
1679 &conn->lsa_policy,
1680 &result);
1682 TALLOC_FREE(conn->lsa_pipe_tcp);
1683 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1684 if (conn->cli) {
1685 cli_set_timeout(conn->cli, 500);
1689 if (conn->netlogon_pipe != NULL) {
1690 TALLOC_FREE(conn->netlogon_pipe);
1691 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1692 if (conn->cli) {
1693 cli_set_timeout(conn->cli, 500);
1697 if (conn->cli) {
1698 cli_shutdown(conn->cli);
1701 conn->cli = NULL;
1704 void close_conns_after_fork(void)
1706 struct winbindd_domain *domain;
1707 struct winbindd_cli_state *cli_state;
1709 for (domain = domain_list(); domain; domain = domain->next) {
1710 struct cli_state *cli = domain->conn.cli;
1713 * first close the low level SMB TCP connection
1714 * so that we don't generate any SMBclose
1715 * requests in invalidate_cm_connection()
1717 if (cli && cli->fd != -1) {
1718 close(domain->conn.cli->fd);
1719 domain->conn.cli->fd = -1;
1722 invalidate_cm_connection(&domain->conn);
1725 for (cli_state = winbindd_client_list();
1726 cli_state != NULL;
1727 cli_state = cli_state->next) {
1728 if (cli_state->sock >= 0) {
1729 close(cli_state->sock);
1730 cli_state->sock = -1;
1735 static bool connection_ok(struct winbindd_domain *domain)
1737 bool ok;
1739 ok = cli_state_is_connected(domain->conn.cli);
1740 if (!ok) {
1741 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1742 domain->dcname, domain->name));
1743 return False;
1746 if (domain->online == False) {
1747 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1748 return False;
1751 return True;
1754 /* Initialize a new connection up to the RPC BIND.
1755 Bypass online status check so always does network calls. */
1757 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1759 NTSTATUS result;
1761 /* Internal connections never use the network. */
1762 if (domain->internal) {
1763 domain->initialized = True;
1764 return NT_STATUS_OK;
1767 if (!winbindd_can_contact_domain(domain)) {
1768 invalidate_cm_connection(&domain->conn);
1769 domain->initialized = True;
1770 return NT_STATUS_OK;
1773 if (connection_ok(domain)) {
1774 if (!domain->initialized) {
1775 set_dc_type_and_flags(domain);
1777 return NT_STATUS_OK;
1780 invalidate_cm_connection(&domain->conn);
1782 result = cm_open_connection(domain, &domain->conn);
1784 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1785 set_dc_type_and_flags(domain);
1788 return result;
1791 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1793 if (domain->internal) {
1794 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1797 if (domain->initialized && !domain->online) {
1798 /* We check for online status elsewhere. */
1799 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1802 return init_dc_connection_network(domain);
1805 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1807 NTSTATUS status;
1809 status = init_dc_connection(domain);
1810 if (!NT_STATUS_IS_OK(status)) {
1811 return status;
1814 if (!domain->internal && domain->conn.cli == NULL) {
1815 /* happens for trusted domains without inbound trust */
1816 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1819 return NT_STATUS_OK;
1822 /******************************************************************************
1823 Set the trust flags (direction and forest location) for a domain
1824 ******************************************************************************/
1826 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1828 struct winbindd_domain *our_domain;
1829 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1830 WERROR werr;
1831 struct netr_DomainTrustList trusts;
1832 int i;
1833 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1834 NETR_TRUST_FLAG_OUTBOUND |
1835 NETR_TRUST_FLAG_INBOUND);
1836 struct rpc_pipe_client *cli;
1837 TALLOC_CTX *mem_ctx = NULL;
1838 struct dcerpc_binding_handle *b;
1840 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1842 /* Our primary domain doesn't need to worry about trust flags.
1843 Force it to go through the network setup */
1844 if ( domain->primary ) {
1845 return False;
1848 our_domain = find_our_domain();
1850 if ( !connection_ok(our_domain) ) {
1851 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1852 return False;
1855 /* This won't work unless our domain is AD */
1857 if ( !our_domain->active_directory ) {
1858 return False;
1861 /* Use DsEnumerateDomainTrusts to get us the trust direction
1862 and type */
1864 result = cm_connect_netlogon(our_domain, &cli);
1866 if (!NT_STATUS_IS_OK(result)) {
1867 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1868 "a connection to %s for PIPE_NETLOGON (%s)\n",
1869 domain->name, nt_errstr(result)));
1870 return False;
1873 b = cli->binding_handle;
1875 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1876 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1877 return False;
1880 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1881 cli->desthost,
1882 flags,
1883 &trusts,
1884 &werr);
1885 if (!NT_STATUS_IS_OK(result)) {
1886 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1887 "failed to query trusted domain list: %s\n",
1888 nt_errstr(result)));
1889 talloc_destroy(mem_ctx);
1890 return false;
1892 if (!W_ERROR_IS_OK(werr)) {
1893 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1894 "failed to query trusted domain list: %s\n",
1895 win_errstr(werr)));
1896 talloc_destroy(mem_ctx);
1897 return false;
1900 /* Now find the domain name and get the flags */
1902 for ( i=0; i<trusts.count; i++ ) {
1903 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1904 domain->domain_flags = trusts.array[i].trust_flags;
1905 domain->domain_type = trusts.array[i].trust_type;
1906 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1908 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1909 domain->active_directory = True;
1911 /* This flag is only set if the domain is *our*
1912 primary domain and the primary domain is in
1913 native mode */
1915 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1917 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1918 "native mode.\n", domain->name,
1919 domain->native_mode ? "" : "NOT "));
1921 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1922 "running active directory.\n", domain->name,
1923 domain->active_directory ? "" : "NOT "));
1926 domain->initialized = True;
1928 break;
1932 talloc_destroy( mem_ctx );
1934 return domain->initialized;
1937 /******************************************************************************
1938 We can 'sense' certain things about the DC by it's replies to certain
1939 questions.
1941 This tells us if this particular remote server is Active Directory, and if it
1942 is native mode.
1943 ******************************************************************************/
1945 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1947 NTSTATUS status, result;
1948 WERROR werr;
1949 TALLOC_CTX *mem_ctx = NULL;
1950 struct rpc_pipe_client *cli = NULL;
1951 struct policy_handle pol;
1952 union dssetup_DsRoleInfo info;
1953 union lsa_PolicyInformation *lsa_info = NULL;
1955 if (!connection_ok(domain)) {
1956 return;
1959 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1960 domain->name);
1961 if (!mem_ctx) {
1962 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1963 return;
1966 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1968 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
1969 &ndr_table_dssetup.syntax_id,
1970 &cli);
1972 if (!NT_STATUS_IS_OK(status)) {
1973 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1974 "PI_DSSETUP on domain %s: (%s)\n",
1975 domain->name, nt_errstr(status)));
1977 /* if this is just a non-AD domain we need to continue
1978 * identifying so that we can in the end return with
1979 * domain->initialized = True - gd */
1981 goto no_dssetup;
1984 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
1985 DS_ROLE_BASIC_INFORMATION,
1986 &info,
1987 &werr);
1988 TALLOC_FREE(cli);
1990 if (NT_STATUS_IS_OK(status)) {
1991 result = werror_to_ntstatus(werr);
1993 if (!NT_STATUS_IS_OK(status)) {
1994 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1995 "on domain %s failed: (%s)\n",
1996 domain->name, nt_errstr(status)));
1998 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1999 * every opcode on the DSSETUP pipe, continue with
2000 * no_dssetup mode here as well to get domain->initialized
2001 * set - gd */
2003 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2004 goto no_dssetup;
2007 TALLOC_FREE(mem_ctx);
2008 return;
2011 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2012 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2013 domain->native_mode = True;
2014 } else {
2015 domain->native_mode = False;
2018 no_dssetup:
2019 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2020 &ndr_table_lsarpc.syntax_id, &cli);
2022 if (!NT_STATUS_IS_OK(status)) {
2023 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2024 "PI_LSARPC on domain %s: (%s)\n",
2025 domain->name, nt_errstr(status)));
2026 TALLOC_FREE(cli);
2027 TALLOC_FREE(mem_ctx);
2028 return;
2031 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2032 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2034 if (NT_STATUS_IS_OK(status)) {
2035 /* This particular query is exactly what Win2k clients use
2036 to determine that the DC is active directory */
2037 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2038 &pol,
2039 LSA_POLICY_INFO_DNS,
2040 &lsa_info,
2041 &result);
2044 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2045 domain->active_directory = True;
2047 if (lsa_info->dns.name.string) {
2048 fstrcpy(domain->name, lsa_info->dns.name.string);
2051 if (lsa_info->dns.dns_domain.string) {
2052 fstrcpy(domain->alt_name,
2053 lsa_info->dns.dns_domain.string);
2056 /* See if we can set some domain trust flags about
2057 ourself */
2059 if (lsa_info->dns.dns_forest.string) {
2060 fstrcpy(domain->forest_name,
2061 lsa_info->dns.dns_forest.string);
2063 if (strequal(domain->forest_name, domain->alt_name)) {
2064 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2068 if (lsa_info->dns.sid) {
2069 sid_copy(&domain->sid, lsa_info->dns.sid);
2071 } else {
2072 domain->active_directory = False;
2074 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2075 SEC_FLAG_MAXIMUM_ALLOWED,
2076 &pol);
2078 if (!NT_STATUS_IS_OK(status)) {
2079 goto done;
2082 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2083 &pol,
2084 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2085 &lsa_info,
2086 &result);
2087 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2089 if (lsa_info->account_domain.name.string) {
2090 fstrcpy(domain->name,
2091 lsa_info->account_domain.name.string);
2094 if (lsa_info->account_domain.sid) {
2095 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2099 done:
2101 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2102 domain->name, domain->native_mode ? "" : "NOT "));
2104 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2105 domain->name, domain->active_directory ? "" : "NOT "));
2107 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2108 domain->can_do_validation6 = domain->active_directory;
2110 TALLOC_FREE(cli);
2112 TALLOC_FREE(mem_ctx);
2114 domain->initialized = True;
2117 /**********************************************************************
2118 Set the domain_flags (trust attributes, domain operating modes, etc...
2119 ***********************************************************************/
2121 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2123 /* we always have to contact our primary domain */
2125 if ( domain->primary ) {
2126 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2127 "primary domain\n"));
2128 set_dc_type_and_flags_connect( domain );
2129 return;
2132 /* Use our DC to get the information if possible */
2134 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2135 /* Otherwise, fallback to contacting the
2136 domain directly */
2137 set_dc_type_and_flags_connect( domain );
2140 return;
2145 /**********************************************************************
2146 ***********************************************************************/
2148 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2149 struct netlogon_creds_CredentialState **ppdc)
2151 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2152 struct rpc_pipe_client *netlogon_pipe;
2154 if (lp_client_schannel() == False) {
2155 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2158 result = cm_connect_netlogon(domain, &netlogon_pipe);
2159 if (!NT_STATUS_IS_OK(result)) {
2160 return result;
2163 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2164 netlogon pipe. */
2166 if (!domain->conn.netlogon_pipe->dc) {
2167 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2170 *ppdc = domain->conn.netlogon_pipe->dc;
2171 return NT_STATUS_OK;
2174 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2175 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2177 struct winbindd_cm_conn *conn;
2178 NTSTATUS status, result;
2179 struct netlogon_creds_CredentialState *p_creds;
2180 char *machine_password = NULL;
2181 char *machine_account = NULL;
2182 char *domain_name = NULL;
2184 if (sid_check_is_domain(&domain->sid)) {
2185 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2188 status = init_dc_connection_rpc(domain);
2189 if (!NT_STATUS_IS_OK(status)) {
2190 return status;
2193 conn = &domain->conn;
2195 if (rpccli_is_connected(conn->samr_pipe)) {
2196 goto done;
2199 TALLOC_FREE(conn->samr_pipe);
2202 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2203 * sign and sealed pipe using the machine account password by
2204 * preference. If we can't - try schannel, if that fails, try
2205 * anonymous.
2208 if ((conn->cli->user_name[0] == '\0') ||
2209 (conn->cli->domain[0] == '\0') ||
2210 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2212 status = get_trust_creds(domain, &machine_password,
2213 &machine_account, NULL);
2214 if (!NT_STATUS_IS_OK(status)) {
2215 DEBUG(10, ("cm_connect_sam: No no user available for "
2216 "domain %s, trying schannel\n", conn->cli->domain));
2217 goto schannel;
2219 domain_name = domain->name;
2220 } else {
2221 machine_password = SMB_STRDUP(conn->cli->password);
2222 machine_account = SMB_STRDUP(conn->cli->user_name);
2223 domain_name = conn->cli->domain;
2226 if (!machine_password || !machine_account) {
2227 status = NT_STATUS_NO_MEMORY;
2228 goto done;
2231 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2232 authenticated SAMR pipe with sign & seal. */
2233 status = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2234 &ndr_table_samr.syntax_id,
2235 NCACN_NP,
2236 DCERPC_AUTH_LEVEL_PRIVACY,
2237 domain_name,
2238 machine_account,
2239 machine_password,
2240 &conn->samr_pipe);
2242 if (!NT_STATUS_IS_OK(status)) {
2243 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2244 "pipe for domain %s using NTLMSSP "
2245 "authenticated pipe: user %s\\%s. Error was "
2246 "%s\n", domain->name, domain_name,
2247 machine_account, nt_errstr(status)));
2248 goto schannel;
2251 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2252 "domain %s using NTLMSSP authenticated "
2253 "pipe: user %s\\%s\n", domain->name,
2254 domain_name, machine_account));
2256 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2257 conn->samr_pipe->desthost,
2258 SEC_FLAG_MAXIMUM_ALLOWED,
2259 &conn->sam_connect_handle,
2260 &result);
2261 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2262 goto open_domain;
2264 if (NT_STATUS_IS_OK(status)) {
2265 status = result;
2268 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2269 "failed for domain %s, error was %s. Trying schannel\n",
2270 domain->name, nt_errstr(status) ));
2271 TALLOC_FREE(conn->samr_pipe);
2273 schannel:
2275 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2277 status = cm_get_schannel_creds(domain, &p_creds);
2278 if (!NT_STATUS_IS_OK(status)) {
2279 /* If this call fails - conn->cli can now be NULL ! */
2280 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2281 "for domain %s (error %s), trying anon\n",
2282 domain->name,
2283 nt_errstr(status) ));
2284 goto anonymous;
2286 status = cli_rpc_pipe_open_schannel_with_key
2287 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2288 DCERPC_AUTH_LEVEL_PRIVACY,
2289 domain->name, &p_creds, &conn->samr_pipe);
2291 if (!NT_STATUS_IS_OK(status)) {
2292 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2293 "domain %s using schannel. Error was %s\n",
2294 domain->name, nt_errstr(status) ));
2295 goto anonymous;
2297 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2298 "schannel.\n", domain->name ));
2300 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2301 conn->samr_pipe->desthost,
2302 SEC_FLAG_MAXIMUM_ALLOWED,
2303 &conn->sam_connect_handle,
2304 &result);
2305 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2306 goto open_domain;
2308 if (NT_STATUS_IS_OK(status)) {
2309 status = result;
2311 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2312 "for domain %s, error was %s. Trying anonymous\n",
2313 domain->name, nt_errstr(status) ));
2314 TALLOC_FREE(conn->samr_pipe);
2316 anonymous:
2318 /* Finally fall back to anonymous. */
2319 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2320 &conn->samr_pipe);
2322 if (!NT_STATUS_IS_OK(status)) {
2323 goto done;
2326 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2327 conn->samr_pipe->desthost,
2328 SEC_FLAG_MAXIMUM_ALLOWED,
2329 &conn->sam_connect_handle,
2330 &result);
2331 if (!NT_STATUS_IS_OK(status)) {
2332 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2333 "for domain %s Error was %s\n",
2334 domain->name, nt_errstr(status) ));
2335 goto done;
2337 if (!NT_STATUS_IS_OK(result)) {
2338 status = result;
2339 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2340 "for domain %s Error was %s\n",
2341 domain->name, nt_errstr(result)));
2342 goto done;
2345 open_domain:
2346 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2347 mem_ctx,
2348 &conn->sam_connect_handle,
2349 SEC_FLAG_MAXIMUM_ALLOWED,
2350 &domain->sid,
2351 &conn->sam_domain_handle,
2352 &result);
2353 if (!NT_STATUS_IS_OK(status)) {
2354 goto done;
2357 status = result;
2358 done:
2360 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2362 * if we got access denied, we might just have no access rights
2363 * to talk to the remote samr server server (e.g. when we are a
2364 * PDC and we are connecting a w2k8 pdc via an interdomain
2365 * trust). In that case do not invalidate the whole connection
2366 * stack
2368 TALLOC_FREE(conn->samr_pipe);
2369 ZERO_STRUCT(conn->sam_domain_handle);
2370 return status;
2371 } else if (!NT_STATUS_IS_OK(status)) {
2372 invalidate_cm_connection(conn);
2373 return status;
2376 *cli = conn->samr_pipe;
2377 *sam_handle = conn->sam_domain_handle;
2378 SAFE_FREE(machine_password);
2379 SAFE_FREE(machine_account);
2380 return status;
2383 /**********************************************************************
2384 open an schanneld ncacn_ip_tcp connection to LSA
2385 ***********************************************************************/
2387 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2388 TALLOC_CTX *mem_ctx,
2389 struct rpc_pipe_client **cli)
2391 struct winbindd_cm_conn *conn;
2392 struct netlogon_creds_CredentialState *creds;
2393 NTSTATUS status;
2395 DEBUG(10,("cm_connect_lsa_tcp\n"));
2397 status = init_dc_connection_rpc(domain);
2398 if (!NT_STATUS_IS_OK(status)) {
2399 return status;
2402 conn = &domain->conn;
2404 if (conn->lsa_pipe_tcp &&
2405 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2406 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2407 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2408 goto done;
2411 TALLOC_FREE(conn->lsa_pipe_tcp);
2413 status = cm_get_schannel_creds(domain, &creds);
2414 if (!NT_STATUS_IS_OK(status)) {
2415 goto done;
2418 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2419 &ndr_table_lsarpc.syntax_id,
2420 NCACN_IP_TCP,
2421 DCERPC_AUTH_LEVEL_PRIVACY,
2422 domain->name,
2423 &creds,
2424 &conn->lsa_pipe_tcp);
2425 if (!NT_STATUS_IS_OK(status)) {
2426 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2427 nt_errstr(status)));
2428 goto done;
2431 done:
2432 if (!NT_STATUS_IS_OK(status)) {
2433 TALLOC_FREE(conn->lsa_pipe_tcp);
2434 return status;
2437 *cli = conn->lsa_pipe_tcp;
2439 return status;
2442 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2443 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2445 struct winbindd_cm_conn *conn;
2446 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2447 struct netlogon_creds_CredentialState *p_creds;
2449 result = init_dc_connection_rpc(domain);
2450 if (!NT_STATUS_IS_OK(result))
2451 return result;
2453 conn = &domain->conn;
2455 if (rpccli_is_connected(conn->lsa_pipe)) {
2456 goto done;
2459 TALLOC_FREE(conn->lsa_pipe);
2461 if ((conn->cli->user_name[0] == '\0') ||
2462 (conn->cli->domain[0] == '\0') ||
2463 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2464 DEBUG(10, ("cm_connect_lsa: No no user available for "
2465 "domain %s, trying schannel\n", conn->cli->domain));
2466 goto schannel;
2469 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2470 * authenticated LSA pipe with sign & seal. */
2471 result = cli_rpc_pipe_open_spnego_ntlmssp
2472 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2473 DCERPC_AUTH_LEVEL_PRIVACY,
2474 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2475 &conn->lsa_pipe);
2477 if (!NT_STATUS_IS_OK(result)) {
2478 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2479 "domain %s using NTLMSSP authenticated pipe: user "
2480 "%s\\%s. Error was %s. Trying schannel.\n",
2481 domain->name, conn->cli->domain,
2482 conn->cli->user_name, nt_errstr(result)));
2483 goto schannel;
2486 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2487 "NTLMSSP authenticated pipe: user %s\\%s\n",
2488 domain->name, conn->cli->domain, conn->cli->user_name ));
2490 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2491 SEC_FLAG_MAXIMUM_ALLOWED,
2492 &conn->lsa_policy);
2493 if (NT_STATUS_IS_OK(result)) {
2494 goto done;
2497 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2498 "schannel\n"));
2500 TALLOC_FREE(conn->lsa_pipe);
2502 schannel:
2504 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2506 result = cm_get_schannel_creds(domain, &p_creds);
2507 if (!NT_STATUS_IS_OK(result)) {
2508 /* If this call fails - conn->cli can now be NULL ! */
2509 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2510 "for domain %s (error %s), trying anon\n",
2511 domain->name,
2512 nt_errstr(result) ));
2513 goto anonymous;
2515 result = cli_rpc_pipe_open_schannel_with_key
2516 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2517 DCERPC_AUTH_LEVEL_PRIVACY,
2518 domain->name, &p_creds, &conn->lsa_pipe);
2520 if (!NT_STATUS_IS_OK(result)) {
2521 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2522 "domain %s using schannel. Error was %s\n",
2523 domain->name, nt_errstr(result) ));
2524 goto anonymous;
2526 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2527 "schannel.\n", domain->name ));
2529 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2530 SEC_FLAG_MAXIMUM_ALLOWED,
2531 &conn->lsa_policy);
2532 if (NT_STATUS_IS_OK(result)) {
2533 goto done;
2536 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2537 "anonymous\n"));
2539 TALLOC_FREE(conn->lsa_pipe);
2541 anonymous:
2543 result = cli_rpc_pipe_open_noauth(conn->cli,
2544 &ndr_table_lsarpc.syntax_id,
2545 &conn->lsa_pipe);
2546 if (!NT_STATUS_IS_OK(result)) {
2547 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2548 goto done;
2551 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2552 SEC_FLAG_MAXIMUM_ALLOWED,
2553 &conn->lsa_policy);
2554 done:
2555 if (!NT_STATUS_IS_OK(result)) {
2556 invalidate_cm_connection(conn);
2557 return result;
2560 *cli = conn->lsa_pipe;
2561 *lsa_policy = conn->lsa_policy;
2562 return result;
2565 /****************************************************************************
2566 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2567 session key stored in conn->netlogon_pipe->dc->sess_key.
2568 ****************************************************************************/
2570 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2571 struct rpc_pipe_client **cli)
2573 struct winbindd_cm_conn *conn;
2574 NTSTATUS result;
2576 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2577 uint8 mach_pwd[16];
2578 enum netr_SchannelType sec_chan_type;
2579 const char *account_name;
2580 struct rpc_pipe_client *netlogon_pipe = NULL;
2582 *cli = NULL;
2584 result = init_dc_connection_rpc(domain);
2585 if (!NT_STATUS_IS_OK(result)) {
2586 return result;
2589 conn = &domain->conn;
2591 if (rpccli_is_connected(conn->netlogon_pipe)) {
2592 *cli = conn->netlogon_pipe;
2593 return NT_STATUS_OK;
2596 TALLOC_FREE(conn->netlogon_pipe);
2598 result = cli_rpc_pipe_open_noauth(conn->cli,
2599 &ndr_table_netlogon.syntax_id,
2600 &netlogon_pipe);
2601 if (!NT_STATUS_IS_OK(result)) {
2602 return result;
2605 if ((!IS_DC) && (!domain->primary)) {
2606 /* Clear the schannel request bit and drop down */
2607 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2608 goto no_schannel;
2611 if (lp_client_schannel() != False) {
2612 neg_flags |= NETLOGON_NEG_SCHANNEL;
2615 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2616 &sec_chan_type))
2618 TALLOC_FREE(netlogon_pipe);
2619 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2622 result = rpccli_netlogon_setup_creds(
2623 netlogon_pipe,
2624 domain->dcname, /* server name. */
2625 domain->name, /* domain name */
2626 global_myname(), /* client name */
2627 account_name, /* machine account */
2628 mach_pwd, /* machine password */
2629 sec_chan_type, /* from get_trust_pw */
2630 &neg_flags);
2632 if (!NT_STATUS_IS_OK(result)) {
2633 TALLOC_FREE(netlogon_pipe);
2634 return result;
2637 if ((lp_client_schannel() == True) &&
2638 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2639 DEBUG(3, ("Server did not offer schannel\n"));
2640 TALLOC_FREE(netlogon_pipe);
2641 return NT_STATUS_ACCESS_DENIED;
2644 no_schannel:
2645 if ((lp_client_schannel() == False) ||
2646 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2648 * NetSamLogonEx only works for schannel
2650 domain->can_do_samlogon_ex = False;
2652 /* We're done - just keep the existing connection to NETLOGON
2653 * open */
2654 conn->netlogon_pipe = netlogon_pipe;
2655 *cli = conn->netlogon_pipe;
2656 return NT_STATUS_OK;
2659 /* Using the credentials from the first pipe, open a signed and sealed
2660 second netlogon pipe. The session key is stored in the schannel
2661 part of the new pipe auth struct.
2664 result = cli_rpc_pipe_open_schannel_with_key(
2665 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2666 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2667 &conn->netlogon_pipe);
2669 /* We can now close the initial netlogon pipe. */
2670 TALLOC_FREE(netlogon_pipe);
2672 if (!NT_STATUS_IS_OK(result)) {
2673 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2674 "was %s\n", nt_errstr(result)));
2676 invalidate_cm_connection(conn);
2677 return result;
2681 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2682 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2683 * supported). We used to only try SamLogonEx for AD, but
2684 * Samba DCs can also do it. And because we don't distinguish
2685 * between Samba and NT4, always try it once.
2687 domain->can_do_samlogon_ex = true;
2689 *cli = conn->netlogon_pipe;
2690 return NT_STATUS_OK;
2693 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2694 void *private_data,
2695 uint32_t msg_type,
2696 struct server_id server_id,
2697 DATA_BLOB *data)
2699 struct winbindd_domain *domain;
2700 char *freeit = NULL;
2701 char *addr;
2703 if ((data == NULL)
2704 || (data->data == NULL)
2705 || (data->length == 0)
2706 || (data->data[data->length-1] != '\0')) {
2707 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2708 "string\n"));
2709 return;
2712 addr = (char *)data->data;
2713 DEBUG(10, ("IP %s dropped\n", addr));
2715 if (!is_ipaddress(addr)) {
2716 char *slash;
2718 * Some code sends us ip addresses with the /netmask
2719 * suffix
2721 slash = strchr(addr, '/');
2722 if (slash == NULL) {
2723 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2724 addr));
2725 return;
2727 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2728 if (freeit == NULL) {
2729 DEBUG(1, ("talloc failed\n"));
2730 return;
2732 addr = freeit;
2733 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2736 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2737 char sockaddr[INET6_ADDRSTRLEN];
2738 if (domain->conn.cli == NULL) {
2739 continue;
2741 if (domain->conn.cli->fd == -1) {
2742 continue;
2744 client_socket_addr(domain->conn.cli->fd, sockaddr,
2745 sizeof(sockaddr));
2746 if (strequal(sockaddr, addr)) {
2747 close(domain->conn.cli->fd);
2748 domain->conn.cli->fd = -1;
2751 TALLOC_FREE(freeit);