s3/s4: merge msleep and smb_msleep
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob8f95031007d9ca358fbe2479462cb13d3d7b3777
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/cli_netlogon.h"
65 #include "rpc_client/cli_netlogon.h"
66 #include "../librpc/gen_ndr/cli_samr.h"
67 #include "../librpc/gen_ndr/cli_lsa.h"
68 #include "rpc_client/cli_lsarpc.h"
69 #include "../librpc/gen_ndr/cli_dssetup.h"
70 #include "libads/sitename_cache.h"
71 #include "librpc/gen_ndr/messaging.h"
72 #include "libsmb/clidgram.h"
73 #include "ads.h"
74 #include "secrets.h"
76 #undef DBGC_CLASS
77 #define DBGC_CLASS DBGC_WINBIND
79 struct dc_name_ip {
80 fstring name;
81 struct sockaddr_storage ss;
84 extern struct winbindd_methods reconnect_methods;
85 extern bool override_logfile;
87 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
88 static void set_dc_type_and_flags( struct winbindd_domain *domain );
89 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
90 struct dc_name_ip **dcs, int *num_dcs);
92 /****************************************************************
93 Child failed to find DC's. Reschedule check.
94 ****************************************************************/
96 static void msg_failed_to_go_online(struct messaging_context *msg,
97 void *private_data,
98 uint32_t msg_type,
99 struct server_id server_id,
100 DATA_BLOB *data)
102 struct winbindd_domain *domain;
103 const char *domainname = (const char *)data->data;
105 if (data->data == NULL || data->length == 0) {
106 return;
109 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
111 for (domain = domain_list(); domain; domain = domain->next) {
112 if (domain->internal) {
113 continue;
116 if (strequal(domain->name, domainname)) {
117 if (domain->online) {
118 /* We're already online, ignore. */
119 DEBUG(5,("msg_fail_to_go_online: domain %s "
120 "already online.\n", domainname));
121 continue;
124 /* Reschedule the online check. */
125 set_domain_offline(domain);
126 break;
131 /****************************************************************
132 Actually cause a reconnect from a message.
133 ****************************************************************/
135 static void msg_try_to_go_online(struct messaging_context *msg,
136 void *private_data,
137 uint32_t msg_type,
138 struct server_id server_id,
139 DATA_BLOB *data)
141 struct winbindd_domain *domain;
142 const char *domainname = (const char *)data->data;
144 if (data->data == NULL || data->length == 0) {
145 return;
148 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
150 for (domain = domain_list(); domain; domain = domain->next) {
151 if (domain->internal) {
152 continue;
155 if (strequal(domain->name, domainname)) {
157 if (domain->online) {
158 /* We're already online, ignore. */
159 DEBUG(5,("msg_try_to_go_online: domain %s "
160 "already online.\n", domainname));
161 continue;
164 /* This call takes care of setting the online
165 flag to true if we connected, or re-adding
166 the offline handler if false. Bypasses online
167 check so always does network calls. */
169 init_dc_connection_network(domain);
170 break;
175 /****************************************************************
176 Fork a child to try and contact a DC. Do this as contacting a
177 DC requires blocking lookups and we don't want to block our
178 parent.
179 ****************************************************************/
181 static bool fork_child_dc_connect(struct winbindd_domain *domain)
183 struct dc_name_ip *dcs = NULL;
184 int num_dcs = 0;
185 TALLOC_CTX *mem_ctx = NULL;
186 pid_t parent_pid = sys_getpid();
187 char *lfile = NULL;
189 if (domain->dc_probe_pid != (pid_t)-1) {
191 * We might already have a DC probe
192 * child working, check.
194 if (process_exists_by_pid(domain->dc_probe_pid)) {
195 DEBUG(10,("fork_child_dc_connect: pid %u already "
196 "checking for DC's.\n",
197 (unsigned int)domain->dc_probe_pid));
198 return true;
200 domain->dc_probe_pid = (pid_t)-1;
203 domain->dc_probe_pid = sys_fork();
205 if (domain->dc_probe_pid == (pid_t)-1) {
206 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
207 return False;
210 if (domain->dc_probe_pid != (pid_t)0) {
211 /* Parent */
212 messaging_register(winbind_messaging_context(), NULL,
213 MSG_WINBIND_TRY_TO_GO_ONLINE,
214 msg_try_to_go_online);
215 messaging_register(winbind_messaging_context(), NULL,
216 MSG_WINBIND_FAILED_TO_GO_ONLINE,
217 msg_failed_to_go_online);
218 return True;
221 /* Child. */
223 /* Leave messages blocked - we will never process one. */
225 if (!override_logfile) {
226 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
227 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
228 _exit(1);
232 if (!winbindd_reinit_after_fork(lfile)) {
233 messaging_send_buf(winbind_messaging_context(),
234 pid_to_procid(parent_pid),
235 MSG_WINBIND_FAILED_TO_GO_ONLINE,
236 (uint8 *)domain->name,
237 strlen(domain->name)+1);
238 _exit(1);
240 SAFE_FREE(lfile);
242 mem_ctx = talloc_init("fork_child_dc_connect");
243 if (!mem_ctx) {
244 DEBUG(0,("talloc_init failed.\n"));
245 messaging_send_buf(winbind_messaging_context(),
246 pid_to_procid(parent_pid),
247 MSG_WINBIND_FAILED_TO_GO_ONLINE,
248 (uint8 *)domain->name,
249 strlen(domain->name)+1);
250 _exit(1);
253 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
254 /* Still offline ? Can't find DC's. */
255 messaging_send_buf(winbind_messaging_context(),
256 pid_to_procid(parent_pid),
257 MSG_WINBIND_FAILED_TO_GO_ONLINE,
258 (uint8 *)domain->name,
259 strlen(domain->name)+1);
260 _exit(0);
263 /* We got a DC. Send a message to our parent to get it to
264 try and do the same. */
266 messaging_send_buf(winbind_messaging_context(),
267 pid_to_procid(parent_pid),
268 MSG_WINBIND_TRY_TO_GO_ONLINE,
269 (uint8 *)domain->name,
270 strlen(domain->name)+1);
271 _exit(0);
274 /****************************************************************
275 Handler triggered if we're offline to try and detect a DC.
276 ****************************************************************/
278 static void check_domain_online_handler(struct event_context *ctx,
279 struct timed_event *te,
280 struct timeval now,
281 void *private_data)
283 struct winbindd_domain *domain =
284 (struct winbindd_domain *)private_data;
286 DEBUG(10,("check_domain_online_handler: called for domain "
287 "%s (online = %s)\n", domain->name,
288 domain->online ? "True" : "False" ));
290 TALLOC_FREE(domain->check_online_event);
292 /* Are we still in "startup" mode ? */
294 if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
295 /* No longer in "startup" mode. */
296 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
297 domain->name ));
298 domain->startup = False;
301 /* We've been told to stay offline, so stay
302 that way. */
304 if (get_global_winbindd_state_offline()) {
305 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
306 domain->name ));
307 return;
310 /* Fork a child to test if it can contact a DC.
311 If it can then send ourselves a message to
312 cause a reconnect. */
314 fork_child_dc_connect(domain);
317 /****************************************************************
318 If we're still offline setup the timeout check.
319 ****************************************************************/
321 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
323 int wbr = lp_winbind_reconnect_delay();
325 if (domain->startup) {
326 domain->check_online_timeout = 10;
327 } else if (domain->check_online_timeout < wbr) {
328 domain->check_online_timeout = wbr;
332 /****************************************************************
333 Set domain offline and also add handler to put us back online
334 if we detect a DC.
335 ****************************************************************/
337 void set_domain_offline(struct winbindd_domain *domain)
339 DEBUG(10,("set_domain_offline: called for domain %s\n",
340 domain->name ));
342 TALLOC_FREE(domain->check_online_event);
344 if (domain->internal) {
345 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
346 domain->name ));
347 return;
350 domain->online = False;
352 /* Offline domains are always initialized. They're
353 re-initialized when they go back online. */
355 domain->initialized = True;
357 /* We only add the timeout handler that checks and
358 allows us to go back online when we've not
359 been told to remain offline. */
361 if (get_global_winbindd_state_offline()) {
362 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
363 domain->name ));
364 return;
367 /* If we're in startup mode, check again in 10 seconds, not in
368 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
370 calc_new_online_timeout_check(domain);
372 domain->check_online_event = event_add_timed(winbind_event_context(),
373 NULL,
374 timeval_current_ofs(domain->check_online_timeout,0),
375 check_domain_online_handler,
376 domain);
378 /* The above *has* to succeed for winbindd to work. */
379 if (!domain->check_online_event) {
380 smb_panic("set_domain_offline: failed to add online handler");
383 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
384 domain->name ));
386 /* Send an offline message to the idmap child when our
387 primary domain goes offline */
389 if ( domain->primary ) {
390 struct winbindd_child *idmap = idmap_child();
392 if ( idmap->pid != 0 ) {
393 messaging_send_buf(winbind_messaging_context(),
394 pid_to_procid(idmap->pid),
395 MSG_WINBIND_OFFLINE,
396 (uint8 *)domain->name,
397 strlen(domain->name)+1);
401 return;
404 /****************************************************************
405 Set domain online - if allowed.
406 ****************************************************************/
408 static void set_domain_online(struct winbindd_domain *domain)
410 DEBUG(10,("set_domain_online: called for domain %s\n",
411 domain->name ));
413 if (domain->internal) {
414 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
415 domain->name ));
416 return;
419 if (get_global_winbindd_state_offline()) {
420 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
421 domain->name ));
422 return;
425 winbindd_set_locator_kdc_envs(domain);
427 /* If we are waiting to get a krb5 ticket, trigger immediately. */
428 ccache_regain_all_now();
430 /* Ok, we're out of any startup mode now... */
431 domain->startup = False;
433 if (domain->online == False) {
434 /* We were offline - now we're online. We default to
435 using the MS-RPC backend if we started offline,
436 and if we're going online for the first time we
437 should really re-initialize the backends and the
438 checks to see if we're talking to an AD or NT domain.
441 domain->initialized = False;
443 /* 'reconnect_methods' is the MS-RPC backend. */
444 if (domain->backend == &reconnect_methods) {
445 domain->backend = NULL;
449 /* Ensure we have no online timeout checks. */
450 domain->check_online_timeout = 0;
451 TALLOC_FREE(domain->check_online_event);
453 /* Ensure we ignore any pending child messages. */
454 messaging_deregister(winbind_messaging_context(),
455 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
456 messaging_deregister(winbind_messaging_context(),
457 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
459 domain->online = True;
461 /* Send an online message to the idmap child when our
462 primary domain comes online */
464 if ( domain->primary ) {
465 struct winbindd_child *idmap = idmap_child();
467 if ( idmap->pid != 0 ) {
468 messaging_send_buf(winbind_messaging_context(),
469 pid_to_procid(idmap->pid),
470 MSG_WINBIND_ONLINE,
471 (uint8 *)domain->name,
472 strlen(domain->name)+1);
476 return;
479 /****************************************************************
480 Requested to set a domain online.
481 ****************************************************************/
483 void set_domain_online_request(struct winbindd_domain *domain)
485 struct timeval tev;
487 DEBUG(10,("set_domain_online_request: called for domain %s\n",
488 domain->name ));
490 if (get_global_winbindd_state_offline()) {
491 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
492 domain->name ));
493 return;
496 if (domain->internal) {
497 DEBUG(10, ("set_domain_online_request: Internal domains are "
498 "always online\n"));
499 return;
502 /* We've been told it's safe to go online and
503 try and connect to a DC. But I don't believe it
504 because network manager seems to lie.
505 Wait at least 5 seconds. Heuristics suck... */
508 GetTimeOfDay(&tev);
510 /* Go into "startup" mode again. */
511 domain->startup_time = time_mono(NULL);
512 domain->startup = True;
514 tev.tv_sec += 5;
516 if (!domain->check_online_event) {
517 /* If we've come from being globally offline we
518 don't have a check online event handler set.
519 We need to add one now we're trying to go
520 back online. */
522 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
523 domain->name ));
526 TALLOC_FREE(domain->check_online_event);
528 domain->check_online_event = event_add_timed(winbind_event_context(),
529 NULL,
530 tev,
531 check_domain_online_handler,
532 domain);
534 /* The above *has* to succeed for winbindd to work. */
535 if (!domain->check_online_event) {
536 smb_panic("set_domain_online_request: failed to add online handler");
540 /****************************************************************
541 Add -ve connection cache entries for domain and realm.
542 ****************************************************************/
544 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
545 const char *server,
546 NTSTATUS result)
548 add_failed_connection_entry(domain->name, server, result);
549 /* If this was the saf name for the last thing we talked to,
550 remove it. */
551 saf_delete(domain->name);
552 if (*domain->alt_name) {
553 add_failed_connection_entry(domain->alt_name, server, result);
554 saf_delete(domain->alt_name);
556 winbindd_unset_locator_kdc_env(domain);
559 /* Choose between anonymous or authenticated connections. We need to use
560 an authenticated connection if DCs have the RestrictAnonymous registry
561 entry set > 0, or the "Additional restrictions for anonymous
562 connections" set in the win2k Local Security Policy.
564 Caller to free() result in domain, username, password
567 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
569 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
570 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
571 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
573 if (*username && **username) {
575 if (!*domain || !**domain)
576 *domain = smb_xstrdup(lp_workgroup());
578 if (!*password || !**password)
579 *password = smb_xstrdup("");
581 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
582 *domain, *username));
584 } else {
585 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
586 *username = smb_xstrdup("");
587 *domain = smb_xstrdup("");
588 *password = smb_xstrdup("");
592 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
593 fstring dcname,
594 struct sockaddr_storage *dc_ss)
596 struct winbindd_domain *our_domain = NULL;
597 struct rpc_pipe_client *netlogon_pipe = NULL;
598 NTSTATUS result;
599 WERROR werr;
600 TALLOC_CTX *mem_ctx;
601 unsigned int orig_timeout;
602 const char *tmp = NULL;
603 const char *p;
605 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
606 * moment.... */
608 if (IS_DC) {
609 return False;
612 if (domain->primary) {
613 return False;
616 our_domain = find_our_domain();
618 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
619 return False;
622 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
623 if (!NT_STATUS_IS_OK(result)) {
624 talloc_destroy(mem_ctx);
625 return False;
628 /* This call can take a long time - allow the server to time out.
629 35 seconds should do it. */
631 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
633 if (our_domain->active_directory) {
634 struct netr_DsRGetDCNameInfo *domain_info = NULL;
636 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
637 mem_ctx,
638 our_domain->dcname,
639 domain->name,
640 NULL,
641 NULL,
642 DS_RETURN_DNS_NAME,
643 &domain_info,
644 &werr);
645 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
646 tmp = talloc_strdup(
647 mem_ctx, domain_info->dc_unc);
648 if (tmp == NULL) {
649 DEBUG(0, ("talloc_strdup failed\n"));
650 talloc_destroy(mem_ctx);
651 return false;
653 if (strlen(domain->alt_name) == 0) {
654 fstrcpy(domain->alt_name,
655 domain_info->domain_name);
657 if (strlen(domain->forest_name) == 0) {
658 fstrcpy(domain->forest_name,
659 domain_info->forest_name);
662 } else {
663 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
664 our_domain->dcname,
665 domain->name,
666 &tmp,
667 &werr);
670 /* And restore our original timeout. */
671 rpccli_set_timeout(netlogon_pipe, orig_timeout);
673 if (!NT_STATUS_IS_OK(result)) {
674 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
675 nt_errstr(result)));
676 talloc_destroy(mem_ctx);
677 return false;
680 if (!W_ERROR_IS_OK(werr)) {
681 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
682 win_errstr(werr)));
683 talloc_destroy(mem_ctx);
684 return false;
687 /* rpccli_netr_GetAnyDCName gives us a name with \\ */
688 p = strip_hostname(tmp);
690 fstrcpy(dcname, p);
692 talloc_destroy(mem_ctx);
694 DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
696 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
697 return False;
700 return True;
704 * Helper function to assemble trust password and account name
706 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
707 char **machine_password,
708 char **machine_account,
709 char **machine_krb5_principal)
711 const char *account_name;
712 const char *name = NULL;
714 /* If we are a DC and this is not our own domain */
716 if (IS_DC) {
717 name = domain->name;
718 } else {
719 struct winbindd_domain *our_domain = find_our_domain();
721 if (!our_domain)
722 return NT_STATUS_INVALID_SERVER_STATE;
724 name = our_domain->name;
727 if (!get_trust_pw_clear(name, machine_password,
728 &account_name, NULL))
730 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
733 if ((machine_account != NULL) &&
734 (asprintf(machine_account, "%s$", account_name) == -1))
736 return NT_STATUS_NO_MEMORY;
739 /* For now assume our machine account only exists in our domain */
741 if (machine_krb5_principal != NULL)
743 struct winbindd_domain *our_domain = find_our_domain();
745 if (!our_domain) {
746 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
749 if (asprintf(machine_krb5_principal, "%s$@%s",
750 account_name, our_domain->alt_name) == -1)
752 return NT_STATUS_NO_MEMORY;
755 strupper_m(*machine_krb5_principal);
758 return NT_STATUS_OK;
761 /************************************************************************
762 Given a fd with a just-connected TCP connection to a DC, open a connection
763 to the pipe.
764 ************************************************************************/
766 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
767 const int sockfd,
768 const char *controller,
769 struct cli_state **cli,
770 bool *retry)
772 char *machine_password = NULL;
773 char *machine_krb5_principal = NULL;
774 char *machine_account = NULL;
775 char *ipc_username = NULL;
776 char *ipc_domain = NULL;
777 char *ipc_password = NULL;
779 struct named_mutex *mutex;
781 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
783 struct sockaddr peeraddr;
784 socklen_t peeraddr_len;
786 struct sockaddr_in *peeraddr_in =
787 (struct sockaddr_in *)(void *)&peeraddr;
789 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
790 controller, domain->name ));
792 *retry = True;
794 mutex = grab_named_mutex(talloc_tos(), controller,
795 WINBIND_SERVER_MUTEX_WAIT_TIME);
796 if (mutex == NULL) {
797 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
798 controller));
799 result = NT_STATUS_POSSIBLE_DEADLOCK;
800 goto done;
803 if ((*cli = cli_initialise()) == NULL) {
804 DEBUG(1, ("Could not cli_initialize\n"));
805 result = NT_STATUS_NO_MEMORY;
806 goto done;
809 (*cli)->timeout = 10000; /* 10 seconds */
810 (*cli)->fd = sockfd;
811 fstrcpy((*cli)->desthost, controller);
812 (*cli)->use_kerberos = True;
814 peeraddr_len = sizeof(peeraddr);
816 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
817 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
818 strerror(errno)));
819 result = NT_STATUS_UNSUCCESSFUL;
820 goto done;
823 if ((peeraddr_len != sizeof(struct sockaddr_in))
824 #ifdef HAVE_IPV6
825 && (peeraddr_len != sizeof(struct sockaddr_in6))
826 #endif
828 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
829 peeraddr_len));
830 result = NT_STATUS_UNSUCCESSFUL;
831 goto done;
834 if ((peeraddr_in->sin_family != PF_INET)
835 #ifdef HAVE_IPV6
836 && (peeraddr_in->sin_family != PF_INET6)
837 #endif
839 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
840 peeraddr_in->sin_family));
841 result = NT_STATUS_UNSUCCESSFUL;
842 goto done;
845 if (ntohs(peeraddr_in->sin_port) == 139) {
846 struct nmb_name calling;
847 struct nmb_name called;
849 make_nmb_name(&calling, global_myname(), 0x0);
850 make_nmb_name(&called, "*SMBSERVER", 0x20);
852 if (!cli_session_request(*cli, &calling, &called)) {
853 DEBUG(8, ("cli_session_request failed for %s\n",
854 controller));
855 result = NT_STATUS_UNSUCCESSFUL;
856 goto done;
860 result = cli_negprot(*cli);
862 if (!NT_STATUS_IS_OK(result)) {
863 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
864 goto done;
867 if (!is_dc_trusted_domain_situation(domain->name) &&
868 (*cli)->protocol >= PROTOCOL_NT1 &&
869 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
871 ADS_STATUS ads_status;
873 result = get_trust_creds(domain, &machine_password,
874 &machine_account,
875 &machine_krb5_principal);
876 if (!NT_STATUS_IS_OK(result)) {
877 goto anon_fallback;
880 if (lp_security() == SEC_ADS) {
882 /* Try a krb5 session */
884 (*cli)->use_kerberos = True;
885 DEBUG(5, ("connecting to %s from %s with kerberos principal "
886 "[%s] and realm [%s]\n", controller, global_myname(),
887 machine_krb5_principal, domain->alt_name));
889 winbindd_set_locator_kdc_envs(domain);
891 ads_status = cli_session_setup_spnego(*cli,
892 machine_krb5_principal,
893 machine_password,
894 lp_workgroup(),
895 domain->alt_name);
897 if (!ADS_ERR_OK(ads_status)) {
898 DEBUG(4,("failed kerberos session setup with %s\n",
899 ads_errstr(ads_status)));
902 result = ads_ntstatus(ads_status);
903 if (NT_STATUS_IS_OK(result)) {
904 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
905 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
906 if (!NT_STATUS_IS_OK(result)) {
907 goto done;
909 goto session_setup_done;
913 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
914 (*cli)->use_kerberos = False;
916 DEBUG(5, ("connecting to %s from %s with username "
917 "[%s]\\[%s]\n", controller, global_myname(),
918 lp_workgroup(), machine_account));
920 ads_status = cli_session_setup_spnego(*cli,
921 machine_account,
922 machine_password,
923 lp_workgroup(),
924 NULL);
925 if (!ADS_ERR_OK(ads_status)) {
926 DEBUG(4, ("authenticated session setup failed with %s\n",
927 ads_errstr(ads_status)));
930 result = ads_ntstatus(ads_status);
931 if (NT_STATUS_IS_OK(result)) {
932 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
933 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
934 if (!NT_STATUS_IS_OK(result)) {
935 goto done;
937 goto session_setup_done;
941 /* Fall back to non-kerberos session setup with auth_user */
943 (*cli)->use_kerberos = False;
945 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
947 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
948 (strlen(ipc_username) > 0)) {
950 /* Only try authenticated if we have a username */
952 DEBUG(5, ("connecting to %s from %s with username "
953 "[%s]\\[%s]\n", controller, global_myname(),
954 ipc_domain, ipc_username));
956 if (NT_STATUS_IS_OK(cli_session_setup(
957 *cli, ipc_username,
958 ipc_password, strlen(ipc_password)+1,
959 ipc_password, strlen(ipc_password)+1,
960 ipc_domain))) {
961 /* Successful logon with given username. */
962 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
963 if (!NT_STATUS_IS_OK(result)) {
964 goto done;
966 goto session_setup_done;
967 } else {
968 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
969 ipc_domain, ipc_username ));
973 anon_fallback:
975 /* Fall back to anonymous connection, this might fail later */
976 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
977 "connection for DC %s\n",
978 controller ));
980 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
981 NULL, 0, ""))) {
982 DEBUG(5, ("Connected anonymously\n"));
983 result = cli_init_creds(*cli, "", "", "");
984 if (!NT_STATUS_IS_OK(result)) {
985 goto done;
987 goto session_setup_done;
990 result = cli_nt_error(*cli);
992 if (NT_STATUS_IS_OK(result))
993 result = NT_STATUS_UNSUCCESSFUL;
995 /* We can't session setup */
997 goto done;
999 session_setup_done:
1001 /* cache the server name for later connections */
1003 saf_store( domain->name, (*cli)->desthost );
1004 if (domain->alt_name && (*cli)->use_kerberos) {
1005 saf_store( domain->alt_name, (*cli)->desthost );
1008 winbindd_set_locator_kdc_envs(domain);
1010 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
1012 if (!NT_STATUS_IS_OK(result)) {
1013 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1014 goto done;
1017 TALLOC_FREE(mutex);
1018 *retry = False;
1020 /* set the domain if empty; needed for schannel connections */
1021 if ( !(*cli)->domain[0] ) {
1022 result = cli_set_domain((*cli), domain->name);
1023 if (!NT_STATUS_IS_OK(result)) {
1024 return result;
1028 result = NT_STATUS_OK;
1030 done:
1031 TALLOC_FREE(mutex);
1032 SAFE_FREE(machine_account);
1033 SAFE_FREE(machine_password);
1034 SAFE_FREE(machine_krb5_principal);
1035 SAFE_FREE(ipc_username);
1036 SAFE_FREE(ipc_domain);
1037 SAFE_FREE(ipc_password);
1039 if (!NT_STATUS_IS_OK(result)) {
1040 winbind_add_failed_connection_entry(domain, controller, result);
1041 if ((*cli) != NULL) {
1042 cli_shutdown(*cli);
1043 *cli = NULL;
1047 return result;
1050 /*******************************************************************
1051 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1052 array.
1054 Keeps the list unique by not adding duplicate entries.
1056 @param[in] mem_ctx talloc memory context to allocate from
1057 @param[in] domain_name domain of the DC
1058 @param[in] dcname name of the DC to add to the list
1059 @param[in] pss Internet address and port pair to add to the list
1060 @param[in,out] dcs array of dc_name_ip structures to add to
1061 @param[in,out] num_dcs number of dcs returned in the dcs array
1062 @return true if the list was added to, false otherwise
1063 *******************************************************************/
1065 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1066 const char *dcname, struct sockaddr_storage *pss,
1067 struct dc_name_ip **dcs, int *num)
1069 int i = 0;
1071 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1072 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1073 return False;
1076 /* Make sure there's no duplicates in the list */
1077 for (i=0; i<*num; i++)
1078 if (sockaddr_equal(
1079 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1080 (struct sockaddr *)(void *)pss))
1081 return False;
1083 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1085 if (*dcs == NULL)
1086 return False;
1088 fstrcpy((*dcs)[*num].name, dcname);
1089 (*dcs)[*num].ss = *pss;
1090 *num += 1;
1091 return True;
1094 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1095 struct sockaddr_storage *pss, uint16 port,
1096 struct sockaddr_storage **addrs, int *num)
1098 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1100 if (*addrs == NULL) {
1101 *num = 0;
1102 return False;
1105 (*addrs)[*num] = *pss;
1106 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1108 *num += 1;
1109 return True;
1112 /*******************************************************************
1113 convert an ip to a name
1114 *******************************************************************/
1116 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1117 const struct winbindd_domain *domain,
1118 struct sockaddr_storage *pss,
1119 fstring name )
1121 struct ip_service ip_list;
1122 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1124 ip_list.ss = *pss;
1125 ip_list.port = 0;
1127 #ifdef WITH_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 /* try GETDC requests next */
1189 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1190 pss, domain->name, &domain->sid,
1191 nt_version)) {
1192 const char *dc_name = NULL;
1193 int i;
1194 smb_msleep(100);
1195 for (i=0; i<5; i++) {
1196 if (receive_getdc_response(mem_ctx, pss, domain->name,
1197 &nt_version,
1198 &dc_name, NULL)) {
1199 fstrcpy(name, dc_name);
1200 namecache_store(name, 0x20, 1, &ip_list);
1201 return True;
1203 smb_msleep(500);
1207 /* try node status request */
1209 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1210 namecache_store(name, 0x20, 1, &ip_list);
1211 return True;
1213 return False;
1216 /*******************************************************************
1217 Retrieve a list of IP addresses for domain controllers.
1219 The array is sorted in the preferred connection order.
1221 @param[in] mem_ctx talloc memory context to allocate from
1222 @param[in] domain domain to retrieve DCs for
1223 @param[out] dcs array of dcs that will be returned
1224 @param[out] num_dcs number of dcs returned in the dcs array
1225 @return always true
1226 *******************************************************************/
1228 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1229 struct dc_name_ip **dcs, int *num_dcs)
1231 fstring dcname;
1232 struct sockaddr_storage ss;
1233 struct ip_service *ip_list = NULL;
1234 int iplist_size = 0;
1235 int i;
1236 bool is_our_domain;
1237 enum security_types sec = (enum security_types)lp_security();
1239 is_our_domain = strequal(domain->name, lp_workgroup());
1241 /* If not our domain, get the preferred DC, by asking our primary DC */
1242 if ( !is_our_domain
1243 && get_dc_name_via_netlogon(domain, dcname, &ss)
1244 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1245 num_dcs) )
1247 char addr[INET6_ADDRSTRLEN];
1248 print_sockaddr(addr, sizeof(addr), &ss);
1249 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1250 dcname, addr));
1251 return True;
1254 if (sec == SEC_ADS) {
1255 char *sitename = NULL;
1257 /* We need to make sure we know the local site before
1258 doing any DNS queries, as this will restrict the
1259 get_sorted_dc_list() call below to only fetching
1260 DNS records for the correct site. */
1262 /* Find any DC to get the site record.
1263 We deliberately don't care about the
1264 return here. */
1266 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1268 sitename = sitename_fetch(domain->alt_name);
1269 if (sitename) {
1271 /* Do the site-specific AD dns lookup first. */
1272 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1273 &iplist_size, True);
1275 /* Add ips to the DC array. We don't look up the name
1276 of the DC in this function, but we fill in the char*
1277 of the ip now to make the failed connection cache
1278 work */
1279 for ( i=0; i<iplist_size; i++ ) {
1280 char addr[INET6_ADDRSTRLEN];
1281 print_sockaddr(addr, sizeof(addr),
1282 &ip_list[i].ss);
1283 add_one_dc_unique(mem_ctx,
1284 domain->name,
1285 addr,
1286 &ip_list[i].ss,
1287 dcs,
1288 num_dcs);
1291 SAFE_FREE(ip_list);
1292 SAFE_FREE(sitename);
1293 iplist_size = 0;
1296 /* Now we add DCs from the main AD DNS lookup. */
1297 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1298 &iplist_size, True);
1300 for ( i=0; i<iplist_size; i++ ) {
1301 char addr[INET6_ADDRSTRLEN];
1302 print_sockaddr(addr, sizeof(addr),
1303 &ip_list[i].ss);
1304 add_one_dc_unique(mem_ctx,
1305 domain->name,
1306 addr,
1307 &ip_list[i].ss,
1308 dcs,
1309 num_dcs);
1312 SAFE_FREE(ip_list);
1313 iplist_size = 0;
1316 /* Try standard netbios queries if no ADS */
1317 if (*num_dcs == 0) {
1318 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1319 False);
1321 for ( i=0; i<iplist_size; i++ ) {
1322 char addr[INET6_ADDRSTRLEN];
1323 print_sockaddr(addr, sizeof(addr),
1324 &ip_list[i].ss);
1325 add_one_dc_unique(mem_ctx,
1326 domain->name,
1327 addr,
1328 &ip_list[i].ss,
1329 dcs,
1330 num_dcs);
1333 SAFE_FREE(ip_list);
1334 iplist_size = 0;
1337 return True;
1340 /*******************************************************************
1341 Find and make a connection to a DC in the given domain.
1343 @param[in] mem_ctx talloc memory context to allocate from
1344 @param[in] domain domain to find a dc in
1345 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1346 @param[out] pss DC Internet address and port
1347 @param[out] fd fd of the open socket connected to the newly found dc
1348 @return true when a DC connection is made, false otherwise
1349 *******************************************************************/
1351 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1352 struct winbindd_domain *domain,
1353 fstring dcname, struct sockaddr_storage *pss, int *fd)
1355 struct dc_name_ip *dcs = NULL;
1356 int num_dcs = 0;
1358 const char **dcnames = NULL;
1359 int num_dcnames = 0;
1361 struct sockaddr_storage *addrs = NULL;
1362 int num_addrs = 0;
1364 int i, fd_index;
1366 *fd = -1;
1368 again:
1369 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1370 return False;
1372 for (i=0; i<num_dcs; i++) {
1374 if (!add_string_to_array(mem_ctx, dcs[i].name,
1375 &dcnames, &num_dcnames)) {
1376 return False;
1378 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1379 &addrs, &num_addrs)) {
1380 return False;
1383 if (!add_string_to_array(mem_ctx, dcs[i].name,
1384 &dcnames, &num_dcnames)) {
1385 return False;
1387 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1388 &addrs, &num_addrs)) {
1389 return False;
1393 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1394 return False;
1396 if ((addrs == NULL) || (dcnames == NULL))
1397 return False;
1399 /* 5 second timeout. */
1400 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1401 for (i=0; i<num_dcs; i++) {
1402 char ab[INET6_ADDRSTRLEN];
1403 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1404 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1405 "domain %s address %s. Error was %s\n",
1406 domain->name, ab, strerror(errno) ));
1407 winbind_add_failed_connection_entry(domain,
1408 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1410 return False;
1413 *pss = addrs[fd_index];
1415 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1416 /* Ok, we've got a name for the DC */
1417 fstrcpy(dcname, dcnames[fd_index]);
1418 return True;
1421 /* Try to figure out the name */
1422 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1423 return True;
1426 /* We can not continue without the DC's name */
1427 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1428 NT_STATUS_UNSUCCESSFUL);
1430 /* Throw away all arrays as we're doing this again. */
1431 TALLOC_FREE(dcs);
1432 num_dcs = 0;
1434 TALLOC_FREE(dcnames);
1435 num_dcnames = 0;
1437 TALLOC_FREE(addrs);
1438 num_addrs = 0;
1440 close(*fd);
1441 *fd = -1;
1443 goto again;
1446 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1447 struct winbindd_cm_conn *new_conn)
1449 TALLOC_CTX *mem_ctx;
1450 NTSTATUS result;
1451 char *saf_servername = saf_fetch( domain->name );
1452 int retries;
1454 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1455 SAFE_FREE(saf_servername);
1456 set_domain_offline(domain);
1457 return NT_STATUS_NO_MEMORY;
1460 /* we have to check the server affinity cache here since
1461 later we selecte a DC based on response time and not preference */
1463 /* Check the negative connection cache
1464 before talking to it. It going down may have
1465 triggered the reconnection. */
1467 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1469 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1470 saf_servername, domain->name ));
1472 /* convert an ip address to a name */
1473 if (is_ipaddress( saf_servername ) ) {
1474 fstring saf_name;
1475 struct sockaddr_storage ss;
1477 if (!interpret_string_addr(&ss, saf_servername,
1478 AI_NUMERICHOST)) {
1479 return NT_STATUS_UNSUCCESSFUL;
1481 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1482 fstrcpy( domain->dcname, saf_name );
1483 } else {
1484 winbind_add_failed_connection_entry(
1485 domain, saf_servername,
1486 NT_STATUS_UNSUCCESSFUL);
1488 } else {
1489 fstrcpy( domain->dcname, saf_servername );
1492 SAFE_FREE( saf_servername );
1495 for (retries = 0; retries < 3; retries++) {
1496 int fd = -1;
1497 bool retry = False;
1499 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1501 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1502 domain->dcname, domain->name ));
1504 if (*domain->dcname
1505 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1506 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1508 struct sockaddr_storage *addrs = NULL;
1509 int num_addrs = 0;
1510 int dummy = 0;
1512 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1513 set_domain_offline(domain);
1514 talloc_destroy(mem_ctx);
1515 return NT_STATUS_NO_MEMORY;
1517 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1518 set_domain_offline(domain);
1519 talloc_destroy(mem_ctx);
1520 return NT_STATUS_NO_MEMORY;
1523 /* 5 second timeout. */
1524 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1525 fd = -1;
1529 if ((fd == -1)
1530 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1532 /* This is the one place where we will
1533 set the global winbindd offline state
1534 to true, if a "WINBINDD_OFFLINE" entry
1535 is found in the winbindd cache. */
1536 set_global_winbindd_state_offline();
1537 break;
1540 new_conn->cli = NULL;
1542 result = cm_prepare_connection(domain, fd, domain->dcname,
1543 &new_conn->cli, &retry);
1545 if (!retry)
1546 break;
1549 if (NT_STATUS_IS_OK(result)) {
1551 winbindd_set_locator_kdc_envs(domain);
1553 if (domain->online == False) {
1554 /* We're changing state from offline to online. */
1555 set_global_winbindd_state_online();
1557 set_domain_online(domain);
1558 } else {
1559 /* Ensure we setup the retry handler. */
1560 set_domain_offline(domain);
1563 talloc_destroy(mem_ctx);
1564 return result;
1567 /* Close down all open pipes on a connection. */
1569 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1571 /* We're closing down a possibly dead
1572 connection. Don't have impossibly long (10s) timeouts. */
1574 if (conn->cli) {
1575 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1578 if (conn->samr_pipe != NULL) {
1579 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1580 rpccli_samr_Close(conn->samr_pipe, talloc_tos(),
1581 &conn->sam_connect_handle);
1583 TALLOC_FREE(conn->samr_pipe);
1584 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1585 if (conn->cli) {
1586 cli_set_timeout(conn->cli, 500);
1590 if (conn->lsa_pipe != NULL) {
1591 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1592 rpccli_lsa_Close(conn->lsa_pipe, talloc_tos(),
1593 &conn->lsa_policy);
1595 TALLOC_FREE(conn->lsa_pipe);
1596 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1597 if (conn->cli) {
1598 cli_set_timeout(conn->cli, 500);
1602 if (conn->lsa_pipe_tcp != NULL) {
1603 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1604 rpccli_lsa_Close(conn->lsa_pipe, talloc_tos(),
1605 &conn->lsa_policy);
1607 TALLOC_FREE(conn->lsa_pipe_tcp);
1608 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1609 if (conn->cli) {
1610 cli_set_timeout(conn->cli, 500);
1614 if (conn->netlogon_pipe != NULL) {
1615 TALLOC_FREE(conn->netlogon_pipe);
1616 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1617 if (conn->cli) {
1618 cli_set_timeout(conn->cli, 500);
1622 if (conn->cli) {
1623 cli_shutdown(conn->cli);
1626 conn->cli = NULL;
1629 void close_conns_after_fork(void)
1631 struct winbindd_domain *domain;
1633 for (domain = domain_list(); domain; domain = domain->next) {
1634 struct cli_state *cli = domain->conn.cli;
1637 * first close the low level SMB TCP connection
1638 * so that we don't generate any SMBclose
1639 * requests in invalidate_cm_connection()
1641 if (cli && cli->fd != -1) {
1642 close(domain->conn.cli->fd);
1643 domain->conn.cli->fd = -1;
1646 invalidate_cm_connection(&domain->conn);
1650 static bool connection_ok(struct winbindd_domain *domain)
1652 bool ok;
1654 ok = cli_state_is_connected(domain->conn.cli);
1655 if (!ok) {
1656 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1657 domain->dcname, domain->name));
1658 return False;
1661 if (domain->online == False) {
1662 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1663 return False;
1666 return True;
1669 /* Initialize a new connection up to the RPC BIND.
1670 Bypass online status check so always does network calls. */
1672 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1674 NTSTATUS result;
1676 /* Internal connections never use the network. */
1677 if (domain->internal) {
1678 domain->initialized = True;
1679 return NT_STATUS_OK;
1682 if (!winbindd_can_contact_domain(domain)) {
1683 invalidate_cm_connection(&domain->conn);
1684 domain->initialized = True;
1685 return NT_STATUS_OK;
1688 if (connection_ok(domain)) {
1689 if (!domain->initialized) {
1690 set_dc_type_and_flags(domain);
1692 return NT_STATUS_OK;
1695 invalidate_cm_connection(&domain->conn);
1697 result = cm_open_connection(domain, &domain->conn);
1699 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1700 set_dc_type_and_flags(domain);
1703 return result;
1706 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1708 if (domain->internal) {
1709 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1712 if (domain->initialized && !domain->online) {
1713 /* We check for online status elsewhere. */
1714 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1717 return init_dc_connection_network(domain);
1720 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1722 NTSTATUS status;
1724 status = init_dc_connection(domain);
1725 if (!NT_STATUS_IS_OK(status)) {
1726 return status;
1729 if (!domain->internal && domain->conn.cli == NULL) {
1730 /* happens for trusted domains without inbound trust */
1731 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1734 return NT_STATUS_OK;
1737 /******************************************************************************
1738 Set the trust flags (direction and forest location) for a domain
1739 ******************************************************************************/
1741 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1743 struct winbindd_domain *our_domain;
1744 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1745 struct netr_DomainTrustList trusts;
1746 int i;
1747 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1748 NETR_TRUST_FLAG_OUTBOUND |
1749 NETR_TRUST_FLAG_INBOUND);
1750 struct rpc_pipe_client *cli;
1751 TALLOC_CTX *mem_ctx = NULL;
1753 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1755 /* Our primary domain doesn't need to worry about trust flags.
1756 Force it to go through the network setup */
1757 if ( domain->primary ) {
1758 return False;
1761 our_domain = find_our_domain();
1763 if ( !connection_ok(our_domain) ) {
1764 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1765 return False;
1768 /* This won't work unless our domain is AD */
1770 if ( !our_domain->active_directory ) {
1771 return False;
1774 /* Use DsEnumerateDomainTrusts to get us the trust direction
1775 and type */
1777 result = cm_connect_netlogon(our_domain, &cli);
1779 if (!NT_STATUS_IS_OK(result)) {
1780 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1781 "a connection to %s for PIPE_NETLOGON (%s)\n",
1782 domain->name, nt_errstr(result)));
1783 return False;
1786 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1787 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1788 return False;
1791 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1792 cli->desthost,
1793 flags,
1794 &trusts,
1795 NULL);
1796 if (!NT_STATUS_IS_OK(result)) {
1797 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1798 "failed to query trusted domain list: %s\n",
1799 nt_errstr(result)));
1800 talloc_destroy(mem_ctx);
1801 return false;
1804 /* Now find the domain name and get the flags */
1806 for ( i=0; i<trusts.count; i++ ) {
1807 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1808 domain->domain_flags = trusts.array[i].trust_flags;
1809 domain->domain_type = trusts.array[i].trust_type;
1810 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1812 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1813 domain->active_directory = True;
1815 /* This flag is only set if the domain is *our*
1816 primary domain and the primary domain is in
1817 native mode */
1819 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1821 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1822 "native mode.\n", domain->name,
1823 domain->native_mode ? "" : "NOT "));
1825 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1826 "running active directory.\n", domain->name,
1827 domain->active_directory ? "" : "NOT "));
1830 domain->initialized = True;
1832 break;
1836 talloc_destroy( mem_ctx );
1838 return domain->initialized;
1841 /******************************************************************************
1842 We can 'sense' certain things about the DC by it's replies to certain
1843 questions.
1845 This tells us if this particular remote server is Active Directory, and if it
1846 is native mode.
1847 ******************************************************************************/
1849 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1851 NTSTATUS result;
1852 WERROR werr;
1853 TALLOC_CTX *mem_ctx = NULL;
1854 struct rpc_pipe_client *cli = NULL;
1855 struct policy_handle pol;
1856 union dssetup_DsRoleInfo info;
1857 union lsa_PolicyInformation *lsa_info = NULL;
1859 if (!connection_ok(domain)) {
1860 return;
1863 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1864 domain->name);
1865 if (!mem_ctx) {
1866 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1867 return;
1870 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1872 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1873 &ndr_table_dssetup.syntax_id,
1874 &cli);
1876 if (!NT_STATUS_IS_OK(result)) {
1877 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1878 "PI_DSSETUP on domain %s: (%s)\n",
1879 domain->name, nt_errstr(result)));
1881 /* if this is just a non-AD domain we need to continue
1882 * identifying so that we can in the end return with
1883 * domain->initialized = True - gd */
1885 goto no_dssetup;
1888 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1889 DS_ROLE_BASIC_INFORMATION,
1890 &info,
1891 &werr);
1892 TALLOC_FREE(cli);
1894 if (!NT_STATUS_IS_OK(result)) {
1895 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1896 "on domain %s failed: (%s)\n",
1897 domain->name, nt_errstr(result)));
1899 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1900 * every opcode on the DSSETUP pipe, continue with
1901 * no_dssetup mode here as well to get domain->initialized
1902 * set - gd */
1904 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1905 goto no_dssetup;
1908 TALLOC_FREE(mem_ctx);
1909 return;
1912 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1913 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1914 domain->native_mode = True;
1915 } else {
1916 domain->native_mode = False;
1919 no_dssetup:
1920 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1921 &ndr_table_lsarpc.syntax_id, &cli);
1923 if (!NT_STATUS_IS_OK(result)) {
1924 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1925 "PI_LSARPC on domain %s: (%s)\n",
1926 domain->name, nt_errstr(result)));
1927 TALLOC_FREE(cli);
1928 TALLOC_FREE(mem_ctx);
1929 return;
1932 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1933 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1935 if (NT_STATUS_IS_OK(result)) {
1936 /* This particular query is exactly what Win2k clients use
1937 to determine that the DC is active directory */
1938 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1939 &pol,
1940 LSA_POLICY_INFO_DNS,
1941 &lsa_info);
1944 if (NT_STATUS_IS_OK(result)) {
1945 domain->active_directory = True;
1947 if (lsa_info->dns.name.string) {
1948 fstrcpy(domain->name, lsa_info->dns.name.string);
1951 if (lsa_info->dns.dns_domain.string) {
1952 fstrcpy(domain->alt_name,
1953 lsa_info->dns.dns_domain.string);
1956 /* See if we can set some domain trust flags about
1957 ourself */
1959 if (lsa_info->dns.dns_forest.string) {
1960 fstrcpy(domain->forest_name,
1961 lsa_info->dns.dns_forest.string);
1963 if (strequal(domain->forest_name, domain->alt_name)) {
1964 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1968 if (lsa_info->dns.sid) {
1969 sid_copy(&domain->sid, lsa_info->dns.sid);
1971 } else {
1972 domain->active_directory = False;
1974 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1975 SEC_FLAG_MAXIMUM_ALLOWED,
1976 &pol);
1978 if (!NT_STATUS_IS_OK(result)) {
1979 goto done;
1982 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1983 &pol,
1984 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1985 &lsa_info);
1987 if (NT_STATUS_IS_OK(result)) {
1989 if (lsa_info->account_domain.name.string) {
1990 fstrcpy(domain->name,
1991 lsa_info->account_domain.name.string);
1994 if (lsa_info->account_domain.sid) {
1995 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1999 done:
2001 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2002 domain->name, domain->native_mode ? "" : "NOT "));
2004 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2005 domain->name, domain->active_directory ? "" : "NOT "));
2007 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2009 TALLOC_FREE(cli);
2011 TALLOC_FREE(mem_ctx);
2013 domain->initialized = True;
2016 /**********************************************************************
2017 Set the domain_flags (trust attributes, domain operating modes, etc...
2018 ***********************************************************************/
2020 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2022 /* we always have to contact our primary domain */
2024 if ( domain->primary ) {
2025 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2026 "primary domain\n"));
2027 set_dc_type_and_flags_connect( domain );
2028 return;
2031 /* Use our DC to get the information if possible */
2033 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2034 /* Otherwise, fallback to contacting the
2035 domain directly */
2036 set_dc_type_and_flags_connect( domain );
2039 return;
2044 /**********************************************************************
2045 ***********************************************************************/
2047 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2048 struct netlogon_creds_CredentialState **ppdc)
2050 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2051 struct rpc_pipe_client *netlogon_pipe;
2053 if (lp_client_schannel() == False) {
2054 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;;
2057 result = cm_connect_netlogon(domain, &netlogon_pipe);
2058 if (!NT_STATUS_IS_OK(result)) {
2059 return result;
2062 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2063 netlogon pipe. */
2065 if (!domain->conn.netlogon_pipe->dc) {
2066 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2069 *ppdc = domain->conn.netlogon_pipe->dc;
2070 return NT_STATUS_OK;
2073 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2074 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2076 struct winbindd_cm_conn *conn;
2077 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2078 struct netlogon_creds_CredentialState *p_creds;
2079 char *machine_password = NULL;
2080 char *machine_account = NULL;
2081 char *domain_name = NULL;
2083 if (strequal(domain->name, get_global_sam_name())) {
2084 result = open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2085 if (!NT_STATUS_IS_OK(result)) {
2086 return result;
2088 return NT_STATUS_OK;
2091 result = init_dc_connection_rpc(domain);
2092 if (!NT_STATUS_IS_OK(result)) {
2093 return result;
2096 conn = &domain->conn;
2098 if (rpccli_is_connected(conn->samr_pipe)) {
2099 goto done;
2102 TALLOC_FREE(conn->samr_pipe);
2105 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2106 * sign and sealed pipe using the machine account password by
2107 * preference. If we can't - try schannel, if that fails, try
2108 * anonymous.
2111 if ((conn->cli->user_name[0] == '\0') ||
2112 (conn->cli->domain[0] == '\0') ||
2113 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2115 result = get_trust_creds(domain, &machine_password,
2116 &machine_account, NULL);
2117 if (!NT_STATUS_IS_OK(result)) {
2118 DEBUG(10, ("cm_connect_sam: No no user available for "
2119 "domain %s, trying schannel\n", conn->cli->domain));
2120 goto schannel;
2122 domain_name = domain->name;
2123 } else {
2124 machine_password = SMB_STRDUP(conn->cli->password);
2125 machine_account = SMB_STRDUP(conn->cli->user_name);
2126 domain_name = conn->cli->domain;
2129 if (!machine_password || !machine_account) {
2130 result = NT_STATUS_NO_MEMORY;
2131 goto done;
2134 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2135 authenticated SAMR pipe with sign & seal. */
2136 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2137 &ndr_table_samr.syntax_id,
2138 NCACN_NP,
2139 DCERPC_AUTH_LEVEL_PRIVACY,
2140 domain_name,
2141 machine_account,
2142 machine_password,
2143 &conn->samr_pipe);
2145 if (!NT_STATUS_IS_OK(result)) {
2146 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2147 "pipe for domain %s using NTLMSSP "
2148 "authenticated pipe: user %s\\%s. Error was "
2149 "%s\n", domain->name, domain_name,
2150 machine_account, nt_errstr(result)));
2151 goto schannel;
2154 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2155 "domain %s using NTLMSSP authenticated "
2156 "pipe: user %s\\%s\n", domain->name,
2157 domain_name, machine_account));
2159 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2160 conn->samr_pipe->desthost,
2161 SEC_FLAG_MAXIMUM_ALLOWED,
2162 &conn->sam_connect_handle);
2163 if (NT_STATUS_IS_OK(result)) {
2164 goto open_domain;
2166 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2167 "failed for domain %s, error was %s. Trying schannel\n",
2168 domain->name, nt_errstr(result) ));
2169 TALLOC_FREE(conn->samr_pipe);
2171 schannel:
2173 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2175 result = cm_get_schannel_creds(domain, &p_creds);
2176 if (!NT_STATUS_IS_OK(result)) {
2177 /* If this call fails - conn->cli can now be NULL ! */
2178 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2179 "for domain %s (error %s), trying anon\n",
2180 domain->name,
2181 nt_errstr(result) ));
2182 goto anonymous;
2184 result = cli_rpc_pipe_open_schannel_with_key
2185 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2186 DCERPC_AUTH_LEVEL_PRIVACY,
2187 domain->name, &p_creds, &conn->samr_pipe);
2189 if (!NT_STATUS_IS_OK(result)) {
2190 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2191 "domain %s using schannel. Error was %s\n",
2192 domain->name, nt_errstr(result) ));
2193 goto anonymous;
2195 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2196 "schannel.\n", domain->name ));
2198 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2199 conn->samr_pipe->desthost,
2200 SEC_FLAG_MAXIMUM_ALLOWED,
2201 &conn->sam_connect_handle);
2202 if (NT_STATUS_IS_OK(result)) {
2203 goto open_domain;
2205 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2206 "for domain %s, error was %s. Trying anonymous\n",
2207 domain->name, nt_errstr(result) ));
2208 TALLOC_FREE(conn->samr_pipe);
2210 anonymous:
2212 /* Finally fall back to anonymous. */
2213 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2214 &conn->samr_pipe);
2216 if (!NT_STATUS_IS_OK(result)) {
2217 goto done;
2220 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2221 conn->samr_pipe->desthost,
2222 SEC_FLAG_MAXIMUM_ALLOWED,
2223 &conn->sam_connect_handle);
2224 if (!NT_STATUS_IS_OK(result)) {
2225 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2226 "for domain %s Error was %s\n",
2227 domain->name, nt_errstr(result) ));
2228 goto done;
2231 open_domain:
2232 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2233 mem_ctx,
2234 &conn->sam_connect_handle,
2235 SEC_FLAG_MAXIMUM_ALLOWED,
2236 &domain->sid,
2237 &conn->sam_domain_handle);
2239 done:
2241 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2243 * if we got access denied, we might just have no access rights
2244 * to talk to the remote samr server server (e.g. when we are a
2245 * PDC and we are connecting a w2k8 pdc via an interdomain
2246 * trust). In that case do not invalidate the whole connection
2247 * stack
2249 TALLOC_FREE(conn->samr_pipe);
2250 ZERO_STRUCT(conn->sam_domain_handle);
2251 return result;
2252 } else if (!NT_STATUS_IS_OK(result)) {
2253 invalidate_cm_connection(conn);
2254 return result;
2257 *cli = conn->samr_pipe;
2258 *sam_handle = conn->sam_domain_handle;
2259 SAFE_FREE(machine_password);
2260 SAFE_FREE(machine_account);
2261 return result;
2264 /**********************************************************************
2265 open an schanneld ncacn_ip_tcp connection to LSA
2266 ***********************************************************************/
2268 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2269 TALLOC_CTX *mem_ctx,
2270 struct rpc_pipe_client **cli)
2272 struct winbindd_cm_conn *conn;
2273 struct netlogon_creds_CredentialState *creds;
2274 NTSTATUS status;
2276 DEBUG(10,("cm_connect_lsa_tcp\n"));
2278 status = init_dc_connection_rpc(domain);
2279 if (!NT_STATUS_IS_OK(status)) {
2280 return status;
2283 conn = &domain->conn;
2285 if (conn->lsa_pipe_tcp &&
2286 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2287 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2288 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2289 goto done;
2292 TALLOC_FREE(conn->lsa_pipe_tcp);
2294 status = cm_get_schannel_creds(domain, &creds);
2295 if (!NT_STATUS_IS_OK(status)) {
2296 goto done;
2299 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2300 &ndr_table_lsarpc.syntax_id,
2301 NCACN_IP_TCP,
2302 DCERPC_AUTH_LEVEL_PRIVACY,
2303 domain->name,
2304 &creds,
2305 &conn->lsa_pipe_tcp);
2306 if (!NT_STATUS_IS_OK(status)) {
2307 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2308 nt_errstr(status)));
2309 goto done;
2312 done:
2313 if (!NT_STATUS_IS_OK(status)) {
2314 TALLOC_FREE(conn->lsa_pipe_tcp);
2315 return status;
2318 *cli = conn->lsa_pipe_tcp;
2320 return status;
2323 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2324 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2326 struct winbindd_cm_conn *conn;
2327 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2328 struct netlogon_creds_CredentialState *p_creds;
2330 result = init_dc_connection_rpc(domain);
2331 if (!NT_STATUS_IS_OK(result))
2332 return result;
2334 conn = &domain->conn;
2336 if (rpccli_is_connected(conn->lsa_pipe)) {
2337 goto done;
2340 TALLOC_FREE(conn->lsa_pipe);
2342 if ((conn->cli->user_name[0] == '\0') ||
2343 (conn->cli->domain[0] == '\0') ||
2344 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2345 DEBUG(10, ("cm_connect_lsa: No no user available for "
2346 "domain %s, trying schannel\n", conn->cli->domain));
2347 goto schannel;
2350 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2351 * authenticated LSA pipe with sign & seal. */
2352 result = cli_rpc_pipe_open_spnego_ntlmssp
2353 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2354 DCERPC_AUTH_LEVEL_PRIVACY,
2355 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2356 &conn->lsa_pipe);
2358 if (!NT_STATUS_IS_OK(result)) {
2359 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2360 "domain %s using NTLMSSP authenticated pipe: user "
2361 "%s\\%s. Error was %s. Trying schannel.\n",
2362 domain->name, conn->cli->domain,
2363 conn->cli->user_name, nt_errstr(result)));
2364 goto schannel;
2367 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2368 "NTLMSSP authenticated pipe: user %s\\%s\n",
2369 domain->name, conn->cli->domain, conn->cli->user_name ));
2371 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2372 SEC_FLAG_MAXIMUM_ALLOWED,
2373 &conn->lsa_policy);
2374 if (NT_STATUS_IS_OK(result)) {
2375 goto done;
2378 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2379 "schannel\n"));
2381 TALLOC_FREE(conn->lsa_pipe);
2383 schannel:
2385 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2387 result = cm_get_schannel_creds(domain, &p_creds);
2388 if (!NT_STATUS_IS_OK(result)) {
2389 /* If this call fails - conn->cli can now be NULL ! */
2390 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2391 "for domain %s (error %s), trying anon\n",
2392 domain->name,
2393 nt_errstr(result) ));
2394 goto anonymous;
2396 result = cli_rpc_pipe_open_schannel_with_key
2397 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2398 DCERPC_AUTH_LEVEL_PRIVACY,
2399 domain->name, &p_creds, &conn->lsa_pipe);
2401 if (!NT_STATUS_IS_OK(result)) {
2402 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2403 "domain %s using schannel. Error was %s\n",
2404 domain->name, nt_errstr(result) ));
2405 goto anonymous;
2407 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2408 "schannel.\n", domain->name ));
2410 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2411 SEC_FLAG_MAXIMUM_ALLOWED,
2412 &conn->lsa_policy);
2413 if (NT_STATUS_IS_OK(result)) {
2414 goto done;
2417 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2418 "anonymous\n"));
2420 TALLOC_FREE(conn->lsa_pipe);
2422 anonymous:
2424 result = cli_rpc_pipe_open_noauth(conn->cli,
2425 &ndr_table_lsarpc.syntax_id,
2426 &conn->lsa_pipe);
2427 if (!NT_STATUS_IS_OK(result)) {
2428 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2429 goto done;
2432 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2433 SEC_FLAG_MAXIMUM_ALLOWED,
2434 &conn->lsa_policy);
2435 done:
2436 if (!NT_STATUS_IS_OK(result)) {
2437 invalidate_cm_connection(conn);
2438 return result;
2441 *cli = conn->lsa_pipe;
2442 *lsa_policy = conn->lsa_policy;
2443 return result;
2446 /****************************************************************************
2447 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2448 session key stored in conn->netlogon_pipe->dc->sess_key.
2449 ****************************************************************************/
2451 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2452 struct rpc_pipe_client **cli)
2454 struct winbindd_cm_conn *conn;
2455 NTSTATUS result;
2457 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2458 uint8 mach_pwd[16];
2459 enum netr_SchannelType sec_chan_type;
2460 const char *account_name;
2461 struct rpc_pipe_client *netlogon_pipe = NULL;
2463 *cli = NULL;
2465 result = init_dc_connection_rpc(domain);
2466 if (!NT_STATUS_IS_OK(result)) {
2467 return result;
2470 conn = &domain->conn;
2472 if (rpccli_is_connected(conn->netlogon_pipe)) {
2473 *cli = conn->netlogon_pipe;
2474 return NT_STATUS_OK;
2477 TALLOC_FREE(conn->netlogon_pipe);
2479 result = cli_rpc_pipe_open_noauth(conn->cli,
2480 &ndr_table_netlogon.syntax_id,
2481 &netlogon_pipe);
2482 if (!NT_STATUS_IS_OK(result)) {
2483 return result;
2486 if ((!IS_DC) && (!domain->primary)) {
2487 /* Clear the schannel request bit and drop down */
2488 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2489 goto no_schannel;
2492 if (lp_client_schannel() != False) {
2493 neg_flags |= NETLOGON_NEG_SCHANNEL;
2496 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2497 &sec_chan_type))
2499 TALLOC_FREE(netlogon_pipe);
2500 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2503 result = rpccli_netlogon_setup_creds(
2504 netlogon_pipe,
2505 domain->dcname, /* server name. */
2506 domain->name, /* domain name */
2507 global_myname(), /* client name */
2508 account_name, /* machine account */
2509 mach_pwd, /* machine password */
2510 sec_chan_type, /* from get_trust_pw */
2511 &neg_flags);
2513 if (!NT_STATUS_IS_OK(result)) {
2514 TALLOC_FREE(netlogon_pipe);
2515 return result;
2518 if ((lp_client_schannel() == True) &&
2519 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2520 DEBUG(3, ("Server did not offer schannel\n"));
2521 TALLOC_FREE(netlogon_pipe);
2522 return NT_STATUS_ACCESS_DENIED;
2525 no_schannel:
2526 if ((lp_client_schannel() == False) ||
2527 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2529 * NetSamLogonEx only works for schannel
2531 domain->can_do_samlogon_ex = False;
2533 /* We're done - just keep the existing connection to NETLOGON
2534 * open */
2535 conn->netlogon_pipe = netlogon_pipe;
2536 *cli = conn->netlogon_pipe;
2537 return NT_STATUS_OK;
2540 /* Using the credentials from the first pipe, open a signed and sealed
2541 second netlogon pipe. The session key is stored in the schannel
2542 part of the new pipe auth struct.
2545 result = cli_rpc_pipe_open_schannel_with_key(
2546 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2547 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2548 &conn->netlogon_pipe);
2550 /* We can now close the initial netlogon pipe. */
2551 TALLOC_FREE(netlogon_pipe);
2553 if (!NT_STATUS_IS_OK(result)) {
2554 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2555 "was %s\n", nt_errstr(result)));
2557 invalidate_cm_connection(conn);
2558 return result;
2562 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2563 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2564 * supported). We used to only try SamLogonEx for AD, but
2565 * Samba DCs can also do it. And because we don't distinguish
2566 * between Samba and NT4, always try it once.
2568 domain->can_do_samlogon_ex = true;
2570 *cli = conn->netlogon_pipe;
2571 return NT_STATUS_OK;