s3-messages: only include messages.h where needed.
[Samba/gbeck.git] / source3 / winbindd / winbindd_cm.c
blob23eaa243b85c10e4b61f600db1f29e44a2a421e0
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
34 selection etc
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
46 implementation. -tpot
51 TODO:
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
57 various sam handles.
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "librpc/gen_ndr/messaging.h"
73 #include "libsmb/clidgram.h"
74 #include "ads.h"
75 #include "secrets.h"
76 #include "../libcli/security/security.h"
77 #include "passdb.h"
78 #include "messages.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 fstrcpy((*cli)->desthost, controller);
820 (*cli)->use_kerberos = True;
822 peeraddr_len = sizeof(peeraddr);
824 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
825 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
826 strerror(errno)));
827 result = NT_STATUS_UNSUCCESSFUL;
828 goto done;
831 if ((peeraddr_len != sizeof(struct sockaddr_in))
832 #ifdef HAVE_IPV6
833 && (peeraddr_len != sizeof(struct sockaddr_in6))
834 #endif
836 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
837 peeraddr_len));
838 result = NT_STATUS_UNSUCCESSFUL;
839 goto done;
842 if ((peeraddr_in->sin_family != PF_INET)
843 #ifdef HAVE_IPV6
844 && (peeraddr_in->sin_family != PF_INET6)
845 #endif
847 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
848 peeraddr_in->sin_family));
849 result = NT_STATUS_UNSUCCESSFUL;
850 goto done;
853 result = cli_negprot(*cli);
855 if (!NT_STATUS_IS_OK(result)) {
856 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
857 goto done;
860 if (!is_dc_trusted_domain_situation(domain->name) &&
861 (*cli)->protocol >= PROTOCOL_NT1 &&
862 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
864 ADS_STATUS ads_status;
866 result = get_trust_creds(domain, &machine_password,
867 &machine_account,
868 &machine_krb5_principal);
869 if (!NT_STATUS_IS_OK(result)) {
870 goto anon_fallback;
873 if (lp_security() == SEC_ADS) {
875 /* Try a krb5 session */
877 (*cli)->use_kerberos = True;
878 DEBUG(5, ("connecting to %s from %s with kerberos principal "
879 "[%s] and realm [%s]\n", controller, global_myname(),
880 machine_krb5_principal, domain->alt_name));
882 winbindd_set_locator_kdc_envs(domain);
884 ads_status = cli_session_setup_spnego(*cli,
885 machine_krb5_principal,
886 machine_password,
887 lp_workgroup(),
888 domain->alt_name);
890 if (!ADS_ERR_OK(ads_status)) {
891 DEBUG(4,("failed kerberos session setup with %s\n",
892 ads_errstr(ads_status)));
895 result = ads_ntstatus(ads_status);
896 if (NT_STATUS_IS_OK(result)) {
897 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
898 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
899 if (!NT_STATUS_IS_OK(result)) {
900 goto done;
902 goto session_setup_done;
906 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
907 (*cli)->use_kerberos = False;
909 DEBUG(5, ("connecting to %s from %s with username "
910 "[%s]\\[%s]\n", controller, global_myname(),
911 lp_workgroup(), machine_account));
913 ads_status = cli_session_setup_spnego(*cli,
914 machine_account,
915 machine_password,
916 lp_workgroup(),
917 NULL);
918 if (!ADS_ERR_OK(ads_status)) {
919 DEBUG(4, ("authenticated session setup failed with %s\n",
920 ads_errstr(ads_status)));
923 result = ads_ntstatus(ads_status);
924 if (NT_STATUS_IS_OK(result)) {
925 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
926 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
927 if (!NT_STATUS_IS_OK(result)) {
928 goto done;
930 goto session_setup_done;
934 /* Fall back to non-kerberos session setup with auth_user */
936 (*cli)->use_kerberos = False;
938 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
940 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
941 (strlen(ipc_username) > 0)) {
943 /* Only try authenticated if we have a username */
945 DEBUG(5, ("connecting to %s from %s with username "
946 "[%s]\\[%s]\n", controller, global_myname(),
947 ipc_domain, ipc_username));
949 if (NT_STATUS_IS_OK(cli_session_setup(
950 *cli, ipc_username,
951 ipc_password, strlen(ipc_password)+1,
952 ipc_password, strlen(ipc_password)+1,
953 ipc_domain))) {
954 /* Successful logon with given username. */
955 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
956 if (!NT_STATUS_IS_OK(result)) {
957 goto done;
959 goto session_setup_done;
960 } else {
961 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
962 ipc_domain, ipc_username ));
966 anon_fallback:
968 /* Fall back to anonymous connection, this might fail later */
969 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
970 "connection for DC %s\n",
971 controller ));
973 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
974 NULL, 0, ""))) {
975 DEBUG(5, ("Connected anonymously\n"));
976 result = cli_init_creds(*cli, "", "", "");
977 if (!NT_STATUS_IS_OK(result)) {
978 goto done;
980 goto session_setup_done;
983 result = cli_nt_error(*cli);
985 if (NT_STATUS_IS_OK(result))
986 result = NT_STATUS_UNSUCCESSFUL;
988 /* We can't session setup */
990 goto done;
992 session_setup_done:
994 /* cache the server name for later connections */
996 saf_store( domain->name, (*cli)->desthost );
997 if (domain->alt_name && (*cli)->use_kerberos) {
998 saf_store( domain->alt_name, (*cli)->desthost );
1001 winbindd_set_locator_kdc_envs(domain);
1003 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
1005 if (!NT_STATUS_IS_OK(result)) {
1006 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1007 goto done;
1010 TALLOC_FREE(mutex);
1011 *retry = False;
1013 /* set the domain if empty; needed for schannel connections */
1014 if ( !(*cli)->domain[0] ) {
1015 result = cli_set_domain((*cli), domain->name);
1016 if (!NT_STATUS_IS_OK(result)) {
1017 return result;
1021 result = NT_STATUS_OK;
1023 done:
1024 TALLOC_FREE(mutex);
1025 SAFE_FREE(machine_account);
1026 SAFE_FREE(machine_password);
1027 SAFE_FREE(machine_krb5_principal);
1028 SAFE_FREE(ipc_username);
1029 SAFE_FREE(ipc_domain);
1030 SAFE_FREE(ipc_password);
1032 if (!NT_STATUS_IS_OK(result)) {
1033 winbind_add_failed_connection_entry(domain, controller, result);
1034 if ((*cli) != NULL) {
1035 cli_shutdown(*cli);
1036 *cli = NULL;
1040 return result;
1043 /*******************************************************************
1044 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1045 array.
1047 Keeps the list unique by not adding duplicate entries.
1049 @param[in] mem_ctx talloc memory context to allocate from
1050 @param[in] domain_name domain of the DC
1051 @param[in] dcname name of the DC to add to the list
1052 @param[in] pss Internet address and port pair to add to the list
1053 @param[in,out] dcs array of dc_name_ip structures to add to
1054 @param[in,out] num_dcs number of dcs returned in the dcs array
1055 @return true if the list was added to, false otherwise
1056 *******************************************************************/
1058 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1059 const char *dcname, struct sockaddr_storage *pss,
1060 struct dc_name_ip **dcs, int *num)
1062 int i = 0;
1064 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1065 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1066 return False;
1069 /* Make sure there's no duplicates in the list */
1070 for (i=0; i<*num; i++)
1071 if (sockaddr_equal(
1072 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1073 (struct sockaddr *)(void *)pss))
1074 return False;
1076 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1078 if (*dcs == NULL)
1079 return False;
1081 fstrcpy((*dcs)[*num].name, dcname);
1082 (*dcs)[*num].ss = *pss;
1083 *num += 1;
1084 return True;
1087 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1088 struct sockaddr_storage *pss, uint16 port,
1089 struct sockaddr_storage **addrs, int *num)
1091 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1093 if (*addrs == NULL) {
1094 *num = 0;
1095 return False;
1098 (*addrs)[*num] = *pss;
1099 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1101 *num += 1;
1102 return True;
1105 /*******************************************************************
1106 convert an ip to a name
1107 *******************************************************************/
1109 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1110 const struct winbindd_domain *domain,
1111 struct sockaddr_storage *pss,
1112 fstring name )
1114 struct ip_service ip_list;
1115 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1116 NTSTATUS status;
1117 const char *dc_name;
1119 ip_list.ss = *pss;
1120 ip_list.port = 0;
1122 #ifdef HAVE_ADS
1123 /* For active directory servers, try to get the ldap server name.
1124 None of these failures should be considered critical for now */
1126 if (lp_security() == SEC_ADS) {
1127 ADS_STRUCT *ads;
1128 ADS_STATUS ads_status;
1129 char addr[INET6_ADDRSTRLEN];
1131 print_sockaddr(addr, sizeof(addr), pss);
1133 ads = ads_init(domain->alt_name, domain->name, addr);
1134 ads->auth.flags |= ADS_AUTH_NO_BIND;
1136 ads_status = ads_connect(ads);
1137 if (ADS_ERR_OK(ads_status)) {
1138 /* We got a cldap packet. */
1139 fstrcpy(name, ads->config.ldap_server_name);
1140 namecache_store(name, 0x20, 1, &ip_list);
1142 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1144 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1145 if (ads_closest_dc(ads)) {
1146 char *sitename = sitename_fetch(ads->config.realm);
1148 /* We're going to use this KDC for this realm/domain.
1149 If we are using sites, then force the krb5 libs
1150 to use this KDC. */
1152 create_local_private_krb5_conf_for_domain(domain->alt_name,
1153 domain->name,
1154 sitename,
1155 pss,
1156 name);
1158 SAFE_FREE(sitename);
1159 } else {
1160 /* use an off site KDC */
1161 create_local_private_krb5_conf_for_domain(domain->alt_name,
1162 domain->name,
1163 NULL,
1164 pss,
1165 name);
1167 winbindd_set_locator_kdc_envs(domain);
1169 /* Ensure we contact this DC also. */
1170 saf_store( domain->name, name);
1171 saf_store( domain->alt_name, name);
1174 ads_destroy( &ads );
1175 return True;
1178 ads_destroy( &ads );
1180 #endif
1182 status = nbt_getdc(winbind_messaging_context(), pss, domain->name,
1183 &domain->sid, nt_version, mem_ctx, &nt_version,
1184 &dc_name, NULL);
1185 if (NT_STATUS_IS_OK(status)) {
1186 fstrcpy(name, dc_name);
1187 namecache_store(name, 0x20, 1, &ip_list);
1188 return True;
1191 /* try node status request */
1193 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1194 namecache_store(name, 0x20, 1, &ip_list);
1195 return True;
1197 return False;
1200 /*******************************************************************
1201 Retrieve a list of IP addresses for domain controllers.
1203 The array is sorted in the preferred connection order.
1205 @param[in] mem_ctx talloc memory context to allocate from
1206 @param[in] domain domain to retrieve DCs for
1207 @param[out] dcs array of dcs that will be returned
1208 @param[out] num_dcs number of dcs returned in the dcs array
1209 @return always true
1210 *******************************************************************/
1212 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1213 struct dc_name_ip **dcs, int *num_dcs)
1215 fstring dcname;
1216 struct sockaddr_storage ss;
1217 struct ip_service *ip_list = NULL;
1218 int iplist_size = 0;
1219 int i;
1220 bool is_our_domain;
1221 enum security_types sec = (enum security_types)lp_security();
1223 is_our_domain = strequal(domain->name, lp_workgroup());
1225 /* If not our domain, get the preferred DC, by asking our primary DC */
1226 if ( !is_our_domain
1227 && get_dc_name_via_netlogon(domain, dcname, &ss)
1228 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1229 num_dcs) )
1231 char addr[INET6_ADDRSTRLEN];
1232 print_sockaddr(addr, sizeof(addr), &ss);
1233 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1234 dcname, addr));
1235 return True;
1238 if (sec == SEC_ADS) {
1239 char *sitename = NULL;
1241 /* We need to make sure we know the local site before
1242 doing any DNS queries, as this will restrict the
1243 get_sorted_dc_list() call below to only fetching
1244 DNS records for the correct site. */
1246 /* Find any DC to get the site record.
1247 We deliberately don't care about the
1248 return here. */
1250 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1252 sitename = sitename_fetch(domain->alt_name);
1253 if (sitename) {
1255 /* Do the site-specific AD dns lookup first. */
1256 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1257 &iplist_size, True);
1259 /* Add ips to the DC array. We don't look up the name
1260 of the DC in this function, but we fill in the char*
1261 of the ip now to make the failed connection cache
1262 work */
1263 for ( i=0; i<iplist_size; i++ ) {
1264 char addr[INET6_ADDRSTRLEN];
1265 print_sockaddr(addr, sizeof(addr),
1266 &ip_list[i].ss);
1267 add_one_dc_unique(mem_ctx,
1268 domain->name,
1269 addr,
1270 &ip_list[i].ss,
1271 dcs,
1272 num_dcs);
1275 SAFE_FREE(ip_list);
1276 SAFE_FREE(sitename);
1277 iplist_size = 0;
1280 /* Now we add DCs from the main AD DNS lookup. */
1281 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1282 &iplist_size, True);
1284 for ( i=0; i<iplist_size; i++ ) {
1285 char addr[INET6_ADDRSTRLEN];
1286 print_sockaddr(addr, sizeof(addr),
1287 &ip_list[i].ss);
1288 add_one_dc_unique(mem_ctx,
1289 domain->name,
1290 addr,
1291 &ip_list[i].ss,
1292 dcs,
1293 num_dcs);
1296 SAFE_FREE(ip_list);
1297 iplist_size = 0;
1300 /* Try standard netbios queries if no ADS */
1301 if (*num_dcs == 0) {
1302 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1303 False);
1305 for ( i=0; i<iplist_size; i++ ) {
1306 char addr[INET6_ADDRSTRLEN];
1307 print_sockaddr(addr, sizeof(addr),
1308 &ip_list[i].ss);
1309 add_one_dc_unique(mem_ctx,
1310 domain->name,
1311 addr,
1312 &ip_list[i].ss,
1313 dcs,
1314 num_dcs);
1317 SAFE_FREE(ip_list);
1318 iplist_size = 0;
1321 return True;
1324 /*******************************************************************
1325 Find and make a connection to a DC in the given domain.
1327 @param[in] mem_ctx talloc memory context to allocate from
1328 @param[in] domain domain to find a dc in
1329 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1330 @param[out] pss DC Internet address and port
1331 @param[out] fd fd of the open socket connected to the newly found dc
1332 @return true when a DC connection is made, false otherwise
1333 *******************************************************************/
1335 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1336 struct winbindd_domain *domain,
1337 fstring dcname, struct sockaddr_storage *pss, int *fd)
1339 struct dc_name_ip *dcs = NULL;
1340 int num_dcs = 0;
1342 const char **dcnames = NULL;
1343 int num_dcnames = 0;
1345 struct sockaddr_storage *addrs = NULL;
1346 int num_addrs = 0;
1348 int i;
1349 size_t fd_index;
1351 NTSTATUS status;
1353 *fd = -1;
1355 again:
1356 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1357 return False;
1359 for (i=0; i<num_dcs; i++) {
1361 if (!add_string_to_array(mem_ctx, dcs[i].name,
1362 &dcnames, &num_dcnames)) {
1363 return False;
1365 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1366 &addrs, &num_addrs)) {
1367 return False;
1371 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1372 return False;
1374 if ((addrs == NULL) || (dcnames == NULL))
1375 return False;
1377 status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1378 num_addrs, 0, fd, &fd_index, NULL);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 for (i=0; i<num_dcs; i++) {
1381 char ab[INET6_ADDRSTRLEN];
1382 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1383 DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1384 "domain %s address %s. Error was %s\n",
1385 domain->name, ab, nt_errstr(status) ));
1386 winbind_add_failed_connection_entry(domain,
1387 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1389 return False;
1392 *pss = addrs[fd_index];
1394 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1395 /* Ok, we've got a name for the DC */
1396 fstrcpy(dcname, dcnames[fd_index]);
1397 return True;
1400 /* Try to figure out the name */
1401 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1402 return True;
1405 /* We can not continue without the DC's name */
1406 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1407 NT_STATUS_UNSUCCESSFUL);
1409 /* Throw away all arrays as we're doing this again. */
1410 TALLOC_FREE(dcs);
1411 num_dcs = 0;
1413 TALLOC_FREE(dcnames);
1414 num_dcnames = 0;
1416 TALLOC_FREE(addrs);
1417 num_addrs = 0;
1419 close(*fd);
1420 *fd = -1;
1422 goto again;
1425 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1427 return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1428 domain_name);
1431 static void store_current_dc_in_gencache(const char *domain_name,
1432 const char *dc_name,
1433 struct cli_state *cli)
1435 char addr[INET6_ADDRSTRLEN];
1436 char *key = NULL;
1437 char *value = NULL;
1439 if (cli == NULL) {
1440 return;
1442 if (cli->fd == -1) {
1443 return;
1445 get_peer_addr(cli->fd, addr, sizeof(addr));
1447 key = current_dc_key(talloc_tos(), domain_name);
1448 if (key == NULL) {
1449 goto done;
1452 value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1453 if (value == NULL) {
1454 goto done;
1457 gencache_set(key, value, 0x7fffffff);
1458 done:
1459 TALLOC_FREE(value);
1460 TALLOC_FREE(key);
1463 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1464 const char *domain_name,
1465 char **p_dc_name, char **p_dc_ip)
1467 char *key, *value, *p;
1468 bool ret = false;
1469 char *dc_name = NULL;
1470 char *dc_ip = NULL;
1472 key = current_dc_key(talloc_tos(), domain_name);
1473 if (key == NULL) {
1474 goto done;
1476 if (!gencache_get(key, &value, NULL)) {
1477 goto done;
1479 p = strchr(value, ' ');
1480 if (p == NULL) {
1481 goto done;
1483 dc_ip = talloc_strndup(mem_ctx, value, p - value);
1484 if (dc_ip == NULL) {
1485 goto done;
1487 dc_name = talloc_strdup(mem_ctx, p+1);
1488 if (dc_name == NULL) {
1489 goto done;
1492 if (p_dc_ip != NULL) {
1493 *p_dc_ip = dc_ip;
1494 dc_ip = NULL;
1496 if (p_dc_name != NULL) {
1497 *p_dc_name = dc_name;
1498 dc_name = NULL;
1500 ret = true;
1501 done:
1502 TALLOC_FREE(dc_name);
1503 TALLOC_FREE(dc_ip);
1504 TALLOC_FREE(key);
1505 return ret;
1508 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1509 struct winbindd_cm_conn *new_conn)
1511 TALLOC_CTX *mem_ctx;
1512 NTSTATUS result;
1513 char *saf_servername = saf_fetch( domain->name );
1514 int retries;
1516 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1517 SAFE_FREE(saf_servername);
1518 set_domain_offline(domain);
1519 return NT_STATUS_NO_MEMORY;
1522 /* we have to check the server affinity cache here since
1523 later we select a DC based on response time and not preference */
1525 /* Check the negative connection cache
1526 before talking to it. It going down may have
1527 triggered the reconnection. */
1529 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1531 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1532 saf_servername, domain->name ));
1534 /* convert an ip address to a name */
1535 if (is_ipaddress( saf_servername ) ) {
1536 fstring saf_name;
1537 struct sockaddr_storage ss;
1539 if (!interpret_string_addr(&ss, saf_servername,
1540 AI_NUMERICHOST)) {
1541 return NT_STATUS_UNSUCCESSFUL;
1543 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1544 fstrcpy( domain->dcname, saf_name );
1545 } else {
1546 winbind_add_failed_connection_entry(
1547 domain, saf_servername,
1548 NT_STATUS_UNSUCCESSFUL);
1550 } else {
1551 fstrcpy( domain->dcname, saf_servername );
1554 SAFE_FREE( saf_servername );
1557 for (retries = 0; retries < 3; retries++) {
1558 int fd = -1;
1559 bool retry = False;
1561 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1563 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1564 domain->dcname, domain->name ));
1566 if (*domain->dcname
1567 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1568 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1570 NTSTATUS status;
1572 status = smbsock_connect(&domain->dcaddr, 0,
1573 NULL, -1, NULL, -1,
1574 &fd, NULL);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 fd = -1;
1580 if ((fd == -1)
1581 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1583 /* This is the one place where we will
1584 set the global winbindd offline state
1585 to true, if a "WINBINDD_OFFLINE" entry
1586 is found in the winbindd cache. */
1587 set_global_winbindd_state_offline();
1588 break;
1591 new_conn->cli = NULL;
1593 result = cm_prepare_connection(domain, fd, domain->dcname,
1594 &new_conn->cli, &retry);
1596 if (!retry)
1597 break;
1600 if (NT_STATUS_IS_OK(result)) {
1602 winbindd_set_locator_kdc_envs(domain);
1604 if (domain->online == False) {
1605 /* We're changing state from offline to online. */
1606 set_global_winbindd_state_online();
1608 set_domain_online(domain);
1611 * Much as I hate global state, this seems to be the point
1612 * where we can be certain that we have a proper connection to
1613 * a DC. wbinfo --dc-info needs that information, store it in
1614 * gencache with a looong timeout. This will need revisiting
1615 * once we start to connect to multiple DCs, wbcDcInfo is
1616 * already prepared for that.
1618 store_current_dc_in_gencache(domain->name, domain->dcname,
1619 new_conn->cli);
1620 } else {
1621 /* Ensure we setup the retry handler. */
1622 set_domain_offline(domain);
1625 talloc_destroy(mem_ctx);
1626 return result;
1629 /* Close down all open pipes on a connection. */
1631 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1633 NTSTATUS result;
1635 /* We're closing down a possibly dead
1636 connection. Don't have impossibly long (10s) timeouts. */
1638 if (conn->cli) {
1639 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1642 if (conn->samr_pipe != NULL) {
1643 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1644 dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1645 talloc_tos(),
1646 &conn->sam_connect_handle,
1647 &result);
1649 TALLOC_FREE(conn->samr_pipe);
1650 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1651 if (conn->cli) {
1652 cli_set_timeout(conn->cli, 500);
1656 if (conn->lsa_pipe != NULL) {
1657 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1658 dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1659 talloc_tos(),
1660 &conn->lsa_policy,
1661 &result);
1663 TALLOC_FREE(conn->lsa_pipe);
1664 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1665 if (conn->cli) {
1666 cli_set_timeout(conn->cli, 500);
1670 if (conn->lsa_pipe_tcp != NULL) {
1671 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1672 dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1673 talloc_tos(),
1674 &conn->lsa_policy,
1675 &result);
1677 TALLOC_FREE(conn->lsa_pipe_tcp);
1678 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1679 if (conn->cli) {
1680 cli_set_timeout(conn->cli, 500);
1684 if (conn->netlogon_pipe != NULL) {
1685 TALLOC_FREE(conn->netlogon_pipe);
1686 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1687 if (conn->cli) {
1688 cli_set_timeout(conn->cli, 500);
1692 if (conn->cli) {
1693 cli_shutdown(conn->cli);
1696 conn->cli = NULL;
1699 void close_conns_after_fork(void)
1701 struct winbindd_domain *domain;
1703 for (domain = domain_list(); domain; domain = domain->next) {
1704 struct cli_state *cli = domain->conn.cli;
1707 * first close the low level SMB TCP connection
1708 * so that we don't generate any SMBclose
1709 * requests in invalidate_cm_connection()
1711 if (cli && cli->fd != -1) {
1712 close(domain->conn.cli->fd);
1713 domain->conn.cli->fd = -1;
1716 invalidate_cm_connection(&domain->conn);
1720 static bool connection_ok(struct winbindd_domain *domain)
1722 bool ok;
1724 ok = cli_state_is_connected(domain->conn.cli);
1725 if (!ok) {
1726 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1727 domain->dcname, domain->name));
1728 return False;
1731 if (domain->online == False) {
1732 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1733 return False;
1736 return True;
1739 /* Initialize a new connection up to the RPC BIND.
1740 Bypass online status check so always does network calls. */
1742 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1744 NTSTATUS result;
1746 /* Internal connections never use the network. */
1747 if (domain->internal) {
1748 domain->initialized = True;
1749 return NT_STATUS_OK;
1752 if (!winbindd_can_contact_domain(domain)) {
1753 invalidate_cm_connection(&domain->conn);
1754 domain->initialized = True;
1755 return NT_STATUS_OK;
1758 if (connection_ok(domain)) {
1759 if (!domain->initialized) {
1760 set_dc_type_and_flags(domain);
1762 return NT_STATUS_OK;
1765 invalidate_cm_connection(&domain->conn);
1767 result = cm_open_connection(domain, &domain->conn);
1769 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1770 set_dc_type_and_flags(domain);
1773 return result;
1776 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1778 if (domain->internal) {
1779 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1782 if (domain->initialized && !domain->online) {
1783 /* We check for online status elsewhere. */
1784 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1787 return init_dc_connection_network(domain);
1790 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1792 NTSTATUS status;
1794 status = init_dc_connection(domain);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 return status;
1799 if (!domain->internal && domain->conn.cli == NULL) {
1800 /* happens for trusted domains without inbound trust */
1801 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1804 return NT_STATUS_OK;
1807 /******************************************************************************
1808 Set the trust flags (direction and forest location) for a domain
1809 ******************************************************************************/
1811 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1813 struct winbindd_domain *our_domain;
1814 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1815 WERROR werr;
1816 struct netr_DomainTrustList trusts;
1817 int i;
1818 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1819 NETR_TRUST_FLAG_OUTBOUND |
1820 NETR_TRUST_FLAG_INBOUND);
1821 struct rpc_pipe_client *cli;
1822 TALLOC_CTX *mem_ctx = NULL;
1823 struct dcerpc_binding_handle *b;
1825 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1827 /* Our primary domain doesn't need to worry about trust flags.
1828 Force it to go through the network setup */
1829 if ( domain->primary ) {
1830 return False;
1833 our_domain = find_our_domain();
1835 if ( !connection_ok(our_domain) ) {
1836 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1837 return False;
1840 /* This won't work unless our domain is AD */
1842 if ( !our_domain->active_directory ) {
1843 return False;
1846 /* Use DsEnumerateDomainTrusts to get us the trust direction
1847 and type */
1849 result = cm_connect_netlogon(our_domain, &cli);
1851 if (!NT_STATUS_IS_OK(result)) {
1852 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1853 "a connection to %s for PIPE_NETLOGON (%s)\n",
1854 domain->name, nt_errstr(result)));
1855 return False;
1858 b = cli->binding_handle;
1860 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1861 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1862 return False;
1865 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1866 cli->desthost,
1867 flags,
1868 &trusts,
1869 &werr);
1870 if (!NT_STATUS_IS_OK(result)) {
1871 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1872 "failed to query trusted domain list: %s\n",
1873 nt_errstr(result)));
1874 talloc_destroy(mem_ctx);
1875 return false;
1877 if (!W_ERROR_IS_OK(werr)) {
1878 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1879 "failed to query trusted domain list: %s\n",
1880 win_errstr(werr)));
1881 talloc_destroy(mem_ctx);
1882 return false;
1885 /* Now find the domain name and get the flags */
1887 for ( i=0; i<trusts.count; i++ ) {
1888 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1889 domain->domain_flags = trusts.array[i].trust_flags;
1890 domain->domain_type = trusts.array[i].trust_type;
1891 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1893 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1894 domain->active_directory = True;
1896 /* This flag is only set if the domain is *our*
1897 primary domain and the primary domain is in
1898 native mode */
1900 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1902 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1903 "native mode.\n", domain->name,
1904 domain->native_mode ? "" : "NOT "));
1906 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1907 "running active directory.\n", domain->name,
1908 domain->active_directory ? "" : "NOT "));
1911 domain->initialized = True;
1913 break;
1917 talloc_destroy( mem_ctx );
1919 return domain->initialized;
1922 /******************************************************************************
1923 We can 'sense' certain things about the DC by it's replies to certain
1924 questions.
1926 This tells us if this particular remote server is Active Directory, and if it
1927 is native mode.
1928 ******************************************************************************/
1930 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1932 NTSTATUS status, result;
1933 WERROR werr;
1934 TALLOC_CTX *mem_ctx = NULL;
1935 struct rpc_pipe_client *cli = NULL;
1936 struct policy_handle pol;
1937 union dssetup_DsRoleInfo info;
1938 union lsa_PolicyInformation *lsa_info = NULL;
1940 if (!connection_ok(domain)) {
1941 return;
1944 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1945 domain->name);
1946 if (!mem_ctx) {
1947 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1948 return;
1951 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1953 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
1954 &ndr_table_dssetup.syntax_id,
1955 &cli);
1957 if (!NT_STATUS_IS_OK(status)) {
1958 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1959 "PI_DSSETUP on domain %s: (%s)\n",
1960 domain->name, nt_errstr(status)));
1962 /* if this is just a non-AD domain we need to continue
1963 * identifying so that we can in the end return with
1964 * domain->initialized = True - gd */
1966 goto no_dssetup;
1969 status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
1970 DS_ROLE_BASIC_INFORMATION,
1971 &info,
1972 &werr);
1973 TALLOC_FREE(cli);
1975 if (NT_STATUS_IS_OK(status)) {
1976 result = werror_to_ntstatus(werr);
1978 if (!NT_STATUS_IS_OK(status)) {
1979 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1980 "on domain %s failed: (%s)\n",
1981 domain->name, nt_errstr(status)));
1983 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1984 * every opcode on the DSSETUP pipe, continue with
1985 * no_dssetup mode here as well to get domain->initialized
1986 * set - gd */
1988 if (NT_STATUS_V(status) == DCERPC_FAULT_OP_RNG_ERROR) {
1989 goto no_dssetup;
1992 TALLOC_FREE(mem_ctx);
1993 return;
1996 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1997 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1998 domain->native_mode = True;
1999 } else {
2000 domain->native_mode = False;
2003 no_dssetup:
2004 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2005 &ndr_table_lsarpc.syntax_id, &cli);
2007 if (!NT_STATUS_IS_OK(status)) {
2008 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2009 "PI_LSARPC on domain %s: (%s)\n",
2010 domain->name, nt_errstr(status)));
2011 TALLOC_FREE(cli);
2012 TALLOC_FREE(mem_ctx);
2013 return;
2016 status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2017 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2019 if (NT_STATUS_IS_OK(status)) {
2020 /* This particular query is exactly what Win2k clients use
2021 to determine that the DC is active directory */
2022 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2023 &pol,
2024 LSA_POLICY_INFO_DNS,
2025 &lsa_info,
2026 &result);
2029 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2030 domain->active_directory = True;
2032 if (lsa_info->dns.name.string) {
2033 fstrcpy(domain->name, lsa_info->dns.name.string);
2036 if (lsa_info->dns.dns_domain.string) {
2037 fstrcpy(domain->alt_name,
2038 lsa_info->dns.dns_domain.string);
2041 /* See if we can set some domain trust flags about
2042 ourself */
2044 if (lsa_info->dns.dns_forest.string) {
2045 fstrcpy(domain->forest_name,
2046 lsa_info->dns.dns_forest.string);
2048 if (strequal(domain->forest_name, domain->alt_name)) {
2049 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2053 if (lsa_info->dns.sid) {
2054 sid_copy(&domain->sid, lsa_info->dns.sid);
2056 } else {
2057 domain->active_directory = False;
2059 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2060 SEC_FLAG_MAXIMUM_ALLOWED,
2061 &pol);
2063 if (!NT_STATUS_IS_OK(status)) {
2064 goto done;
2067 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2068 &pol,
2069 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2070 &lsa_info,
2071 &result);
2072 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2074 if (lsa_info->account_domain.name.string) {
2075 fstrcpy(domain->name,
2076 lsa_info->account_domain.name.string);
2079 if (lsa_info->account_domain.sid) {
2080 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2084 done:
2086 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2087 domain->name, domain->native_mode ? "" : "NOT "));
2089 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2090 domain->name, domain->active_directory ? "" : "NOT "));
2092 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2093 domain->can_do_validation6 = domain->active_directory;
2095 TALLOC_FREE(cli);
2097 TALLOC_FREE(mem_ctx);
2099 domain->initialized = True;
2102 /**********************************************************************
2103 Set the domain_flags (trust attributes, domain operating modes, etc...
2104 ***********************************************************************/
2106 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2108 /* we always have to contact our primary domain */
2110 if ( domain->primary ) {
2111 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2112 "primary domain\n"));
2113 set_dc_type_and_flags_connect( domain );
2114 return;
2117 /* Use our DC to get the information if possible */
2119 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2120 /* Otherwise, fallback to contacting the
2121 domain directly */
2122 set_dc_type_and_flags_connect( domain );
2125 return;
2130 /**********************************************************************
2131 ***********************************************************************/
2133 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2134 struct netlogon_creds_CredentialState **ppdc)
2136 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2137 struct rpc_pipe_client *netlogon_pipe;
2139 if (lp_client_schannel() == False) {
2140 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2143 result = cm_connect_netlogon(domain, &netlogon_pipe);
2144 if (!NT_STATUS_IS_OK(result)) {
2145 return result;
2148 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2149 netlogon pipe. */
2151 if (!domain->conn.netlogon_pipe->dc) {
2152 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2155 *ppdc = domain->conn.netlogon_pipe->dc;
2156 return NT_STATUS_OK;
2159 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2160 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2162 struct winbindd_cm_conn *conn;
2163 NTSTATUS status, result;
2164 struct netlogon_creds_CredentialState *p_creds;
2165 char *machine_password = NULL;
2166 char *machine_account = NULL;
2167 char *domain_name = NULL;
2169 if (sid_check_is_domain(&domain->sid)) {
2170 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2173 status = init_dc_connection_rpc(domain);
2174 if (!NT_STATUS_IS_OK(status)) {
2175 return status;
2178 conn = &domain->conn;
2180 if (rpccli_is_connected(conn->samr_pipe)) {
2181 goto done;
2184 TALLOC_FREE(conn->samr_pipe);
2187 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2188 * sign and sealed pipe using the machine account password by
2189 * preference. If we can't - try schannel, if that fails, try
2190 * anonymous.
2193 if ((conn->cli->user_name[0] == '\0') ||
2194 (conn->cli->domain[0] == '\0') ||
2195 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2197 status = get_trust_creds(domain, &machine_password,
2198 &machine_account, NULL);
2199 if (!NT_STATUS_IS_OK(status)) {
2200 DEBUG(10, ("cm_connect_sam: No no user available for "
2201 "domain %s, trying schannel\n", conn->cli->domain));
2202 goto schannel;
2204 domain_name = domain->name;
2205 } else {
2206 machine_password = SMB_STRDUP(conn->cli->password);
2207 machine_account = SMB_STRDUP(conn->cli->user_name);
2208 domain_name = conn->cli->domain;
2211 if (!machine_password || !machine_account) {
2212 status = NT_STATUS_NO_MEMORY;
2213 goto done;
2216 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2217 authenticated SAMR pipe with sign & seal. */
2218 status = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2219 &ndr_table_samr.syntax_id,
2220 NCACN_NP,
2221 DCERPC_AUTH_LEVEL_PRIVACY,
2222 domain_name,
2223 machine_account,
2224 machine_password,
2225 &conn->samr_pipe);
2227 if (!NT_STATUS_IS_OK(status)) {
2228 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2229 "pipe for domain %s using NTLMSSP "
2230 "authenticated pipe: user %s\\%s. Error was "
2231 "%s\n", domain->name, domain_name,
2232 machine_account, nt_errstr(status)));
2233 goto schannel;
2236 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2237 "domain %s using NTLMSSP authenticated "
2238 "pipe: user %s\\%s\n", domain->name,
2239 domain_name, machine_account));
2241 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2242 conn->samr_pipe->desthost,
2243 SEC_FLAG_MAXIMUM_ALLOWED,
2244 &conn->sam_connect_handle,
2245 &result);
2246 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2247 goto open_domain;
2249 if (NT_STATUS_IS_OK(status)) {
2250 status = result;
2253 DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2254 "failed for domain %s, error was %s. Trying schannel\n",
2255 domain->name, nt_errstr(status) ));
2256 TALLOC_FREE(conn->samr_pipe);
2258 schannel:
2260 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2262 status = cm_get_schannel_creds(domain, &p_creds);
2263 if (!NT_STATUS_IS_OK(status)) {
2264 /* If this call fails - conn->cli can now be NULL ! */
2265 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2266 "for domain %s (error %s), trying anon\n",
2267 domain->name,
2268 nt_errstr(status) ));
2269 goto anonymous;
2271 status = cli_rpc_pipe_open_schannel_with_key
2272 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2273 DCERPC_AUTH_LEVEL_PRIVACY,
2274 domain->name, &p_creds, &conn->samr_pipe);
2276 if (!NT_STATUS_IS_OK(status)) {
2277 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2278 "domain %s using schannel. Error was %s\n",
2279 domain->name, nt_errstr(status) ));
2280 goto anonymous;
2282 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2283 "schannel.\n", domain->name ));
2285 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2286 conn->samr_pipe->desthost,
2287 SEC_FLAG_MAXIMUM_ALLOWED,
2288 &conn->sam_connect_handle,
2289 &result);
2290 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2291 goto open_domain;
2293 if (NT_STATUS_IS_OK(status)) {
2294 status = result;
2296 DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2297 "for domain %s, error was %s. Trying anonymous\n",
2298 domain->name, nt_errstr(status) ));
2299 TALLOC_FREE(conn->samr_pipe);
2301 anonymous:
2303 /* Finally fall back to anonymous. */
2304 status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2305 &conn->samr_pipe);
2307 if (!NT_STATUS_IS_OK(status)) {
2308 goto done;
2311 status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2312 conn->samr_pipe->desthost,
2313 SEC_FLAG_MAXIMUM_ALLOWED,
2314 &conn->sam_connect_handle,
2315 &result);
2316 if (!NT_STATUS_IS_OK(status)) {
2317 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2318 "for domain %s Error was %s\n",
2319 domain->name, nt_errstr(status) ));
2320 goto done;
2322 if (!NT_STATUS_IS_OK(result)) {
2323 status = result;
2324 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2325 "for domain %s Error was %s\n",
2326 domain->name, nt_errstr(result)));
2327 goto done;
2330 open_domain:
2331 status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2332 mem_ctx,
2333 &conn->sam_connect_handle,
2334 SEC_FLAG_MAXIMUM_ALLOWED,
2335 &domain->sid,
2336 &conn->sam_domain_handle,
2337 &result);
2338 if (!NT_STATUS_IS_OK(status)) {
2339 goto done;
2342 status = result;
2343 done:
2345 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2347 * if we got access denied, we might just have no access rights
2348 * to talk to the remote samr server server (e.g. when we are a
2349 * PDC and we are connecting a w2k8 pdc via an interdomain
2350 * trust). In that case do not invalidate the whole connection
2351 * stack
2353 TALLOC_FREE(conn->samr_pipe);
2354 ZERO_STRUCT(conn->sam_domain_handle);
2355 return status;
2356 } else if (!NT_STATUS_IS_OK(status)) {
2357 invalidate_cm_connection(conn);
2358 return status;
2361 *cli = conn->samr_pipe;
2362 *sam_handle = conn->sam_domain_handle;
2363 SAFE_FREE(machine_password);
2364 SAFE_FREE(machine_account);
2365 return status;
2368 /**********************************************************************
2369 open an schanneld ncacn_ip_tcp connection to LSA
2370 ***********************************************************************/
2372 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2373 TALLOC_CTX *mem_ctx,
2374 struct rpc_pipe_client **cli)
2376 struct winbindd_cm_conn *conn;
2377 struct netlogon_creds_CredentialState *creds;
2378 NTSTATUS status;
2380 DEBUG(10,("cm_connect_lsa_tcp\n"));
2382 status = init_dc_connection_rpc(domain);
2383 if (!NT_STATUS_IS_OK(status)) {
2384 return status;
2387 conn = &domain->conn;
2389 if (conn->lsa_pipe_tcp &&
2390 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2391 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2392 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2393 goto done;
2396 TALLOC_FREE(conn->lsa_pipe_tcp);
2398 status = cm_get_schannel_creds(domain, &creds);
2399 if (!NT_STATUS_IS_OK(status)) {
2400 goto done;
2403 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2404 &ndr_table_lsarpc.syntax_id,
2405 NCACN_IP_TCP,
2406 DCERPC_AUTH_LEVEL_PRIVACY,
2407 domain->name,
2408 &creds,
2409 &conn->lsa_pipe_tcp);
2410 if (!NT_STATUS_IS_OK(status)) {
2411 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2412 nt_errstr(status)));
2413 goto done;
2416 done:
2417 if (!NT_STATUS_IS_OK(status)) {
2418 TALLOC_FREE(conn->lsa_pipe_tcp);
2419 return status;
2422 *cli = conn->lsa_pipe_tcp;
2424 return status;
2427 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2428 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2430 struct winbindd_cm_conn *conn;
2431 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2432 struct netlogon_creds_CredentialState *p_creds;
2434 result = init_dc_connection_rpc(domain);
2435 if (!NT_STATUS_IS_OK(result))
2436 return result;
2438 conn = &domain->conn;
2440 if (rpccli_is_connected(conn->lsa_pipe)) {
2441 goto done;
2444 TALLOC_FREE(conn->lsa_pipe);
2446 if ((conn->cli->user_name[0] == '\0') ||
2447 (conn->cli->domain[0] == '\0') ||
2448 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2449 DEBUG(10, ("cm_connect_lsa: No no user available for "
2450 "domain %s, trying schannel\n", conn->cli->domain));
2451 goto schannel;
2454 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2455 * authenticated LSA pipe with sign & seal. */
2456 result = cli_rpc_pipe_open_spnego_ntlmssp
2457 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2458 DCERPC_AUTH_LEVEL_PRIVACY,
2459 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2460 &conn->lsa_pipe);
2462 if (!NT_STATUS_IS_OK(result)) {
2463 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2464 "domain %s using NTLMSSP authenticated pipe: user "
2465 "%s\\%s. Error was %s. Trying schannel.\n",
2466 domain->name, conn->cli->domain,
2467 conn->cli->user_name, nt_errstr(result)));
2468 goto schannel;
2471 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2472 "NTLMSSP authenticated pipe: user %s\\%s\n",
2473 domain->name, conn->cli->domain, conn->cli->user_name ));
2475 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2476 SEC_FLAG_MAXIMUM_ALLOWED,
2477 &conn->lsa_policy);
2478 if (NT_STATUS_IS_OK(result)) {
2479 goto done;
2482 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2483 "schannel\n"));
2485 TALLOC_FREE(conn->lsa_pipe);
2487 schannel:
2489 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2491 result = cm_get_schannel_creds(domain, &p_creds);
2492 if (!NT_STATUS_IS_OK(result)) {
2493 /* If this call fails - conn->cli can now be NULL ! */
2494 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2495 "for domain %s (error %s), trying anon\n",
2496 domain->name,
2497 nt_errstr(result) ));
2498 goto anonymous;
2500 result = cli_rpc_pipe_open_schannel_with_key
2501 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2502 DCERPC_AUTH_LEVEL_PRIVACY,
2503 domain->name, &p_creds, &conn->lsa_pipe);
2505 if (!NT_STATUS_IS_OK(result)) {
2506 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2507 "domain %s using schannel. Error was %s\n",
2508 domain->name, nt_errstr(result) ));
2509 goto anonymous;
2511 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2512 "schannel.\n", domain->name ));
2514 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2515 SEC_FLAG_MAXIMUM_ALLOWED,
2516 &conn->lsa_policy);
2517 if (NT_STATUS_IS_OK(result)) {
2518 goto done;
2521 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2522 "anonymous\n"));
2524 TALLOC_FREE(conn->lsa_pipe);
2526 anonymous:
2528 result = cli_rpc_pipe_open_noauth(conn->cli,
2529 &ndr_table_lsarpc.syntax_id,
2530 &conn->lsa_pipe);
2531 if (!NT_STATUS_IS_OK(result)) {
2532 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2533 goto done;
2536 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2537 SEC_FLAG_MAXIMUM_ALLOWED,
2538 &conn->lsa_policy);
2539 done:
2540 if (!NT_STATUS_IS_OK(result)) {
2541 invalidate_cm_connection(conn);
2542 return result;
2545 *cli = conn->lsa_pipe;
2546 *lsa_policy = conn->lsa_policy;
2547 return result;
2550 /****************************************************************************
2551 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2552 session key stored in conn->netlogon_pipe->dc->sess_key.
2553 ****************************************************************************/
2555 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2556 struct rpc_pipe_client **cli)
2558 struct winbindd_cm_conn *conn;
2559 NTSTATUS result;
2561 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2562 uint8 mach_pwd[16];
2563 enum netr_SchannelType sec_chan_type;
2564 const char *account_name;
2565 struct rpc_pipe_client *netlogon_pipe = NULL;
2567 *cli = NULL;
2569 result = init_dc_connection_rpc(domain);
2570 if (!NT_STATUS_IS_OK(result)) {
2571 return result;
2574 conn = &domain->conn;
2576 if (rpccli_is_connected(conn->netlogon_pipe)) {
2577 *cli = conn->netlogon_pipe;
2578 return NT_STATUS_OK;
2581 TALLOC_FREE(conn->netlogon_pipe);
2583 result = cli_rpc_pipe_open_noauth(conn->cli,
2584 &ndr_table_netlogon.syntax_id,
2585 &netlogon_pipe);
2586 if (!NT_STATUS_IS_OK(result)) {
2587 return result;
2590 if ((!IS_DC) && (!domain->primary)) {
2591 /* Clear the schannel request bit and drop down */
2592 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2593 goto no_schannel;
2596 if (lp_client_schannel() != False) {
2597 neg_flags |= NETLOGON_NEG_SCHANNEL;
2600 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2601 &sec_chan_type))
2603 TALLOC_FREE(netlogon_pipe);
2604 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2607 result = rpccli_netlogon_setup_creds(
2608 netlogon_pipe,
2609 domain->dcname, /* server name. */
2610 domain->name, /* domain name */
2611 global_myname(), /* client name */
2612 account_name, /* machine account */
2613 mach_pwd, /* machine password */
2614 sec_chan_type, /* from get_trust_pw */
2615 &neg_flags);
2617 if (!NT_STATUS_IS_OK(result)) {
2618 TALLOC_FREE(netlogon_pipe);
2619 return result;
2622 if ((lp_client_schannel() == True) &&
2623 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2624 DEBUG(3, ("Server did not offer schannel\n"));
2625 TALLOC_FREE(netlogon_pipe);
2626 return NT_STATUS_ACCESS_DENIED;
2629 no_schannel:
2630 if ((lp_client_schannel() == False) ||
2631 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2633 * NetSamLogonEx only works for schannel
2635 domain->can_do_samlogon_ex = False;
2637 /* We're done - just keep the existing connection to NETLOGON
2638 * open */
2639 conn->netlogon_pipe = netlogon_pipe;
2640 *cli = conn->netlogon_pipe;
2641 return NT_STATUS_OK;
2644 /* Using the credentials from the first pipe, open a signed and sealed
2645 second netlogon pipe. The session key is stored in the schannel
2646 part of the new pipe auth struct.
2649 result = cli_rpc_pipe_open_schannel_with_key(
2650 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2651 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2652 &conn->netlogon_pipe);
2654 /* We can now close the initial netlogon pipe. */
2655 TALLOC_FREE(netlogon_pipe);
2657 if (!NT_STATUS_IS_OK(result)) {
2658 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2659 "was %s\n", nt_errstr(result)));
2661 invalidate_cm_connection(conn);
2662 return result;
2666 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2667 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2668 * supported). We used to only try SamLogonEx for AD, but
2669 * Samba DCs can also do it. And because we don't distinguish
2670 * between Samba and NT4, always try it once.
2672 domain->can_do_samlogon_ex = true;
2674 *cli = conn->netlogon_pipe;
2675 return NT_STATUS_OK;
2678 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2679 void *private_data,
2680 uint32_t msg_type,
2681 struct server_id server_id,
2682 DATA_BLOB *data)
2684 struct winbindd_domain *domain;
2685 char *freeit = NULL;
2686 char *addr;
2688 if ((data == NULL)
2689 || (data->data == NULL)
2690 || (data->length == 0)
2691 || (data->data[data->length-1] != '\0')) {
2692 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2693 "string\n"));
2694 return;
2697 addr = (char *)data->data;
2698 DEBUG(10, ("IP %s dropped\n", addr));
2700 if (!is_ipaddress(addr)) {
2701 char *slash;
2703 * Some code sends us ip addresses with the /netmask
2704 * suffix
2706 slash = strchr(addr, '/');
2707 if (slash == NULL) {
2708 DEBUG(1, ("invalid msg_ip_dropped message: %s",
2709 addr));
2710 return;
2712 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2713 if (freeit == NULL) {
2714 DEBUG(1, ("talloc failed\n"));
2715 return;
2717 addr = freeit;
2718 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2721 for (domain = domain_list(); domain != NULL; domain = domain->next) {
2722 char sockaddr[INET6_ADDRSTRLEN];
2723 if (domain->conn.cli == NULL) {
2724 continue;
2726 if (domain->conn.cli->fd == -1) {
2727 continue;
2729 client_socket_addr(domain->conn.cli->fd, sockaddr,
2730 sizeof(sockaddr));
2731 if (strequal(sockaddr, addr)) {
2732 close(domain->conn.cli->fd);
2733 domain->conn.cli->fd = -1;
2736 TALLOC_FREE(freeit);