s3:winbindd_cm: use rpccli_is_connected() helper function
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob24e555607baf510afa6addb1c7ffb0b56d89870d
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 "../librpc/gen_ndr/cli_samr.h"
66 #include "../librpc/gen_ndr/cli_lsa.h"
67 #include "../librpc/gen_ndr/cli_dssetup.h"
68 #include "libads/sitename_cache.h"
70 #undef DBGC_CLASS
71 #define DBGC_CLASS DBGC_WINBIND
73 struct dc_name_ip {
74 fstring name;
75 struct sockaddr_storage ss;
78 extern struct winbindd_methods reconnect_methods;
79 extern bool override_logfile;
81 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
82 static void set_dc_type_and_flags( struct winbindd_domain *domain );
83 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
84 struct dc_name_ip **dcs, int *num_dcs);
86 /****************************************************************
87 Child failed to find DC's. Reschedule check.
88 ****************************************************************/
90 static void msg_failed_to_go_online(struct messaging_context *msg,
91 void *private_data,
92 uint32_t msg_type,
93 struct server_id server_id,
94 DATA_BLOB *data)
96 struct winbindd_domain *domain;
97 const char *domainname = (const char *)data->data;
99 if (data->data == NULL || data->length == 0) {
100 return;
103 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
105 for (domain = domain_list(); domain; domain = domain->next) {
106 if (domain->internal) {
107 continue;
110 if (strequal(domain->name, domainname)) {
111 if (domain->online) {
112 /* We're already online, ignore. */
113 DEBUG(5,("msg_fail_to_go_online: domain %s "
114 "already online.\n", domainname));
115 continue;
118 /* Reschedule the online check. */
119 set_domain_offline(domain);
120 break;
125 /****************************************************************
126 Actually cause a reconnect from a message.
127 ****************************************************************/
129 static void msg_try_to_go_online(struct messaging_context *msg,
130 void *private_data,
131 uint32_t msg_type,
132 struct server_id server_id,
133 DATA_BLOB *data)
135 struct winbindd_domain *domain;
136 const char *domainname = (const char *)data->data;
138 if (data->data == NULL || data->length == 0) {
139 return;
142 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
144 for (domain = domain_list(); domain; domain = domain->next) {
145 if (domain->internal) {
146 continue;
149 if (strequal(domain->name, domainname)) {
151 if (domain->online) {
152 /* We're already online, ignore. */
153 DEBUG(5,("msg_try_to_go_online: domain %s "
154 "already online.\n", domainname));
155 continue;
158 /* This call takes care of setting the online
159 flag to true if we connected, or re-adding
160 the offline handler if false. Bypasses online
161 check so always does network calls. */
163 init_dc_connection_network(domain);
164 break;
169 /****************************************************************
170 Fork a child to try and contact a DC. Do this as contacting a
171 DC requires blocking lookups and we don't want to block our
172 parent.
173 ****************************************************************/
175 static bool fork_child_dc_connect(struct winbindd_domain *domain)
177 struct dc_name_ip *dcs = NULL;
178 int num_dcs = 0;
179 TALLOC_CTX *mem_ctx = NULL;
180 pid_t parent_pid = sys_getpid();
181 char *lfile = NULL;
183 /* Stop zombies */
184 CatchChild();
186 if (domain->dc_probe_pid != (pid_t)-1) {
188 * We might already have a DC probe
189 * child working, check.
191 if (process_exists_by_pid(domain->dc_probe_pid)) {
192 DEBUG(10,("fork_child_dc_connect: pid %u already "
193 "checking for DC's.\n",
194 (unsigned int)domain->dc_probe_pid));
195 return true;
197 domain->dc_probe_pid = (pid_t)-1;
200 domain->dc_probe_pid = sys_fork();
202 if (domain->dc_probe_pid == (pid_t)-1) {
203 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
204 return False;
207 if (domain->dc_probe_pid != (pid_t)0) {
208 /* Parent */
209 messaging_register(winbind_messaging_context(), NULL,
210 MSG_WINBIND_TRY_TO_GO_ONLINE,
211 msg_try_to_go_online);
212 messaging_register(winbind_messaging_context(), NULL,
213 MSG_WINBIND_FAILED_TO_GO_ONLINE,
214 msg_failed_to_go_online);
215 return True;
218 /* Child. */
220 /* Leave messages blocked - we will never process one. */
222 if (!override_logfile) {
223 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
224 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
225 _exit(1);
229 if (!winbindd_reinit_after_fork(lfile)) {
230 messaging_send_buf(winbind_messaging_context(),
231 pid_to_procid(parent_pid),
232 MSG_WINBIND_FAILED_TO_GO_ONLINE,
233 (uint8 *)domain->name,
234 strlen(domain->name)+1);
235 _exit(1);
237 SAFE_FREE(lfile);
239 mem_ctx = talloc_init("fork_child_dc_connect");
240 if (!mem_ctx) {
241 DEBUG(0,("talloc_init failed.\n"));
242 messaging_send_buf(winbind_messaging_context(),
243 pid_to_procid(parent_pid),
244 MSG_WINBIND_FAILED_TO_GO_ONLINE,
245 (uint8 *)domain->name,
246 strlen(domain->name)+1);
247 _exit(1);
250 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
251 /* Still offline ? Can't find DC's. */
252 messaging_send_buf(winbind_messaging_context(),
253 pid_to_procid(parent_pid),
254 MSG_WINBIND_FAILED_TO_GO_ONLINE,
255 (uint8 *)domain->name,
256 strlen(domain->name)+1);
257 _exit(0);
260 /* We got a DC. Send a message to our parent to get it to
261 try and do the same. */
263 messaging_send_buf(winbind_messaging_context(),
264 pid_to_procid(parent_pid),
265 MSG_WINBIND_TRY_TO_GO_ONLINE,
266 (uint8 *)domain->name,
267 strlen(domain->name)+1);
268 _exit(0);
271 /****************************************************************
272 Handler triggered if we're offline to try and detect a DC.
273 ****************************************************************/
275 static void check_domain_online_handler(struct event_context *ctx,
276 struct timed_event *te,
277 struct timeval now,
278 void *private_data)
280 struct winbindd_domain *domain =
281 (struct winbindd_domain *)private_data;
283 DEBUG(10,("check_domain_online_handler: called for domain "
284 "%s (online = %s)\n", domain->name,
285 domain->online ? "True" : "False" ));
287 TALLOC_FREE(domain->check_online_event);
289 /* Are we still in "startup" mode ? */
291 if (domain->startup && (now.tv_sec > domain->startup_time + 30)) {
292 /* No longer in "startup" mode. */
293 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
294 domain->name ));
295 domain->startup = False;
298 /* We've been told to stay offline, so stay
299 that way. */
301 if (get_global_winbindd_state_offline()) {
302 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
303 domain->name ));
304 return;
307 /* Fork a child to test if it can contact a DC.
308 If it can then send ourselves a message to
309 cause a reconnect. */
311 fork_child_dc_connect(domain);
314 /****************************************************************
315 If we're still offline setup the timeout check.
316 ****************************************************************/
318 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
320 int wbr = lp_winbind_reconnect_delay();
322 if (domain->startup) {
323 domain->check_online_timeout = 10;
324 } else if (domain->check_online_timeout < wbr) {
325 domain->check_online_timeout = wbr;
329 /****************************************************************
330 Set domain offline and also add handler to put us back online
331 if we detect a DC.
332 ****************************************************************/
334 void set_domain_offline(struct winbindd_domain *domain)
336 DEBUG(10,("set_domain_offline: called for domain %s\n",
337 domain->name ));
339 TALLOC_FREE(domain->check_online_event);
341 if (domain->internal) {
342 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
343 domain->name ));
344 return;
347 domain->online = False;
349 /* Offline domains are always initialized. They're
350 re-initialized when they go back online. */
352 domain->initialized = True;
354 /* We only add the timeout handler that checks and
355 allows us to go back online when we've not
356 been told to remain offline. */
358 if (get_global_winbindd_state_offline()) {
359 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
360 domain->name ));
361 return;
364 /* If we're in startup mode, check again in 10 seconds, not in
365 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
367 calc_new_online_timeout_check(domain);
369 domain->check_online_event = event_add_timed(winbind_event_context(),
370 NULL,
371 timeval_current_ofs(domain->check_online_timeout,0),
372 check_domain_online_handler,
373 domain);
375 /* The above *has* to succeed for winbindd to work. */
376 if (!domain->check_online_event) {
377 smb_panic("set_domain_offline: failed to add online handler");
380 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
381 domain->name ));
383 /* Send an offline message to the idmap child when our
384 primary domain goes offline */
386 if ( domain->primary ) {
387 struct winbindd_child *idmap = idmap_child();
389 if ( idmap->pid != 0 ) {
390 messaging_send_buf(winbind_messaging_context(),
391 pid_to_procid(idmap->pid),
392 MSG_WINBIND_OFFLINE,
393 (uint8 *)domain->name,
394 strlen(domain->name)+1);
398 return;
401 /****************************************************************
402 Set domain online - if allowed.
403 ****************************************************************/
405 static void set_domain_online(struct winbindd_domain *domain)
407 DEBUG(10,("set_domain_online: called for domain %s\n",
408 domain->name ));
410 if (domain->internal) {
411 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
412 domain->name ));
413 return;
416 if (get_global_winbindd_state_offline()) {
417 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
418 domain->name ));
419 return;
422 winbindd_set_locator_kdc_envs(domain);
424 /* If we are waiting to get a krb5 ticket, trigger immediately. */
425 ccache_regain_all_now();
427 /* Ok, we're out of any startup mode now... */
428 domain->startup = False;
430 if (domain->online == False) {
431 /* We were offline - now we're online. We default to
432 using the MS-RPC backend if we started offline,
433 and if we're going online for the first time we
434 should really re-initialize the backends and the
435 checks to see if we're talking to an AD or NT domain.
438 domain->initialized = False;
440 /* 'reconnect_methods' is the MS-RPC backend. */
441 if (domain->backend == &reconnect_methods) {
442 domain->backend = NULL;
446 /* Ensure we have no online timeout checks. */
447 domain->check_online_timeout = 0;
448 TALLOC_FREE(domain->check_online_event);
450 /* Ensure we ignore any pending child messages. */
451 messaging_deregister(winbind_messaging_context(),
452 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
453 messaging_deregister(winbind_messaging_context(),
454 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
456 domain->online = True;
458 /* Send an online message to the idmap child when our
459 primary domain comes online */
461 if ( domain->primary ) {
462 struct winbindd_child *idmap = idmap_child();
464 if ( idmap->pid != 0 ) {
465 messaging_send_buf(winbind_messaging_context(),
466 pid_to_procid(idmap->pid),
467 MSG_WINBIND_ONLINE,
468 (uint8 *)domain->name,
469 strlen(domain->name)+1);
473 return;
476 /****************************************************************
477 Requested to set a domain online.
478 ****************************************************************/
480 void set_domain_online_request(struct winbindd_domain *domain)
482 struct timeval tev;
484 DEBUG(10,("set_domain_online_request: called for domain %s\n",
485 domain->name ));
487 if (get_global_winbindd_state_offline()) {
488 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
489 domain->name ));
490 return;
493 if (domain->internal) {
494 DEBUG(10, ("set_domain_online_request: Internal domains are "
495 "always online\n"));
496 return;
499 /* We've been told it's safe to go online and
500 try and connect to a DC. But I don't believe it
501 because network manager seems to lie.
502 Wait at least 5 seconds. Heuristics suck... */
505 GetTimeOfDay(&tev);
507 /* Go into "startup" mode again. */
508 domain->startup_time = tev.tv_sec;
509 domain->startup = True;
511 tev.tv_sec += 5;
513 if (!domain->check_online_event) {
514 /* If we've come from being globally offline we
515 don't have a check online event handler set.
516 We need to add one now we're trying to go
517 back online. */
519 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
520 domain->name ));
523 TALLOC_FREE(domain->check_online_event);
525 domain->check_online_event = event_add_timed(winbind_event_context(),
526 NULL,
527 tev,
528 check_domain_online_handler,
529 domain);
531 /* The above *has* to succeed for winbindd to work. */
532 if (!domain->check_online_event) {
533 smb_panic("set_domain_online_request: failed to add online handler");
537 /****************************************************************
538 Add -ve connection cache entries for domain and realm.
539 ****************************************************************/
541 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
542 const char *server,
543 NTSTATUS result)
545 add_failed_connection_entry(domain->name, server, result);
546 /* If this was the saf name for the last thing we talked to,
547 remove it. */
548 saf_delete(domain->name);
549 if (*domain->alt_name) {
550 add_failed_connection_entry(domain->alt_name, server, result);
551 saf_delete(domain->alt_name);
553 winbindd_unset_locator_kdc_env(domain);
556 /* Choose between anonymous or authenticated connections. We need to use
557 an authenticated connection if DCs have the RestrictAnonymous registry
558 entry set > 0, or the "Additional restrictions for anonymous
559 connections" set in the win2k Local Security Policy.
561 Caller to free() result in domain, username, password
564 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
566 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
567 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
568 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
570 if (*username && **username) {
572 if (!*domain || !**domain)
573 *domain = smb_xstrdup(lp_workgroup());
575 if (!*password || !**password)
576 *password = smb_xstrdup("");
578 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
579 *domain, *username));
581 } else {
582 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
583 *username = smb_xstrdup("");
584 *domain = smb_xstrdup("");
585 *password = smb_xstrdup("");
589 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
590 fstring dcname,
591 struct sockaddr_storage *dc_ss)
593 struct winbindd_domain *our_domain = NULL;
594 struct rpc_pipe_client *netlogon_pipe = NULL;
595 NTSTATUS result;
596 WERROR werr;
597 TALLOC_CTX *mem_ctx;
598 unsigned int orig_timeout;
599 const char *tmp = NULL;
600 const char *p;
602 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
603 * moment.... */
605 if (IS_DC) {
606 return False;
609 if (domain->primary) {
610 return False;
613 our_domain = find_our_domain();
615 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
616 return False;
619 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
620 if (!NT_STATUS_IS_OK(result)) {
621 talloc_destroy(mem_ctx);
622 return False;
625 /* This call can take a long time - allow the server to time out.
626 35 seconds should do it. */
628 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
630 if (our_domain->active_directory) {
631 struct netr_DsRGetDCNameInfo *domain_info = NULL;
633 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
634 mem_ctx,
635 our_domain->dcname,
636 domain->name,
637 NULL,
638 NULL,
639 DS_RETURN_DNS_NAME,
640 &domain_info,
641 &werr);
642 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
643 tmp = talloc_strdup(
644 mem_ctx, domain_info->dc_unc);
645 if (tmp == NULL) {
646 DEBUG(0, ("talloc_strdup failed\n"));
647 talloc_destroy(mem_ctx);
648 return false;
650 if (strlen(domain->alt_name) == 0) {
651 fstrcpy(domain->alt_name,
652 domain_info->domain_name);
654 if (strlen(domain->forest_name) == 0) {
655 fstrcpy(domain->forest_name,
656 domain_info->forest_name);
659 } else {
660 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
661 our_domain->dcname,
662 domain->name,
663 &tmp,
664 &werr);
667 /* And restore our original timeout. */
668 rpccli_set_timeout(netlogon_pipe, orig_timeout);
670 if (!NT_STATUS_IS_OK(result)) {
671 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
672 nt_errstr(result)));
673 talloc_destroy(mem_ctx);
674 return false;
677 if (!W_ERROR_IS_OK(werr)) {
678 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
679 win_errstr(werr)));
680 talloc_destroy(mem_ctx);
681 return false;
684 /* rpccli_netr_GetAnyDCName gives us a name with \\ */
685 p = strip_hostname(tmp);
687 fstrcpy(dcname, p);
689 talloc_destroy(mem_ctx);
691 DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
693 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
694 return False;
697 return True;
701 * Helper function to assemble trust password and account name
703 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
704 char **machine_password,
705 char **machine_account,
706 char **machine_krb5_principal)
708 const char *account_name;
709 const char *name = NULL;
711 /* If we are a DC and this is not our own domain */
713 if (IS_DC) {
714 name = domain->name;
715 } else {
716 struct winbindd_domain *our_domain = find_our_domain();
718 if (!our_domain)
719 return NT_STATUS_INVALID_SERVER_STATE;
721 name = our_domain->name;
724 if (!get_trust_pw_clear(name, machine_password,
725 &account_name, NULL))
727 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
730 if ((machine_account != NULL) &&
731 (asprintf(machine_account, "%s$", account_name) == -1))
733 return NT_STATUS_NO_MEMORY;
736 /* For now assume our machine account only exists in our domain */
738 if (machine_krb5_principal != NULL)
740 struct winbindd_domain *our_domain = find_our_domain();
742 if (!our_domain) {
743 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
746 if (asprintf(machine_krb5_principal, "%s$@%s",
747 account_name, our_domain->alt_name) == -1)
749 return NT_STATUS_NO_MEMORY;
752 strupper_m(*machine_krb5_principal);
755 return NT_STATUS_OK;
758 /************************************************************************
759 Given a fd with a just-connected TCP connection to a DC, open a connection
760 to the pipe.
761 ************************************************************************/
763 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
764 const int sockfd,
765 const char *controller,
766 struct cli_state **cli,
767 bool *retry)
769 char *machine_password = NULL;
770 char *machine_krb5_principal = NULL;
771 char *machine_account = NULL;
772 char *ipc_username = NULL;
773 char *ipc_domain = NULL;
774 char *ipc_password = NULL;
776 struct named_mutex *mutex;
778 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
780 struct sockaddr peeraddr;
781 socklen_t peeraddr_len;
783 struct sockaddr_in *peeraddr_in =
784 (struct sockaddr_in *)(void *)&peeraddr;
786 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
787 controller, domain->name ));
789 *retry = True;
791 mutex = grab_named_mutex(talloc_tos(), controller,
792 WINBIND_SERVER_MUTEX_WAIT_TIME);
793 if (mutex == NULL) {
794 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
795 controller));
796 result = NT_STATUS_POSSIBLE_DEADLOCK;
797 goto done;
800 if ((*cli = cli_initialise()) == NULL) {
801 DEBUG(1, ("Could not cli_initialize\n"));
802 result = NT_STATUS_NO_MEMORY;
803 goto done;
806 (*cli)->timeout = 10000; /* 10 seconds */
807 (*cli)->fd = sockfd;
808 fstrcpy((*cli)->desthost, controller);
809 (*cli)->use_kerberos = True;
811 peeraddr_len = sizeof(peeraddr);
813 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
814 (peeraddr_len != sizeof(struct sockaddr_in)) ||
815 (peeraddr_in->sin_family != PF_INET))
817 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
818 result = NT_STATUS_UNSUCCESSFUL;
819 goto done;
822 if (ntohs(peeraddr_in->sin_port) == 139) {
823 struct nmb_name calling;
824 struct nmb_name called;
826 make_nmb_name(&calling, global_myname(), 0x0);
827 make_nmb_name(&called, "*SMBSERVER", 0x20);
829 if (!cli_session_request(*cli, &calling, &called)) {
830 DEBUG(8, ("cli_session_request failed for %s\n",
831 controller));
832 result = NT_STATUS_UNSUCCESSFUL;
833 goto done;
837 result = cli_negprot(*cli);
839 if (!NT_STATUS_IS_OK(result)) {
840 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
841 goto done;
844 if (!is_dc_trusted_domain_situation(domain->name) &&
845 (*cli)->protocol >= PROTOCOL_NT1 &&
846 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
848 ADS_STATUS ads_status;
850 result = get_trust_creds(domain, &machine_password,
851 &machine_account,
852 &machine_krb5_principal);
853 if (!NT_STATUS_IS_OK(result)) {
854 goto anon_fallback;
857 if (lp_security() == SEC_ADS) {
859 /* Try a krb5 session */
861 (*cli)->use_kerberos = True;
862 DEBUG(5, ("connecting to %s from %s with kerberos principal "
863 "[%s] and realm [%s]\n", controller, global_myname(),
864 machine_krb5_principal, domain->alt_name));
866 winbindd_set_locator_kdc_envs(domain);
868 ads_status = cli_session_setup_spnego(*cli,
869 machine_krb5_principal,
870 machine_password,
871 lp_workgroup(),
872 domain->alt_name);
874 if (!ADS_ERR_OK(ads_status)) {
875 DEBUG(4,("failed kerberos session setup with %s\n",
876 ads_errstr(ads_status)));
879 result = ads_ntstatus(ads_status);
880 if (NT_STATUS_IS_OK(result)) {
881 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
882 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
883 if (!NT_STATUS_IS_OK(result)) {
884 goto done;
886 goto session_setup_done;
890 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
891 (*cli)->use_kerberos = False;
893 DEBUG(5, ("connecting to %s from %s with username "
894 "[%s]\\[%s]\n", controller, global_myname(),
895 lp_workgroup(), machine_account));
897 ads_status = cli_session_setup_spnego(*cli,
898 machine_account,
899 machine_password,
900 lp_workgroup(),
901 NULL);
902 if (!ADS_ERR_OK(ads_status)) {
903 DEBUG(4, ("authenticated session setup failed with %s\n",
904 ads_errstr(ads_status)));
907 result = ads_ntstatus(ads_status);
908 if (NT_STATUS_IS_OK(result)) {
909 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
910 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
911 if (!NT_STATUS_IS_OK(result)) {
912 goto done;
914 goto session_setup_done;
918 /* Fall back to non-kerberos session setup with auth_user */
920 (*cli)->use_kerberos = False;
922 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
924 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
925 (strlen(ipc_username) > 0)) {
927 /* Only try authenticated if we have a username */
929 DEBUG(5, ("connecting to %s from %s with username "
930 "[%s]\\[%s]\n", controller, global_myname(),
931 ipc_domain, ipc_username));
933 if (NT_STATUS_IS_OK(cli_session_setup(
934 *cli, ipc_username,
935 ipc_password, strlen(ipc_password)+1,
936 ipc_password, strlen(ipc_password)+1,
937 ipc_domain))) {
938 /* Successful logon with given username. */
939 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
940 if (!NT_STATUS_IS_OK(result)) {
941 goto done;
943 goto session_setup_done;
944 } else {
945 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
946 ipc_domain, ipc_username ));
950 anon_fallback:
952 /* Fall back to anonymous connection, this might fail later */
953 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
954 "connection for DC %s\n",
955 controller ));
957 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
958 NULL, 0, ""))) {
959 DEBUG(5, ("Connected anonymously\n"));
960 result = cli_init_creds(*cli, "", "", "");
961 if (!NT_STATUS_IS_OK(result)) {
962 goto done;
964 goto session_setup_done;
967 result = cli_nt_error(*cli);
969 if (NT_STATUS_IS_OK(result))
970 result = NT_STATUS_UNSUCCESSFUL;
972 /* We can't session setup */
974 goto done;
976 session_setup_done:
978 /* cache the server name for later connections */
980 saf_store( domain->name, (*cli)->desthost );
981 if (domain->alt_name && (*cli)->use_kerberos) {
982 saf_store( domain->alt_name, (*cli)->desthost );
985 winbindd_set_locator_kdc_envs(domain);
987 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
989 if (!NT_STATUS_IS_OK(result)) {
990 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
991 goto done;
994 TALLOC_FREE(mutex);
995 *retry = False;
997 /* set the domain if empty; needed for schannel connections */
998 if ( !(*cli)->domain[0] ) {
999 result = cli_set_domain((*cli), domain->name);
1000 if (!NT_STATUS_IS_OK(result)) {
1001 return result;
1005 result = NT_STATUS_OK;
1007 done:
1008 TALLOC_FREE(mutex);
1009 SAFE_FREE(machine_account);
1010 SAFE_FREE(machine_password);
1011 SAFE_FREE(machine_krb5_principal);
1012 SAFE_FREE(ipc_username);
1013 SAFE_FREE(ipc_domain);
1014 SAFE_FREE(ipc_password);
1016 if (!NT_STATUS_IS_OK(result)) {
1017 winbind_add_failed_connection_entry(domain, controller, result);
1018 if ((*cli) != NULL) {
1019 cli_shutdown(*cli);
1020 *cli = NULL;
1024 return result;
1027 /*******************************************************************
1028 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1029 array.
1031 Keeps the list unique by not adding duplicate entries.
1033 @param[in] mem_ctx talloc memory context to allocate from
1034 @param[in] domain_name domain of the DC
1035 @param[in] dcname name of the DC to add to the list
1036 @param[in] pss Internet address and port pair to add to the list
1037 @param[in,out] dcs array of dc_name_ip structures to add to
1038 @param[in,out] num_dcs number of dcs returned in the dcs array
1039 @return true if the list was added to, false otherwise
1040 *******************************************************************/
1042 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1043 const char *dcname, struct sockaddr_storage *pss,
1044 struct dc_name_ip **dcs, int *num)
1046 int i = 0;
1048 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1049 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1050 return False;
1053 /* Make sure there's no duplicates in the list */
1054 for (i=0; i<*num; i++)
1055 if (sockaddr_equal(
1056 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1057 (struct sockaddr *)(void *)pss))
1058 return False;
1060 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1062 if (*dcs == NULL)
1063 return False;
1065 fstrcpy((*dcs)[*num].name, dcname);
1066 (*dcs)[*num].ss = *pss;
1067 *num += 1;
1068 return True;
1071 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1072 struct sockaddr_storage *pss, uint16 port,
1073 struct sockaddr_storage **addrs, int *num)
1075 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1077 if (*addrs == NULL) {
1078 *num = 0;
1079 return False;
1082 (*addrs)[*num] = *pss;
1083 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1085 *num += 1;
1086 return True;
1089 /*******************************************************************
1090 convert an ip to a name
1091 *******************************************************************/
1093 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1094 const struct winbindd_domain *domain,
1095 struct sockaddr_storage *pss,
1096 fstring name )
1098 struct ip_service ip_list;
1099 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1101 ip_list.ss = *pss;
1102 ip_list.port = 0;
1104 #ifdef WITH_ADS
1105 /* For active directory servers, try to get the ldap server name.
1106 None of these failures should be considered critical for now */
1108 if (lp_security() == SEC_ADS) {
1109 ADS_STRUCT *ads;
1110 ADS_STATUS ads_status;
1111 char addr[INET6_ADDRSTRLEN];
1113 print_sockaddr(addr, sizeof(addr), pss);
1115 ads = ads_init(domain->alt_name, domain->name, addr);
1116 ads->auth.flags |= ADS_AUTH_NO_BIND;
1118 ads_status = ads_connect(ads);
1119 if (ADS_ERR_OK(ads_status)) {
1120 /* We got a cldap packet. */
1121 fstrcpy(name, ads->config.ldap_server_name);
1122 namecache_store(name, 0x20, 1, &ip_list);
1124 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1126 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1127 if (ads_closest_dc(ads)) {
1128 char *sitename = sitename_fetch(ads->config.realm);
1130 /* We're going to use this KDC for this realm/domain.
1131 If we are using sites, then force the krb5 libs
1132 to use this KDC. */
1134 create_local_private_krb5_conf_for_domain(domain->alt_name,
1135 domain->name,
1136 sitename,
1137 pss);
1139 SAFE_FREE(sitename);
1140 } else {
1141 /* use an off site KDC */
1142 create_local_private_krb5_conf_for_domain(domain->alt_name,
1143 domain->name,
1144 NULL,
1145 pss);
1147 winbindd_set_locator_kdc_envs(domain);
1149 /* Ensure we contact this DC also. */
1150 saf_store( domain->name, name);
1151 saf_store( domain->alt_name, name);
1154 ads_destroy( &ads );
1155 return True;
1158 ads_destroy( &ads );
1160 #endif
1162 /* try GETDC requests next */
1164 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1165 pss, domain->name, &domain->sid,
1166 nt_version)) {
1167 const char *dc_name = NULL;
1168 int i;
1169 smb_msleep(100);
1170 for (i=0; i<5; i++) {
1171 if (receive_getdc_response(mem_ctx, pss, domain->name,
1172 &nt_version,
1173 &dc_name, NULL)) {
1174 fstrcpy(name, dc_name);
1175 namecache_store(name, 0x20, 1, &ip_list);
1176 return True;
1178 smb_msleep(500);
1182 /* try node status request */
1184 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1185 namecache_store(name, 0x20, 1, &ip_list);
1186 return True;
1188 return False;
1191 /*******************************************************************
1192 Retrieve a list of IP addresses for domain controllers.
1194 The array is sorted in the preferred connection order.
1196 @param[in] mem_ctx talloc memory context to allocate from
1197 @param[in] domain domain to retrieve DCs for
1198 @param[out] dcs array of dcs that will be returned
1199 @param[out] num_dcs number of dcs returned in the dcs array
1200 @return always true
1201 *******************************************************************/
1203 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1204 struct dc_name_ip **dcs, int *num_dcs)
1206 fstring dcname;
1207 struct sockaddr_storage ss;
1208 struct ip_service *ip_list = NULL;
1209 int iplist_size = 0;
1210 int i;
1211 bool is_our_domain;
1212 enum security_types sec = (enum security_types)lp_security();
1214 is_our_domain = strequal(domain->name, lp_workgroup());
1216 /* If not our domain, get the preferred DC, by asking our primary DC */
1217 if ( !is_our_domain
1218 && get_dc_name_via_netlogon(domain, dcname, &ss)
1219 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1220 num_dcs) )
1222 char addr[INET6_ADDRSTRLEN];
1223 print_sockaddr(addr, sizeof(addr), &ss);
1224 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1225 dcname, addr));
1226 return True;
1229 if (sec == SEC_ADS) {
1230 char *sitename = NULL;
1232 /* We need to make sure we know the local site before
1233 doing any DNS queries, as this will restrict the
1234 get_sorted_dc_list() call below to only fetching
1235 DNS records for the correct site. */
1237 /* Find any DC to get the site record.
1238 We deliberately don't care about the
1239 return here. */
1241 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1243 sitename = sitename_fetch(domain->alt_name);
1244 if (sitename) {
1246 /* Do the site-specific AD dns lookup first. */
1247 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1248 &iplist_size, True);
1250 /* Add ips to the DC array. We don't look up the name
1251 of the DC in this function, but we fill in the char*
1252 of the ip now to make the failed connection cache
1253 work */
1254 for ( i=0; i<iplist_size; i++ ) {
1255 char addr[INET6_ADDRSTRLEN];
1256 print_sockaddr(addr, sizeof(addr),
1257 &ip_list[i].ss);
1258 add_one_dc_unique(mem_ctx,
1259 domain->name,
1260 addr,
1261 &ip_list[i].ss,
1262 dcs,
1263 num_dcs);
1266 SAFE_FREE(ip_list);
1267 SAFE_FREE(sitename);
1268 iplist_size = 0;
1271 /* Now we add DCs from the main AD DNS lookup. */
1272 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1273 &iplist_size, True);
1275 for ( i=0; i<iplist_size; i++ ) {
1276 char addr[INET6_ADDRSTRLEN];
1277 print_sockaddr(addr, sizeof(addr),
1278 &ip_list[i].ss);
1279 add_one_dc_unique(mem_ctx,
1280 domain->name,
1281 addr,
1282 &ip_list[i].ss,
1283 dcs,
1284 num_dcs);
1287 SAFE_FREE(ip_list);
1288 iplist_size = 0;
1291 /* Try standard netbios queries if no ADS */
1292 if (*num_dcs == 0) {
1293 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1294 False);
1296 for ( i=0; i<iplist_size; i++ ) {
1297 char addr[INET6_ADDRSTRLEN];
1298 print_sockaddr(addr, sizeof(addr),
1299 &ip_list[i].ss);
1300 add_one_dc_unique(mem_ctx,
1301 domain->name,
1302 addr,
1303 &ip_list[i].ss,
1304 dcs,
1305 num_dcs);
1308 SAFE_FREE(ip_list);
1309 iplist_size = 0;
1312 return True;
1315 /*******************************************************************
1316 Find and make a connection to a DC in the given domain.
1318 @param[in] mem_ctx talloc memory context to allocate from
1319 @param[in] domain domain to find a dc in
1320 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1321 @param[out] pss DC Internet address and port
1322 @param[out] fd fd of the open socket connected to the newly found dc
1323 @return true when a DC connection is made, false otherwise
1324 *******************************************************************/
1326 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1327 struct winbindd_domain *domain,
1328 fstring dcname, struct sockaddr_storage *pss, int *fd)
1330 struct dc_name_ip *dcs = NULL;
1331 int num_dcs = 0;
1333 const char **dcnames = NULL;
1334 int num_dcnames = 0;
1336 struct sockaddr_storage *addrs = NULL;
1337 int num_addrs = 0;
1339 int i, fd_index;
1341 *fd = -1;
1343 again:
1344 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1345 return False;
1347 for (i=0; i<num_dcs; i++) {
1349 if (!add_string_to_array(mem_ctx, dcs[i].name,
1350 &dcnames, &num_dcnames)) {
1351 return False;
1353 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1354 &addrs, &num_addrs)) {
1355 return False;
1358 if (!add_string_to_array(mem_ctx, dcs[i].name,
1359 &dcnames, &num_dcnames)) {
1360 return False;
1362 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1363 &addrs, &num_addrs)) {
1364 return False;
1368 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1369 return False;
1371 if ((addrs == NULL) || (dcnames == NULL))
1372 return False;
1374 /* 5 second timeout. */
1375 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1376 for (i=0; i<num_dcs; i++) {
1377 char ab[INET6_ADDRSTRLEN];
1378 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1379 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1380 "domain %s address %s. Error was %s\n",
1381 domain->name, ab, strerror(errno) ));
1382 winbind_add_failed_connection_entry(domain,
1383 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1385 return False;
1388 *pss = addrs[fd_index];
1390 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1391 /* Ok, we've got a name for the DC */
1392 fstrcpy(dcname, dcnames[fd_index]);
1393 return True;
1396 /* Try to figure out the name */
1397 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1398 return True;
1401 /* We can not continue without the DC's name */
1402 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1403 NT_STATUS_UNSUCCESSFUL);
1405 /* Throw away all arrays as we're doing this again. */
1406 TALLOC_FREE(dcs);
1407 num_dcs = 0;
1409 TALLOC_FREE(dcnames);
1410 num_dcnames = 0;
1412 TALLOC_FREE(addrs);
1413 num_addrs = 0;
1415 close(*fd);
1416 *fd = -1;
1418 goto again;
1421 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1422 struct winbindd_cm_conn *new_conn)
1424 TALLOC_CTX *mem_ctx;
1425 NTSTATUS result;
1426 char *saf_servername = saf_fetch( domain->name );
1427 int retries;
1429 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1430 SAFE_FREE(saf_servername);
1431 set_domain_offline(domain);
1432 return NT_STATUS_NO_MEMORY;
1435 /* we have to check the server affinity cache here since
1436 later we selecte a DC based on response time and not preference */
1438 /* Check the negative connection cache
1439 before talking to it. It going down may have
1440 triggered the reconnection. */
1442 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1444 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1445 saf_servername, domain->name ));
1447 /* convert an ip address to a name */
1448 if (is_ipaddress( saf_servername ) ) {
1449 fstring saf_name;
1450 struct sockaddr_storage ss;
1452 if (!interpret_string_addr(&ss, saf_servername,
1453 AI_NUMERICHOST)) {
1454 return NT_STATUS_UNSUCCESSFUL;
1456 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1457 fstrcpy( domain->dcname, saf_name );
1458 } else {
1459 winbind_add_failed_connection_entry(
1460 domain, saf_servername,
1461 NT_STATUS_UNSUCCESSFUL);
1463 } else {
1464 fstrcpy( domain->dcname, saf_servername );
1467 SAFE_FREE( saf_servername );
1470 for (retries = 0; retries < 3; retries++) {
1471 int fd = -1;
1472 bool retry = False;
1474 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1476 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1477 domain->dcname, domain->name ));
1479 if (*domain->dcname
1480 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1481 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1483 struct sockaddr_storage *addrs = NULL;
1484 int num_addrs = 0;
1485 int dummy = 0;
1487 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1488 set_domain_offline(domain);
1489 talloc_destroy(mem_ctx);
1490 return NT_STATUS_NO_MEMORY;
1492 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1493 set_domain_offline(domain);
1494 talloc_destroy(mem_ctx);
1495 return NT_STATUS_NO_MEMORY;
1498 /* 5 second timeout. */
1499 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1500 fd = -1;
1504 if ((fd == -1)
1505 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1507 /* This is the one place where we will
1508 set the global winbindd offline state
1509 to true, if a "WINBINDD_OFFLINE" entry
1510 is found in the winbindd cache. */
1511 set_global_winbindd_state_offline();
1512 break;
1515 new_conn->cli = NULL;
1517 result = cm_prepare_connection(domain, fd, domain->dcname,
1518 &new_conn->cli, &retry);
1520 if (!retry)
1521 break;
1524 if (NT_STATUS_IS_OK(result)) {
1526 winbindd_set_locator_kdc_envs(domain);
1528 if (domain->online == False) {
1529 /* We're changing state from offline to online. */
1530 set_global_winbindd_state_online();
1532 set_domain_online(domain);
1533 } else {
1534 /* Ensure we setup the retry handler. */
1535 set_domain_offline(domain);
1538 talloc_destroy(mem_ctx);
1539 return result;
1542 /* Close down all open pipes on a connection. */
1544 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1546 /* We're closing down a possibly dead
1547 connection. Don't have impossibly long (10s) timeouts. */
1549 if (conn->cli) {
1550 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1553 if (conn->samr_pipe != NULL) {
1554 TALLOC_FREE(conn->samr_pipe);
1555 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1556 if (conn->cli) {
1557 cli_set_timeout(conn->cli, 500);
1561 if (conn->lsa_pipe != NULL) {
1562 TALLOC_FREE(conn->lsa_pipe);
1563 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1564 if (conn->cli) {
1565 cli_set_timeout(conn->cli, 500);
1569 if (conn->lsa_pipe_tcp != NULL) {
1570 TALLOC_FREE(conn->lsa_pipe_tcp);
1571 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1572 if (conn->cli) {
1573 cli_set_timeout(conn->cli, 500);
1577 if (conn->netlogon_pipe != NULL) {
1578 TALLOC_FREE(conn->netlogon_pipe);
1579 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1580 if (conn->cli) {
1581 cli_set_timeout(conn->cli, 500);
1585 if (conn->cli) {
1586 cli_shutdown(conn->cli);
1589 conn->cli = NULL;
1592 void close_conns_after_fork(void)
1594 struct winbindd_domain *domain;
1596 for (domain = domain_list(); domain; domain = domain->next) {
1597 if (domain->conn.cli == NULL)
1598 continue;
1600 if (domain->conn.cli->fd == -1)
1601 continue;
1603 close(domain->conn.cli->fd);
1604 domain->conn.cli->fd = -1;
1608 static bool connection_ok(struct winbindd_domain *domain)
1610 bool ok;
1612 ok = cli_state_is_connected(domain->conn.cli);
1613 if (!ok) {
1614 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1615 domain->dcname, domain->name));
1616 return False;
1619 if (domain->online == False) {
1620 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1621 return False;
1624 return True;
1627 /* Initialize a new connection up to the RPC BIND.
1628 Bypass online status check so always does network calls. */
1630 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1632 NTSTATUS result;
1634 /* Internal connections never use the network. */
1635 if (domain->internal || !winbindd_can_contact_domain(domain)) {
1636 domain->initialized = True;
1637 return NT_STATUS_OK;
1640 if (connection_ok(domain)) {
1641 if (!domain->initialized) {
1642 set_dc_type_and_flags(domain);
1644 return NT_STATUS_OK;
1647 invalidate_cm_connection(&domain->conn);
1649 result = cm_open_connection(domain, &domain->conn);
1651 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1652 set_dc_type_and_flags(domain);
1655 return result;
1658 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1660 if (domain->initialized && !domain->online) {
1661 /* We check for online status elsewhere. */
1662 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1665 return init_dc_connection_network(domain);
1668 /******************************************************************************
1669 Set the trust flags (direction and forest location) for a domain
1670 ******************************************************************************/
1672 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1674 struct winbindd_domain *our_domain;
1675 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1676 struct netr_DomainTrustList trusts;
1677 int i;
1678 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1679 NETR_TRUST_FLAG_OUTBOUND |
1680 NETR_TRUST_FLAG_INBOUND);
1681 struct rpc_pipe_client *cli;
1682 TALLOC_CTX *mem_ctx = NULL;
1684 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1686 /* Our primary domain doesn't need to worry about trust flags.
1687 Force it to go through the network setup */
1688 if ( domain->primary ) {
1689 return False;
1692 our_domain = find_our_domain();
1694 if ( !connection_ok(our_domain) ) {
1695 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1696 return False;
1699 /* This won't work unless our domain is AD */
1701 if ( !our_domain->active_directory ) {
1702 return False;
1705 /* Use DsEnumerateDomainTrusts to get us the trust direction
1706 and type */
1708 result = cm_connect_netlogon(our_domain, &cli);
1710 if (!NT_STATUS_IS_OK(result)) {
1711 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1712 "a connection to %s for PIPE_NETLOGON (%s)\n",
1713 domain->name, nt_errstr(result)));
1714 return False;
1717 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1718 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1719 return False;
1722 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1723 cli->desthost,
1724 flags,
1725 &trusts,
1726 NULL);
1727 if (!NT_STATUS_IS_OK(result)) {
1728 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1729 "failed to query trusted domain list: %s\n",
1730 nt_errstr(result)));
1731 talloc_destroy(mem_ctx);
1732 return false;
1735 /* Now find the domain name and get the flags */
1737 for ( i=0; i<trusts.count; i++ ) {
1738 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1739 domain->domain_flags = trusts.array[i].trust_flags;
1740 domain->domain_type = trusts.array[i].trust_type;
1741 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1743 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1744 domain->active_directory = True;
1746 /* This flag is only set if the domain is *our*
1747 primary domain and the primary domain is in
1748 native mode */
1750 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1752 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1753 "native mode.\n", domain->name,
1754 domain->native_mode ? "" : "NOT "));
1756 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1757 "running active directory.\n", domain->name,
1758 domain->active_directory ? "" : "NOT "));
1761 domain->initialized = True;
1763 break;
1767 talloc_destroy( mem_ctx );
1769 return domain->initialized;
1772 /******************************************************************************
1773 We can 'sense' certain things about the DC by it's replies to certain
1774 questions.
1776 This tells us if this particular remote server is Active Directory, and if it
1777 is native mode.
1778 ******************************************************************************/
1780 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1782 NTSTATUS result;
1783 WERROR werr;
1784 TALLOC_CTX *mem_ctx = NULL;
1785 struct rpc_pipe_client *cli = NULL;
1786 struct policy_handle pol;
1787 union dssetup_DsRoleInfo info;
1788 union lsa_PolicyInformation *lsa_info = NULL;
1790 if (!connection_ok(domain)) {
1791 return;
1794 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1795 domain->name);
1796 if (!mem_ctx) {
1797 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1798 return;
1801 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1803 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1804 &ndr_table_dssetup.syntax_id,
1805 &cli);
1807 if (!NT_STATUS_IS_OK(result)) {
1808 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1809 "PI_DSSETUP on domain %s: (%s)\n",
1810 domain->name, nt_errstr(result)));
1812 /* if this is just a non-AD domain we need to continue
1813 * identifying so that we can in the end return with
1814 * domain->initialized = True - gd */
1816 goto no_dssetup;
1819 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1820 DS_ROLE_BASIC_INFORMATION,
1821 &info,
1822 &werr);
1823 TALLOC_FREE(cli);
1825 if (!NT_STATUS_IS_OK(result)) {
1826 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1827 "on domain %s failed: (%s)\n",
1828 domain->name, nt_errstr(result)));
1830 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1831 * every opcode on the DSSETUP pipe, continue with
1832 * no_dssetup mode here as well to get domain->initialized
1833 * set - gd */
1835 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1836 goto no_dssetup;
1839 TALLOC_FREE(mem_ctx);
1840 return;
1843 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1844 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1845 domain->native_mode = True;
1846 } else {
1847 domain->native_mode = False;
1850 no_dssetup:
1851 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1852 &ndr_table_lsarpc.syntax_id, &cli);
1854 if (!NT_STATUS_IS_OK(result)) {
1855 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1856 "PI_LSARPC on domain %s: (%s)\n",
1857 domain->name, nt_errstr(result)));
1858 TALLOC_FREE(cli);
1859 TALLOC_FREE(mem_ctx);
1860 return;
1863 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1864 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1866 if (NT_STATUS_IS_OK(result)) {
1867 /* This particular query is exactly what Win2k clients use
1868 to determine that the DC is active directory */
1869 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1870 &pol,
1871 LSA_POLICY_INFO_DNS,
1872 &lsa_info);
1875 if (NT_STATUS_IS_OK(result)) {
1876 domain->active_directory = True;
1878 if (lsa_info->dns.name.string) {
1879 fstrcpy(domain->name, lsa_info->dns.name.string);
1882 if (lsa_info->dns.dns_domain.string) {
1883 fstrcpy(domain->alt_name,
1884 lsa_info->dns.dns_domain.string);
1887 /* See if we can set some domain trust flags about
1888 ourself */
1890 if (lsa_info->dns.dns_forest.string) {
1891 fstrcpy(domain->forest_name,
1892 lsa_info->dns.dns_forest.string);
1894 if (strequal(domain->forest_name, domain->alt_name)) {
1895 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1899 if (lsa_info->dns.sid) {
1900 sid_copy(&domain->sid, lsa_info->dns.sid);
1902 } else {
1903 domain->active_directory = False;
1905 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1906 SEC_FLAG_MAXIMUM_ALLOWED,
1907 &pol);
1909 if (!NT_STATUS_IS_OK(result)) {
1910 goto done;
1913 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1914 &pol,
1915 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1916 &lsa_info);
1918 if (NT_STATUS_IS_OK(result)) {
1920 if (lsa_info->account_domain.name.string) {
1921 fstrcpy(domain->name,
1922 lsa_info->account_domain.name.string);
1925 if (lsa_info->account_domain.sid) {
1926 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1930 done:
1932 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1933 domain->name, domain->native_mode ? "" : "NOT "));
1935 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1936 domain->name, domain->active_directory ? "" : "NOT "));
1938 domain->can_do_ncacn_ip_tcp = domain->active_directory;
1940 TALLOC_FREE(cli);
1942 TALLOC_FREE(mem_ctx);
1944 domain->initialized = True;
1947 /**********************************************************************
1948 Set the domain_flags (trust attributes, domain operating modes, etc...
1949 ***********************************************************************/
1951 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1953 /* we always have to contact our primary domain */
1955 if ( domain->primary ) {
1956 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1957 "primary domain\n"));
1958 set_dc_type_and_flags_connect( domain );
1959 return;
1962 /* Use our DC to get the information if possible */
1964 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1965 /* Otherwise, fallback to contacting the
1966 domain directly */
1967 set_dc_type_and_flags_connect( domain );
1970 return;
1975 /**********************************************************************
1976 ***********************************************************************/
1978 static bool cm_get_schannel_creds(struct winbindd_domain *domain,
1979 struct netlogon_creds_CredentialState **ppdc)
1981 NTSTATUS result;
1982 struct rpc_pipe_client *netlogon_pipe;
1984 if (lp_client_schannel() == False) {
1985 return False;
1988 result = cm_connect_netlogon(domain, &netlogon_pipe);
1989 if (!NT_STATUS_IS_OK(result)) {
1990 return False;
1993 /* Return a pointer to the struct netlogon_creds_CredentialState from the
1994 netlogon pipe. */
1996 if (!domain->conn.netlogon_pipe->dc) {
1997 return false;
2000 *ppdc = domain->conn.netlogon_pipe->dc;
2001 return True;
2004 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2005 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2007 struct winbindd_cm_conn *conn;
2008 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2009 struct netlogon_creds_CredentialState *p_creds;
2010 char *machine_password = NULL;
2011 char *machine_account = NULL;
2012 char *domain_name = NULL;
2014 result = init_dc_connection(domain);
2015 if (!NT_STATUS_IS_OK(result)) {
2016 return result;
2019 conn = &domain->conn;
2021 if (rpccli_is_connected(conn->samr_pipe)) {
2022 goto done;
2027 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2028 * sign and sealed pipe using the machine account password by
2029 * preference. If we can't - try schannel, if that fails, try
2030 * anonymous.
2033 if ((conn->cli->user_name[0] == '\0') ||
2034 (conn->cli->domain[0] == '\0') ||
2035 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2037 result = get_trust_creds(domain, &machine_password,
2038 &machine_account, NULL);
2039 if (!NT_STATUS_IS_OK(result)) {
2040 DEBUG(10, ("cm_connect_sam: No no user available for "
2041 "domain %s, trying schannel\n", conn->cli->domain));
2042 goto schannel;
2044 domain_name = domain->name;
2045 } else {
2046 machine_password = SMB_STRDUP(conn->cli->password);
2047 machine_account = SMB_STRDUP(conn->cli->user_name);
2048 domain_name = conn->cli->domain;
2051 if (!machine_password || !machine_account) {
2052 result = NT_STATUS_NO_MEMORY;
2053 goto done;
2056 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2057 authenticated SAMR pipe with sign & seal. */
2058 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2059 &ndr_table_samr.syntax_id,
2060 NCACN_NP,
2061 DCERPC_AUTH_LEVEL_PRIVACY,
2062 domain_name,
2063 machine_account,
2064 machine_password,
2065 &conn->samr_pipe);
2067 if (!NT_STATUS_IS_OK(result)) {
2068 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2069 "pipe for domain %s using NTLMSSP "
2070 "authenticated pipe: user %s\\%s. Error was "
2071 "%s\n", domain->name, domain_name,
2072 machine_account, nt_errstr(result)));
2073 goto schannel;
2076 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2077 "domain %s using NTLMSSP authenticated "
2078 "pipe: user %s\\%s\n", domain->name,
2079 domain_name, machine_account));
2081 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2082 conn->samr_pipe->desthost,
2083 SEC_FLAG_MAXIMUM_ALLOWED,
2084 &conn->sam_connect_handle);
2085 if (NT_STATUS_IS_OK(result)) {
2086 goto open_domain;
2088 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2089 "failed for domain %s, error was %s. Trying schannel\n",
2090 domain->name, nt_errstr(result) ));
2091 TALLOC_FREE(conn->samr_pipe);
2093 schannel:
2095 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2097 if (!cm_get_schannel_creds(domain, &p_creds)) {
2098 /* If this call fails - conn->cli can now be NULL ! */
2099 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2100 "for domain %s, trying anon\n", domain->name));
2101 goto anonymous;
2103 result = cli_rpc_pipe_open_schannel_with_key
2104 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2105 DCERPC_AUTH_LEVEL_PRIVACY,
2106 domain->name, &p_creds, &conn->samr_pipe);
2108 if (!NT_STATUS_IS_OK(result)) {
2109 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2110 "domain %s using schannel. Error was %s\n",
2111 domain->name, nt_errstr(result) ));
2112 goto anonymous;
2114 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2115 "schannel.\n", domain->name ));
2117 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2118 conn->samr_pipe->desthost,
2119 SEC_FLAG_MAXIMUM_ALLOWED,
2120 &conn->sam_connect_handle);
2121 if (NT_STATUS_IS_OK(result)) {
2122 goto open_domain;
2124 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2125 "for domain %s, error was %s. Trying anonymous\n",
2126 domain->name, nt_errstr(result) ));
2127 TALLOC_FREE(conn->samr_pipe);
2129 anonymous:
2131 /* Finally fall back to anonymous. */
2132 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2133 &conn->samr_pipe);
2135 if (!NT_STATUS_IS_OK(result)) {
2136 goto done;
2139 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2140 conn->samr_pipe->desthost,
2141 SEC_FLAG_MAXIMUM_ALLOWED,
2142 &conn->sam_connect_handle);
2143 if (!NT_STATUS_IS_OK(result)) {
2144 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2145 "for domain %s Error was %s\n",
2146 domain->name, nt_errstr(result) ));
2147 goto done;
2150 open_domain:
2151 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2152 mem_ctx,
2153 &conn->sam_connect_handle,
2154 SEC_FLAG_MAXIMUM_ALLOWED,
2155 &domain->sid,
2156 &conn->sam_domain_handle);
2158 done:
2160 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2162 * if we got access denied, we might just have no access rights
2163 * to talk to the remote samr server server (e.g. when we are a
2164 * PDC and we are connecting a w2k8 pdc via an interdomain
2165 * trust). In that case do not invalidate the whole connection
2166 * stack
2168 TALLOC_FREE(conn->samr_pipe);
2169 ZERO_STRUCT(conn->sam_domain_handle);
2170 return result;
2171 } else if (!NT_STATUS_IS_OK(result)) {
2172 invalidate_cm_connection(conn);
2173 return result;
2176 *cli = conn->samr_pipe;
2177 *sam_handle = conn->sam_domain_handle;
2178 SAFE_FREE(machine_password);
2179 SAFE_FREE(machine_account);
2180 return result;
2183 /**********************************************************************
2184 open an schanneld ncacn_ip_tcp connection to LSA
2185 ***********************************************************************/
2187 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2188 TALLOC_CTX *mem_ctx,
2189 struct rpc_pipe_client **cli)
2191 struct winbindd_cm_conn *conn;
2192 NTSTATUS status;
2194 DEBUG(10,("cm_connect_lsa_tcp\n"));
2196 status = init_dc_connection(domain);
2197 if (!NT_STATUS_IS_OK(status)) {
2198 return status;
2201 conn = &domain->conn;
2203 if (conn->lsa_pipe_tcp &&
2204 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2205 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2206 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2207 goto done;
2210 TALLOC_FREE(conn->lsa_pipe_tcp);
2212 status = cli_rpc_pipe_open_schannel(conn->cli,
2213 &ndr_table_lsarpc.syntax_id,
2214 NCACN_IP_TCP,
2215 DCERPC_AUTH_LEVEL_PRIVACY,
2216 domain->name,
2217 &conn->lsa_pipe_tcp);
2218 if (!NT_STATUS_IS_OK(status)) {
2219 DEBUG(10,("cli_rpc_pipe_open_schannel failed: %s\n",
2220 nt_errstr(status)));
2221 goto done;
2224 done:
2225 if (!NT_STATUS_IS_OK(status)) {
2226 TALLOC_FREE(conn->lsa_pipe_tcp);
2227 return status;
2230 *cli = conn->lsa_pipe_tcp;
2232 return status;
2235 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2236 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2238 struct winbindd_cm_conn *conn;
2239 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2240 struct netlogon_creds_CredentialState *p_creds;
2242 result = init_dc_connection(domain);
2243 if (!NT_STATUS_IS_OK(result))
2244 return result;
2246 conn = &domain->conn;
2248 if (rpccli_is_connected(conn->lsa_pipe)) {
2249 goto done;
2252 if ((conn->cli->user_name[0] == '\0') ||
2253 (conn->cli->domain[0] == '\0') ||
2254 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2255 DEBUG(10, ("cm_connect_lsa: No no user available for "
2256 "domain %s, trying schannel\n", conn->cli->domain));
2257 goto schannel;
2260 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2261 * authenticated LSA pipe with sign & seal. */
2262 result = cli_rpc_pipe_open_spnego_ntlmssp
2263 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2264 DCERPC_AUTH_LEVEL_PRIVACY,
2265 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2266 &conn->lsa_pipe);
2268 if (!NT_STATUS_IS_OK(result)) {
2269 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2270 "domain %s using NTLMSSP authenticated pipe: user "
2271 "%s\\%s. Error was %s. Trying schannel.\n",
2272 domain->name, conn->cli->domain,
2273 conn->cli->user_name, nt_errstr(result)));
2274 goto schannel;
2277 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2278 "NTLMSSP authenticated pipe: user %s\\%s\n",
2279 domain->name, conn->cli->domain, conn->cli->user_name ));
2281 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2282 SEC_FLAG_MAXIMUM_ALLOWED,
2283 &conn->lsa_policy);
2284 if (NT_STATUS_IS_OK(result)) {
2285 goto done;
2288 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2289 "schannel\n"));
2291 TALLOC_FREE(conn->lsa_pipe);
2293 schannel:
2295 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2297 if (!cm_get_schannel_creds(domain, &p_creds)) {
2298 /* If this call fails - conn->cli can now be NULL ! */
2299 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2300 "for domain %s, trying anon\n", domain->name));
2301 goto anonymous;
2303 result = cli_rpc_pipe_open_schannel_with_key
2304 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2305 DCERPC_AUTH_LEVEL_PRIVACY,
2306 domain->name, &p_creds, &conn->lsa_pipe);
2308 if (!NT_STATUS_IS_OK(result)) {
2309 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2310 "domain %s using schannel. Error was %s\n",
2311 domain->name, nt_errstr(result) ));
2312 goto anonymous;
2314 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2315 "schannel.\n", domain->name ));
2317 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2318 SEC_FLAG_MAXIMUM_ALLOWED,
2319 &conn->lsa_policy);
2320 if (NT_STATUS_IS_OK(result)) {
2321 goto done;
2324 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2325 "anonymous\n"));
2327 TALLOC_FREE(conn->lsa_pipe);
2329 anonymous:
2331 result = cli_rpc_pipe_open_noauth(conn->cli,
2332 &ndr_table_lsarpc.syntax_id,
2333 &conn->lsa_pipe);
2334 if (!NT_STATUS_IS_OK(result)) {
2335 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2336 goto done;
2339 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2340 SEC_FLAG_MAXIMUM_ALLOWED,
2341 &conn->lsa_policy);
2342 done:
2343 if (!NT_STATUS_IS_OK(result)) {
2344 invalidate_cm_connection(conn);
2345 return result;
2348 *cli = conn->lsa_pipe;
2349 *lsa_policy = conn->lsa_policy;
2350 return result;
2353 /****************************************************************************
2354 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2355 session key stored in conn->netlogon_pipe->dc->sess_key.
2356 ****************************************************************************/
2358 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2359 struct rpc_pipe_client **cli)
2361 struct winbindd_cm_conn *conn;
2362 NTSTATUS result;
2364 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2365 uint8 mach_pwd[16];
2366 enum netr_SchannelType sec_chan_type;
2367 const char *account_name;
2368 struct rpc_pipe_client *netlogon_pipe = NULL;
2370 *cli = NULL;
2372 result = init_dc_connection(domain);
2373 if (!NT_STATUS_IS_OK(result)) {
2374 return result;
2377 conn = &domain->conn;
2379 if (rpccli_is_connected(conn->netlogon_pipe)) {
2380 *cli = conn->netlogon_pipe;
2381 return NT_STATUS_OK;
2384 result = cli_rpc_pipe_open_noauth(conn->cli,
2385 &ndr_table_netlogon.syntax_id,
2386 &netlogon_pipe);
2387 if (!NT_STATUS_IS_OK(result)) {
2388 return result;
2391 if ((!IS_DC) && (!domain->primary)) {
2392 /* Clear the schannel request bit and drop down */
2393 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2394 goto no_schannel;
2397 if (lp_client_schannel() != False) {
2398 neg_flags |= NETLOGON_NEG_SCHANNEL;
2401 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2402 &sec_chan_type))
2404 TALLOC_FREE(netlogon_pipe);
2405 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2408 result = rpccli_netlogon_setup_creds(
2409 netlogon_pipe,
2410 domain->dcname, /* server name. */
2411 domain->name, /* domain name */
2412 global_myname(), /* client name */
2413 account_name, /* machine account */
2414 mach_pwd, /* machine password */
2415 sec_chan_type, /* from get_trust_pw */
2416 &neg_flags);
2418 if (!NT_STATUS_IS_OK(result)) {
2419 TALLOC_FREE(netlogon_pipe);
2420 return result;
2423 if ((lp_client_schannel() == True) &&
2424 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2425 DEBUG(3, ("Server did not offer schannel\n"));
2426 TALLOC_FREE(netlogon_pipe);
2427 return NT_STATUS_ACCESS_DENIED;
2430 no_schannel:
2431 if ((lp_client_schannel() == False) ||
2432 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2434 * NetSamLogonEx only works for schannel
2436 domain->can_do_samlogon_ex = False;
2438 /* We're done - just keep the existing connection to NETLOGON
2439 * open */
2440 conn->netlogon_pipe = netlogon_pipe;
2441 *cli = conn->netlogon_pipe;
2442 return NT_STATUS_OK;
2445 /* Using the credentials from the first pipe, open a signed and sealed
2446 second netlogon pipe. The session key is stored in the schannel
2447 part of the new pipe auth struct.
2450 result = cli_rpc_pipe_open_schannel_with_key(
2451 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2452 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2453 &conn->netlogon_pipe);
2455 /* We can now close the initial netlogon pipe. */
2456 TALLOC_FREE(netlogon_pipe);
2458 if (!NT_STATUS_IS_OK(result)) {
2459 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2460 "was %s\n", nt_errstr(result)));
2462 /* make sure we return something besides OK */
2463 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2467 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2468 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2469 * supported). We used to only try SamLogonEx for AD, but
2470 * Samba DCs can also do it. And because we don't distinguish
2471 * between Samba and NT4, always try it once.
2473 domain->can_do_samlogon_ex = true;
2475 *cli = conn->netlogon_pipe;
2476 return NT_STATUS_OK;