s3-waf: Add dummy configuration option for sendfile-support
[Samba.git] / source3 / winbindd / winbindd_cm.c
blob64dd69069c4a77853528c793297d40036860b23d
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"
73 #undef DBGC_CLASS
74 #define DBGC_CLASS DBGC_WINBIND
76 struct dc_name_ip {
77 fstring name;
78 struct sockaddr_storage ss;
81 extern struct winbindd_methods reconnect_methods;
82 extern bool override_logfile;
84 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
85 static void set_dc_type_and_flags( struct winbindd_domain *domain );
86 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
87 struct dc_name_ip **dcs, int *num_dcs);
89 /****************************************************************
90 Child failed to find DC's. Reschedule check.
91 ****************************************************************/
93 static void msg_failed_to_go_online(struct messaging_context *msg,
94 void *private_data,
95 uint32_t msg_type,
96 struct server_id server_id,
97 DATA_BLOB *data)
99 struct winbindd_domain *domain;
100 const char *domainname = (const char *)data->data;
102 if (data->data == NULL || data->length == 0) {
103 return;
106 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
108 for (domain = domain_list(); domain; domain = domain->next) {
109 if (domain->internal) {
110 continue;
113 if (strequal(domain->name, domainname)) {
114 if (domain->online) {
115 /* We're already online, ignore. */
116 DEBUG(5,("msg_fail_to_go_online: domain %s "
117 "already online.\n", domainname));
118 continue;
121 /* Reschedule the online check. */
122 set_domain_offline(domain);
123 break;
128 /****************************************************************
129 Actually cause a reconnect from a message.
130 ****************************************************************/
132 static void msg_try_to_go_online(struct messaging_context *msg,
133 void *private_data,
134 uint32_t msg_type,
135 struct server_id server_id,
136 DATA_BLOB *data)
138 struct winbindd_domain *domain;
139 const char *domainname = (const char *)data->data;
141 if (data->data == NULL || data->length == 0) {
142 return;
145 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
147 for (domain = domain_list(); domain; domain = domain->next) {
148 if (domain->internal) {
149 continue;
152 if (strequal(domain->name, domainname)) {
154 if (domain->online) {
155 /* We're already online, ignore. */
156 DEBUG(5,("msg_try_to_go_online: domain %s "
157 "already online.\n", domainname));
158 continue;
161 /* This call takes care of setting the online
162 flag to true if we connected, or re-adding
163 the offline handler if false. Bypasses online
164 check so always does network calls. */
166 init_dc_connection_network(domain);
167 break;
172 /****************************************************************
173 Fork a child to try and contact a DC. Do this as contacting a
174 DC requires blocking lookups and we don't want to block our
175 parent.
176 ****************************************************************/
178 static bool fork_child_dc_connect(struct winbindd_domain *domain)
180 struct dc_name_ip *dcs = NULL;
181 int num_dcs = 0;
182 TALLOC_CTX *mem_ctx = NULL;
183 pid_t parent_pid = sys_getpid();
184 char *lfile = NULL;
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 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
815 strerror(errno)));
816 result = NT_STATUS_UNSUCCESSFUL;
817 goto done;
820 if ((peeraddr_len != sizeof(struct sockaddr_in))
821 #ifdef HAVE_IPV6
822 && (peeraddr_len != sizeof(struct sockaddr_in6))
823 #endif
825 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
826 peeraddr_len));
827 result = NT_STATUS_UNSUCCESSFUL;
828 goto done;
831 if ((peeraddr_in->sin_family != PF_INET)
832 #ifdef HAVE_IPV6
833 && (peeraddr_in->sin_family != PF_INET6)
834 #endif
836 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
837 peeraddr_in->sin_family));
838 result = NT_STATUS_UNSUCCESSFUL;
839 goto done;
842 if (ntohs(peeraddr_in->sin_port) == 139) {
843 struct nmb_name calling;
844 struct nmb_name called;
846 make_nmb_name(&calling, global_myname(), 0x0);
847 make_nmb_name(&called, "*SMBSERVER", 0x20);
849 if (!cli_session_request(*cli, &calling, &called)) {
850 DEBUG(8, ("cli_session_request failed for %s\n",
851 controller));
852 result = NT_STATUS_UNSUCCESSFUL;
853 goto done;
857 result = cli_negprot(*cli);
859 if (!NT_STATUS_IS_OK(result)) {
860 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
861 goto done;
864 if (!is_dc_trusted_domain_situation(domain->name) &&
865 (*cli)->protocol >= PROTOCOL_NT1 &&
866 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
868 ADS_STATUS ads_status;
870 result = get_trust_creds(domain, &machine_password,
871 &machine_account,
872 &machine_krb5_principal);
873 if (!NT_STATUS_IS_OK(result)) {
874 goto anon_fallback;
877 if (lp_security() == SEC_ADS) {
879 /* Try a krb5 session */
881 (*cli)->use_kerberos = True;
882 DEBUG(5, ("connecting to %s from %s with kerberos principal "
883 "[%s] and realm [%s]\n", controller, global_myname(),
884 machine_krb5_principal, domain->alt_name));
886 winbindd_set_locator_kdc_envs(domain);
888 ads_status = cli_session_setup_spnego(*cli,
889 machine_krb5_principal,
890 machine_password,
891 lp_workgroup(),
892 domain->alt_name);
894 if (!ADS_ERR_OK(ads_status)) {
895 DEBUG(4,("failed kerberos session setup with %s\n",
896 ads_errstr(ads_status)));
899 result = ads_ntstatus(ads_status);
900 if (NT_STATUS_IS_OK(result)) {
901 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
902 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
903 if (!NT_STATUS_IS_OK(result)) {
904 goto done;
906 goto session_setup_done;
910 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
911 (*cli)->use_kerberos = False;
913 DEBUG(5, ("connecting to %s from %s with username "
914 "[%s]\\[%s]\n", controller, global_myname(),
915 lp_workgroup(), machine_account));
917 ads_status = cli_session_setup_spnego(*cli,
918 machine_account,
919 machine_password,
920 lp_workgroup(),
921 NULL);
922 if (!ADS_ERR_OK(ads_status)) {
923 DEBUG(4, ("authenticated session setup failed with %s\n",
924 ads_errstr(ads_status)));
927 result = ads_ntstatus(ads_status);
928 if (NT_STATUS_IS_OK(result)) {
929 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
930 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
931 if (!NT_STATUS_IS_OK(result)) {
932 goto done;
934 goto session_setup_done;
938 /* Fall back to non-kerberos session setup with auth_user */
940 (*cli)->use_kerberos = False;
942 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
944 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
945 (strlen(ipc_username) > 0)) {
947 /* Only try authenticated if we have a username */
949 DEBUG(5, ("connecting to %s from %s with username "
950 "[%s]\\[%s]\n", controller, global_myname(),
951 ipc_domain, ipc_username));
953 if (NT_STATUS_IS_OK(cli_session_setup(
954 *cli, ipc_username,
955 ipc_password, strlen(ipc_password)+1,
956 ipc_password, strlen(ipc_password)+1,
957 ipc_domain))) {
958 /* Successful logon with given username. */
959 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
960 if (!NT_STATUS_IS_OK(result)) {
961 goto done;
963 goto session_setup_done;
964 } else {
965 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
966 ipc_domain, ipc_username ));
970 anon_fallback:
972 /* Fall back to anonymous connection, this might fail later */
973 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
974 "connection for DC %s\n",
975 controller ));
977 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
978 NULL, 0, ""))) {
979 DEBUG(5, ("Connected anonymously\n"));
980 result = cli_init_creds(*cli, "", "", "");
981 if (!NT_STATUS_IS_OK(result)) {
982 goto done;
984 goto session_setup_done;
987 result = cli_nt_error(*cli);
989 if (NT_STATUS_IS_OK(result))
990 result = NT_STATUS_UNSUCCESSFUL;
992 /* We can't session setup */
994 goto done;
996 session_setup_done:
998 /* cache the server name for later connections */
1000 saf_store( domain->name, (*cli)->desthost );
1001 if (domain->alt_name && (*cli)->use_kerberos) {
1002 saf_store( domain->alt_name, (*cli)->desthost );
1005 winbindd_set_locator_kdc_envs(domain);
1007 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
1009 if (!NT_STATUS_IS_OK(result)) {
1010 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1011 goto done;
1014 TALLOC_FREE(mutex);
1015 *retry = False;
1017 /* set the domain if empty; needed for schannel connections */
1018 if ( !(*cli)->domain[0] ) {
1019 result = cli_set_domain((*cli), domain->name);
1020 if (!NT_STATUS_IS_OK(result)) {
1021 return result;
1025 result = NT_STATUS_OK;
1027 done:
1028 TALLOC_FREE(mutex);
1029 SAFE_FREE(machine_account);
1030 SAFE_FREE(machine_password);
1031 SAFE_FREE(machine_krb5_principal);
1032 SAFE_FREE(ipc_username);
1033 SAFE_FREE(ipc_domain);
1034 SAFE_FREE(ipc_password);
1036 if (!NT_STATUS_IS_OK(result)) {
1037 winbind_add_failed_connection_entry(domain, controller, result);
1038 if ((*cli) != NULL) {
1039 cli_shutdown(*cli);
1040 *cli = NULL;
1044 return result;
1047 /*******************************************************************
1048 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1049 array.
1051 Keeps the list unique by not adding duplicate entries.
1053 @param[in] mem_ctx talloc memory context to allocate from
1054 @param[in] domain_name domain of the DC
1055 @param[in] dcname name of the DC to add to the list
1056 @param[in] pss Internet address and port pair to add to the list
1057 @param[in,out] dcs array of dc_name_ip structures to add to
1058 @param[in,out] num_dcs number of dcs returned in the dcs array
1059 @return true if the list was added to, false otherwise
1060 *******************************************************************/
1062 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1063 const char *dcname, struct sockaddr_storage *pss,
1064 struct dc_name_ip **dcs, int *num)
1066 int i = 0;
1068 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1069 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1070 return False;
1073 /* Make sure there's no duplicates in the list */
1074 for (i=0; i<*num; i++)
1075 if (sockaddr_equal(
1076 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1077 (struct sockaddr *)(void *)pss))
1078 return False;
1080 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1082 if (*dcs == NULL)
1083 return False;
1085 fstrcpy((*dcs)[*num].name, dcname);
1086 (*dcs)[*num].ss = *pss;
1087 *num += 1;
1088 return True;
1091 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1092 struct sockaddr_storage *pss, uint16 port,
1093 struct sockaddr_storage **addrs, int *num)
1095 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1097 if (*addrs == NULL) {
1098 *num = 0;
1099 return False;
1102 (*addrs)[*num] = *pss;
1103 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1105 *num += 1;
1106 return True;
1109 /*******************************************************************
1110 convert an ip to a name
1111 *******************************************************************/
1113 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1114 const struct winbindd_domain *domain,
1115 struct sockaddr_storage *pss,
1116 fstring name )
1118 struct ip_service ip_list;
1119 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1121 ip_list.ss = *pss;
1122 ip_list.port = 0;
1124 #ifdef WITH_ADS
1125 /* For active directory servers, try to get the ldap server name.
1126 None of these failures should be considered critical for now */
1128 if (lp_security() == SEC_ADS) {
1129 ADS_STRUCT *ads;
1130 ADS_STATUS ads_status;
1131 char addr[INET6_ADDRSTRLEN];
1133 print_sockaddr(addr, sizeof(addr), pss);
1135 ads = ads_init(domain->alt_name, domain->name, addr);
1136 ads->auth.flags |= ADS_AUTH_NO_BIND;
1138 ads_status = ads_connect(ads);
1139 if (ADS_ERR_OK(ads_status)) {
1140 /* We got a cldap packet. */
1141 fstrcpy(name, ads->config.ldap_server_name);
1142 namecache_store(name, 0x20, 1, &ip_list);
1144 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1146 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1147 if (ads_closest_dc(ads)) {
1148 char *sitename = sitename_fetch(ads->config.realm);
1150 /* We're going to use this KDC for this realm/domain.
1151 If we are using sites, then force the krb5 libs
1152 to use this KDC. */
1154 create_local_private_krb5_conf_for_domain(domain->alt_name,
1155 domain->name,
1156 sitename,
1157 pss,
1158 name);
1160 SAFE_FREE(sitename);
1161 } else {
1162 /* use an off site KDC */
1163 create_local_private_krb5_conf_for_domain(domain->alt_name,
1164 domain->name,
1165 NULL,
1166 pss,
1167 name);
1169 winbindd_set_locator_kdc_envs(domain);
1171 /* Ensure we contact this DC also. */
1172 saf_store( domain->name, name);
1173 saf_store( domain->alt_name, name);
1176 ads_destroy( &ads );
1177 return True;
1180 ads_destroy( &ads );
1182 #endif
1184 /* try GETDC requests next */
1186 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1187 pss, domain->name, &domain->sid,
1188 nt_version)) {
1189 const char *dc_name = NULL;
1190 int i;
1191 smb_msleep(100);
1192 for (i=0; i<5; i++) {
1193 if (receive_getdc_response(mem_ctx, pss, domain->name,
1194 &nt_version,
1195 &dc_name, NULL)) {
1196 fstrcpy(name, dc_name);
1197 namecache_store(name, 0x20, 1, &ip_list);
1198 return True;
1200 smb_msleep(500);
1204 /* try node status request */
1206 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1207 namecache_store(name, 0x20, 1, &ip_list);
1208 return True;
1210 return False;
1213 /*******************************************************************
1214 Retrieve a list of IP addresses for domain controllers.
1216 The array is sorted in the preferred connection order.
1218 @param[in] mem_ctx talloc memory context to allocate from
1219 @param[in] domain domain to retrieve DCs for
1220 @param[out] dcs array of dcs that will be returned
1221 @param[out] num_dcs number of dcs returned in the dcs array
1222 @return always true
1223 *******************************************************************/
1225 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1226 struct dc_name_ip **dcs, int *num_dcs)
1228 fstring dcname;
1229 struct sockaddr_storage ss;
1230 struct ip_service *ip_list = NULL;
1231 int iplist_size = 0;
1232 int i;
1233 bool is_our_domain;
1234 enum security_types sec = (enum security_types)lp_security();
1236 is_our_domain = strequal(domain->name, lp_workgroup());
1238 /* If not our domain, get the preferred DC, by asking our primary DC */
1239 if ( !is_our_domain
1240 && get_dc_name_via_netlogon(domain, dcname, &ss)
1241 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1242 num_dcs) )
1244 char addr[INET6_ADDRSTRLEN];
1245 print_sockaddr(addr, sizeof(addr), &ss);
1246 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1247 dcname, addr));
1248 return True;
1251 if (sec == SEC_ADS) {
1252 char *sitename = NULL;
1254 /* We need to make sure we know the local site before
1255 doing any DNS queries, as this will restrict the
1256 get_sorted_dc_list() call below to only fetching
1257 DNS records for the correct site. */
1259 /* Find any DC to get the site record.
1260 We deliberately don't care about the
1261 return here. */
1263 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1265 sitename = sitename_fetch(domain->alt_name);
1266 if (sitename) {
1268 /* Do the site-specific AD dns lookup first. */
1269 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1270 &iplist_size, True);
1272 /* Add ips to the DC array. We don't look up the name
1273 of the DC in this function, but we fill in the char*
1274 of the ip now to make the failed connection cache
1275 work */
1276 for ( i=0; i<iplist_size; i++ ) {
1277 char addr[INET6_ADDRSTRLEN];
1278 print_sockaddr(addr, sizeof(addr),
1279 &ip_list[i].ss);
1280 add_one_dc_unique(mem_ctx,
1281 domain->name,
1282 addr,
1283 &ip_list[i].ss,
1284 dcs,
1285 num_dcs);
1288 SAFE_FREE(ip_list);
1289 SAFE_FREE(sitename);
1290 iplist_size = 0;
1293 /* Now we add DCs from the main AD DNS lookup. */
1294 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1295 &iplist_size, True);
1297 for ( i=0; i<iplist_size; i++ ) {
1298 char addr[INET6_ADDRSTRLEN];
1299 print_sockaddr(addr, sizeof(addr),
1300 &ip_list[i].ss);
1301 add_one_dc_unique(mem_ctx,
1302 domain->name,
1303 addr,
1304 &ip_list[i].ss,
1305 dcs,
1306 num_dcs);
1309 SAFE_FREE(ip_list);
1310 iplist_size = 0;
1313 /* Try standard netbios queries if no ADS */
1314 if (*num_dcs == 0) {
1315 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1316 False);
1318 for ( i=0; i<iplist_size; i++ ) {
1319 char addr[INET6_ADDRSTRLEN];
1320 print_sockaddr(addr, sizeof(addr),
1321 &ip_list[i].ss);
1322 add_one_dc_unique(mem_ctx,
1323 domain->name,
1324 addr,
1325 &ip_list[i].ss,
1326 dcs,
1327 num_dcs);
1330 SAFE_FREE(ip_list);
1331 iplist_size = 0;
1334 return True;
1337 /*******************************************************************
1338 Find and make a connection to a DC in the given domain.
1340 @param[in] mem_ctx talloc memory context to allocate from
1341 @param[in] domain domain to find a dc in
1342 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1343 @param[out] pss DC Internet address and port
1344 @param[out] fd fd of the open socket connected to the newly found dc
1345 @return true when a DC connection is made, false otherwise
1346 *******************************************************************/
1348 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1349 struct winbindd_domain *domain,
1350 fstring dcname, struct sockaddr_storage *pss, int *fd)
1352 struct dc_name_ip *dcs = NULL;
1353 int num_dcs = 0;
1355 const char **dcnames = NULL;
1356 int num_dcnames = 0;
1358 struct sockaddr_storage *addrs = NULL;
1359 int num_addrs = 0;
1361 int i, fd_index;
1363 *fd = -1;
1365 again:
1366 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1367 return False;
1369 for (i=0; i<num_dcs; i++) {
1371 if (!add_string_to_array(mem_ctx, dcs[i].name,
1372 &dcnames, &num_dcnames)) {
1373 return False;
1375 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1376 &addrs, &num_addrs)) {
1377 return False;
1380 if (!add_string_to_array(mem_ctx, dcs[i].name,
1381 &dcnames, &num_dcnames)) {
1382 return False;
1384 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1385 &addrs, &num_addrs)) {
1386 return False;
1390 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1391 return False;
1393 if ((addrs == NULL) || (dcnames == NULL))
1394 return False;
1396 /* 5 second timeout. */
1397 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1398 for (i=0; i<num_dcs; i++) {
1399 char ab[INET6_ADDRSTRLEN];
1400 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1401 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1402 "domain %s address %s. Error was %s\n",
1403 domain->name, ab, strerror(errno) ));
1404 winbind_add_failed_connection_entry(domain,
1405 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1407 return False;
1410 *pss = addrs[fd_index];
1412 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1413 /* Ok, we've got a name for the DC */
1414 fstrcpy(dcname, dcnames[fd_index]);
1415 return True;
1418 /* Try to figure out the name */
1419 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1420 return True;
1423 /* We can not continue without the DC's name */
1424 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1425 NT_STATUS_UNSUCCESSFUL);
1427 /* Throw away all arrays as we're doing this again. */
1428 TALLOC_FREE(dcs);
1429 num_dcs = 0;
1431 TALLOC_FREE(dcnames);
1432 num_dcnames = 0;
1434 TALLOC_FREE(addrs);
1435 num_addrs = 0;
1437 close(*fd);
1438 *fd = -1;
1440 goto again;
1443 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1444 struct winbindd_cm_conn *new_conn)
1446 TALLOC_CTX *mem_ctx;
1447 NTSTATUS result;
1448 char *saf_servername = saf_fetch( domain->name );
1449 int retries;
1451 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1452 SAFE_FREE(saf_servername);
1453 set_domain_offline(domain);
1454 return NT_STATUS_NO_MEMORY;
1457 /* we have to check the server affinity cache here since
1458 later we selecte a DC based on response time and not preference */
1460 /* Check the negative connection cache
1461 before talking to it. It going down may have
1462 triggered the reconnection. */
1464 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1466 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1467 saf_servername, domain->name ));
1469 /* convert an ip address to a name */
1470 if (is_ipaddress( saf_servername ) ) {
1471 fstring saf_name;
1472 struct sockaddr_storage ss;
1474 if (!interpret_string_addr(&ss, saf_servername,
1475 AI_NUMERICHOST)) {
1476 return NT_STATUS_UNSUCCESSFUL;
1478 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1479 fstrcpy( domain->dcname, saf_name );
1480 } else {
1481 winbind_add_failed_connection_entry(
1482 domain, saf_servername,
1483 NT_STATUS_UNSUCCESSFUL);
1485 } else {
1486 fstrcpy( domain->dcname, saf_servername );
1489 SAFE_FREE( saf_servername );
1492 for (retries = 0; retries < 3; retries++) {
1493 int fd = -1;
1494 bool retry = False;
1496 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1498 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1499 domain->dcname, domain->name ));
1501 if (*domain->dcname
1502 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1503 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1505 struct sockaddr_storage *addrs = NULL;
1506 int num_addrs = 0;
1507 int dummy = 0;
1509 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1510 set_domain_offline(domain);
1511 talloc_destroy(mem_ctx);
1512 return NT_STATUS_NO_MEMORY;
1514 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1515 set_domain_offline(domain);
1516 talloc_destroy(mem_ctx);
1517 return NT_STATUS_NO_MEMORY;
1520 /* 5 second timeout. */
1521 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1522 fd = -1;
1526 if ((fd == -1)
1527 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1529 /* This is the one place where we will
1530 set the global winbindd offline state
1531 to true, if a "WINBINDD_OFFLINE" entry
1532 is found in the winbindd cache. */
1533 set_global_winbindd_state_offline();
1534 break;
1537 new_conn->cli = NULL;
1539 result = cm_prepare_connection(domain, fd, domain->dcname,
1540 &new_conn->cli, &retry);
1542 if (!retry)
1543 break;
1546 if (NT_STATUS_IS_OK(result)) {
1548 winbindd_set_locator_kdc_envs(domain);
1550 if (domain->online == False) {
1551 /* We're changing state from offline to online. */
1552 set_global_winbindd_state_online();
1554 set_domain_online(domain);
1555 } else {
1556 /* Ensure we setup the retry handler. */
1557 set_domain_offline(domain);
1560 talloc_destroy(mem_ctx);
1561 return result;
1564 /* Close down all open pipes on a connection. */
1566 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1568 /* We're closing down a possibly dead
1569 connection. Don't have impossibly long (10s) timeouts. */
1571 if (conn->cli) {
1572 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1575 if (conn->samr_pipe != NULL) {
1576 TALLOC_FREE(conn->samr_pipe);
1577 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1578 if (conn->cli) {
1579 cli_set_timeout(conn->cli, 500);
1583 if (conn->lsa_pipe != NULL) {
1584 TALLOC_FREE(conn->lsa_pipe);
1585 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1586 if (conn->cli) {
1587 cli_set_timeout(conn->cli, 500);
1591 if (conn->lsa_pipe_tcp != NULL) {
1592 TALLOC_FREE(conn->lsa_pipe_tcp);
1593 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1594 if (conn->cli) {
1595 cli_set_timeout(conn->cli, 500);
1599 if (conn->netlogon_pipe != NULL) {
1600 TALLOC_FREE(conn->netlogon_pipe);
1601 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1602 if (conn->cli) {
1603 cli_set_timeout(conn->cli, 500);
1607 if (conn->cli) {
1608 cli_shutdown(conn->cli);
1611 conn->cli = NULL;
1614 void close_conns_after_fork(void)
1616 struct winbindd_domain *domain;
1618 for (domain = domain_list(); domain; domain = domain->next) {
1619 struct cli_state *cli = domain->conn.cli;
1622 * first close the low level SMB TCP connection
1623 * so that we don't generate any SMBclose
1624 * requests in invalidate_cm_connection()
1626 if (cli && cli->fd != -1) {
1627 close(domain->conn.cli->fd);
1628 domain->conn.cli->fd = -1;
1631 invalidate_cm_connection(&domain->conn);
1635 static bool connection_ok(struct winbindd_domain *domain)
1637 bool ok;
1639 ok = cli_state_is_connected(domain->conn.cli);
1640 if (!ok) {
1641 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1642 domain->dcname, domain->name));
1643 return False;
1646 if (domain->online == False) {
1647 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1648 return False;
1651 return True;
1654 /* Initialize a new connection up to the RPC BIND.
1655 Bypass online status check so always does network calls. */
1657 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1659 NTSTATUS result;
1661 /* Internal connections never use the network. */
1662 if (domain->internal) {
1663 domain->initialized = True;
1664 return NT_STATUS_OK;
1667 if (!winbindd_can_contact_domain(domain)) {
1668 invalidate_cm_connection(&domain->conn);
1669 domain->initialized = True;
1670 return NT_STATUS_OK;
1673 if (connection_ok(domain)) {
1674 if (!domain->initialized) {
1675 set_dc_type_and_flags(domain);
1677 return NT_STATUS_OK;
1680 invalidate_cm_connection(&domain->conn);
1682 result = cm_open_connection(domain, &domain->conn);
1684 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1685 set_dc_type_and_flags(domain);
1688 return result;
1691 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1693 if (domain->internal) {
1694 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1697 if (domain->initialized && !domain->online) {
1698 /* We check for online status elsewhere. */
1699 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1702 return init_dc_connection_network(domain);
1705 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1707 NTSTATUS status;
1709 status = init_dc_connection(domain);
1710 if (!NT_STATUS_IS_OK(status)) {
1711 return status;
1714 if (!domain->internal && domain->conn.cli == NULL) {
1715 /* happens for trusted domains without inbound trust */
1716 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1719 return NT_STATUS_OK;
1722 /******************************************************************************
1723 Set the trust flags (direction and forest location) for a domain
1724 ******************************************************************************/
1726 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1728 struct winbindd_domain *our_domain;
1729 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1730 struct netr_DomainTrustList trusts;
1731 int i;
1732 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1733 NETR_TRUST_FLAG_OUTBOUND |
1734 NETR_TRUST_FLAG_INBOUND);
1735 struct rpc_pipe_client *cli;
1736 TALLOC_CTX *mem_ctx = NULL;
1738 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1740 /* Our primary domain doesn't need to worry about trust flags.
1741 Force it to go through the network setup */
1742 if ( domain->primary ) {
1743 return False;
1746 our_domain = find_our_domain();
1748 if ( !connection_ok(our_domain) ) {
1749 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1750 return False;
1753 /* This won't work unless our domain is AD */
1755 if ( !our_domain->active_directory ) {
1756 return False;
1759 /* Use DsEnumerateDomainTrusts to get us the trust direction
1760 and type */
1762 result = cm_connect_netlogon(our_domain, &cli);
1764 if (!NT_STATUS_IS_OK(result)) {
1765 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1766 "a connection to %s for PIPE_NETLOGON (%s)\n",
1767 domain->name, nt_errstr(result)));
1768 return False;
1771 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1772 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1773 return False;
1776 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1777 cli->desthost,
1778 flags,
1779 &trusts,
1780 NULL);
1781 if (!NT_STATUS_IS_OK(result)) {
1782 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1783 "failed to query trusted domain list: %s\n",
1784 nt_errstr(result)));
1785 talloc_destroy(mem_ctx);
1786 return false;
1789 /* Now find the domain name and get the flags */
1791 for ( i=0; i<trusts.count; i++ ) {
1792 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1793 domain->domain_flags = trusts.array[i].trust_flags;
1794 domain->domain_type = trusts.array[i].trust_type;
1795 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1797 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1798 domain->active_directory = True;
1800 /* This flag is only set if the domain is *our*
1801 primary domain and the primary domain is in
1802 native mode */
1804 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1806 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1807 "native mode.\n", domain->name,
1808 domain->native_mode ? "" : "NOT "));
1810 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1811 "running active directory.\n", domain->name,
1812 domain->active_directory ? "" : "NOT "));
1815 domain->initialized = True;
1817 break;
1821 talloc_destroy( mem_ctx );
1823 return domain->initialized;
1826 /******************************************************************************
1827 We can 'sense' certain things about the DC by it's replies to certain
1828 questions.
1830 This tells us if this particular remote server is Active Directory, and if it
1831 is native mode.
1832 ******************************************************************************/
1834 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1836 NTSTATUS result;
1837 WERROR werr;
1838 TALLOC_CTX *mem_ctx = NULL;
1839 struct rpc_pipe_client *cli = NULL;
1840 struct policy_handle pol;
1841 union dssetup_DsRoleInfo info;
1842 union lsa_PolicyInformation *lsa_info = NULL;
1844 if (!connection_ok(domain)) {
1845 return;
1848 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1849 domain->name);
1850 if (!mem_ctx) {
1851 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1852 return;
1855 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1857 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1858 &ndr_table_dssetup.syntax_id,
1859 &cli);
1861 if (!NT_STATUS_IS_OK(result)) {
1862 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1863 "PI_DSSETUP on domain %s: (%s)\n",
1864 domain->name, nt_errstr(result)));
1866 /* if this is just a non-AD domain we need to continue
1867 * identifying so that we can in the end return with
1868 * domain->initialized = True - gd */
1870 goto no_dssetup;
1873 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1874 DS_ROLE_BASIC_INFORMATION,
1875 &info,
1876 &werr);
1877 TALLOC_FREE(cli);
1879 if (!NT_STATUS_IS_OK(result)) {
1880 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1881 "on domain %s failed: (%s)\n",
1882 domain->name, nt_errstr(result)));
1884 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1885 * every opcode on the DSSETUP pipe, continue with
1886 * no_dssetup mode here as well to get domain->initialized
1887 * set - gd */
1889 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1890 goto no_dssetup;
1893 TALLOC_FREE(mem_ctx);
1894 return;
1897 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1898 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1899 domain->native_mode = True;
1900 } else {
1901 domain->native_mode = False;
1904 no_dssetup:
1905 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1906 &ndr_table_lsarpc.syntax_id, &cli);
1908 if (!NT_STATUS_IS_OK(result)) {
1909 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1910 "PI_LSARPC on domain %s: (%s)\n",
1911 domain->name, nt_errstr(result)));
1912 TALLOC_FREE(cli);
1913 TALLOC_FREE(mem_ctx);
1914 return;
1917 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1918 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1920 if (NT_STATUS_IS_OK(result)) {
1921 /* This particular query is exactly what Win2k clients use
1922 to determine that the DC is active directory */
1923 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1924 &pol,
1925 LSA_POLICY_INFO_DNS,
1926 &lsa_info);
1929 if (NT_STATUS_IS_OK(result)) {
1930 domain->active_directory = True;
1932 if (lsa_info->dns.name.string) {
1933 fstrcpy(domain->name, lsa_info->dns.name.string);
1936 if (lsa_info->dns.dns_domain.string) {
1937 fstrcpy(domain->alt_name,
1938 lsa_info->dns.dns_domain.string);
1941 /* See if we can set some domain trust flags about
1942 ourself */
1944 if (lsa_info->dns.dns_forest.string) {
1945 fstrcpy(domain->forest_name,
1946 lsa_info->dns.dns_forest.string);
1948 if (strequal(domain->forest_name, domain->alt_name)) {
1949 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1953 if (lsa_info->dns.sid) {
1954 sid_copy(&domain->sid, lsa_info->dns.sid);
1956 } else {
1957 domain->active_directory = False;
1959 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1960 SEC_FLAG_MAXIMUM_ALLOWED,
1961 &pol);
1963 if (!NT_STATUS_IS_OK(result)) {
1964 goto done;
1967 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1968 &pol,
1969 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1970 &lsa_info);
1972 if (NT_STATUS_IS_OK(result)) {
1974 if (lsa_info->account_domain.name.string) {
1975 fstrcpy(domain->name,
1976 lsa_info->account_domain.name.string);
1979 if (lsa_info->account_domain.sid) {
1980 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1984 done:
1986 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1987 domain->name, domain->native_mode ? "" : "NOT "));
1989 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1990 domain->name, domain->active_directory ? "" : "NOT "));
1992 domain->can_do_ncacn_ip_tcp = domain->active_directory;
1994 TALLOC_FREE(cli);
1996 TALLOC_FREE(mem_ctx);
1998 domain->initialized = True;
2001 /**********************************************************************
2002 Set the domain_flags (trust attributes, domain operating modes, etc...
2003 ***********************************************************************/
2005 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2007 /* we always have to contact our primary domain */
2009 if ( domain->primary ) {
2010 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2011 "primary domain\n"));
2012 set_dc_type_and_flags_connect( domain );
2013 return;
2016 /* Use our DC to get the information if possible */
2018 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2019 /* Otherwise, fallback to contacting the
2020 domain directly */
2021 set_dc_type_and_flags_connect( domain );
2024 return;
2029 /**********************************************************************
2030 ***********************************************************************/
2032 static bool cm_get_schannel_creds(struct winbindd_domain *domain,
2033 struct netlogon_creds_CredentialState **ppdc)
2035 NTSTATUS result;
2036 struct rpc_pipe_client *netlogon_pipe;
2038 if (lp_client_schannel() == False) {
2039 return False;
2042 result = cm_connect_netlogon(domain, &netlogon_pipe);
2043 if (!NT_STATUS_IS_OK(result)) {
2044 return False;
2047 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2048 netlogon pipe. */
2050 if (!domain->conn.netlogon_pipe->dc) {
2051 return false;
2054 *ppdc = domain->conn.netlogon_pipe->dc;
2055 return True;
2058 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2059 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2061 struct winbindd_cm_conn *conn;
2062 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2063 struct netlogon_creds_CredentialState *p_creds;
2064 char *machine_password = NULL;
2065 char *machine_account = NULL;
2066 char *domain_name = NULL;
2068 result = init_dc_connection_rpc(domain);
2069 if (!NT_STATUS_IS_OK(result)) {
2070 return result;
2073 conn = &domain->conn;
2075 if (rpccli_is_connected(conn->samr_pipe)) {
2076 goto done;
2079 TALLOC_FREE(conn->samr_pipe);
2082 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2083 * sign and sealed pipe using the machine account password by
2084 * preference. If we can't - try schannel, if that fails, try
2085 * anonymous.
2088 if ((conn->cli->user_name[0] == '\0') ||
2089 (conn->cli->domain[0] == '\0') ||
2090 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2092 result = get_trust_creds(domain, &machine_password,
2093 &machine_account, NULL);
2094 if (!NT_STATUS_IS_OK(result)) {
2095 DEBUG(10, ("cm_connect_sam: No no user available for "
2096 "domain %s, trying schannel\n", conn->cli->domain));
2097 goto schannel;
2099 domain_name = domain->name;
2100 } else {
2101 machine_password = SMB_STRDUP(conn->cli->password);
2102 machine_account = SMB_STRDUP(conn->cli->user_name);
2103 domain_name = conn->cli->domain;
2106 if (!machine_password || !machine_account) {
2107 result = NT_STATUS_NO_MEMORY;
2108 goto done;
2111 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2112 authenticated SAMR pipe with sign & seal. */
2113 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2114 &ndr_table_samr.syntax_id,
2115 NCACN_NP,
2116 DCERPC_AUTH_LEVEL_PRIVACY,
2117 domain_name,
2118 machine_account,
2119 machine_password,
2120 &conn->samr_pipe);
2122 if (!NT_STATUS_IS_OK(result)) {
2123 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2124 "pipe for domain %s using NTLMSSP "
2125 "authenticated pipe: user %s\\%s. Error was "
2126 "%s\n", domain->name, domain_name,
2127 machine_account, nt_errstr(result)));
2128 goto schannel;
2131 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2132 "domain %s using NTLMSSP authenticated "
2133 "pipe: user %s\\%s\n", domain->name,
2134 domain_name, machine_account));
2136 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2137 conn->samr_pipe->desthost,
2138 SEC_FLAG_MAXIMUM_ALLOWED,
2139 &conn->sam_connect_handle);
2140 if (NT_STATUS_IS_OK(result)) {
2141 goto open_domain;
2143 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2144 "failed for domain %s, error was %s. Trying schannel\n",
2145 domain->name, nt_errstr(result) ));
2146 TALLOC_FREE(conn->samr_pipe);
2148 schannel:
2150 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2152 if (!cm_get_schannel_creds(domain, &p_creds)) {
2153 /* If this call fails - conn->cli can now be NULL ! */
2154 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2155 "for domain %s, trying anon\n", domain->name));
2156 goto anonymous;
2158 result = cli_rpc_pipe_open_schannel_with_key
2159 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2160 DCERPC_AUTH_LEVEL_PRIVACY,
2161 domain->name, &p_creds, &conn->samr_pipe);
2163 if (!NT_STATUS_IS_OK(result)) {
2164 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2165 "domain %s using schannel. Error was %s\n",
2166 domain->name, nt_errstr(result) ));
2167 goto anonymous;
2169 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2170 "schannel.\n", domain->name ));
2172 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2173 conn->samr_pipe->desthost,
2174 SEC_FLAG_MAXIMUM_ALLOWED,
2175 &conn->sam_connect_handle);
2176 if (NT_STATUS_IS_OK(result)) {
2177 goto open_domain;
2179 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2180 "for domain %s, error was %s. Trying anonymous\n",
2181 domain->name, nt_errstr(result) ));
2182 TALLOC_FREE(conn->samr_pipe);
2184 anonymous:
2186 /* Finally fall back to anonymous. */
2187 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2188 &conn->samr_pipe);
2190 if (!NT_STATUS_IS_OK(result)) {
2191 goto done;
2194 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2195 conn->samr_pipe->desthost,
2196 SEC_FLAG_MAXIMUM_ALLOWED,
2197 &conn->sam_connect_handle);
2198 if (!NT_STATUS_IS_OK(result)) {
2199 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2200 "for domain %s Error was %s\n",
2201 domain->name, nt_errstr(result) ));
2202 goto done;
2205 open_domain:
2206 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2207 mem_ctx,
2208 &conn->sam_connect_handle,
2209 SEC_FLAG_MAXIMUM_ALLOWED,
2210 &domain->sid,
2211 &conn->sam_domain_handle);
2213 done:
2215 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2217 * if we got access denied, we might just have no access rights
2218 * to talk to the remote samr server server (e.g. when we are a
2219 * PDC and we are connecting a w2k8 pdc via an interdomain
2220 * trust). In that case do not invalidate the whole connection
2221 * stack
2223 TALLOC_FREE(conn->samr_pipe);
2224 ZERO_STRUCT(conn->sam_domain_handle);
2225 return result;
2226 } else if (!NT_STATUS_IS_OK(result)) {
2227 invalidate_cm_connection(conn);
2228 return result;
2231 *cli = conn->samr_pipe;
2232 *sam_handle = conn->sam_domain_handle;
2233 SAFE_FREE(machine_password);
2234 SAFE_FREE(machine_account);
2235 return result;
2238 /**********************************************************************
2239 open an schanneld ncacn_ip_tcp connection to LSA
2240 ***********************************************************************/
2242 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2243 TALLOC_CTX *mem_ctx,
2244 struct rpc_pipe_client **cli)
2246 struct winbindd_cm_conn *conn;
2247 NTSTATUS status;
2249 DEBUG(10,("cm_connect_lsa_tcp\n"));
2251 status = init_dc_connection_rpc(domain);
2252 if (!NT_STATUS_IS_OK(status)) {
2253 return status;
2256 conn = &domain->conn;
2258 if (conn->lsa_pipe_tcp &&
2259 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2260 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2261 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2262 goto done;
2265 TALLOC_FREE(conn->lsa_pipe_tcp);
2267 status = cli_rpc_pipe_open_schannel(conn->cli,
2268 &ndr_table_lsarpc.syntax_id,
2269 NCACN_IP_TCP,
2270 DCERPC_AUTH_LEVEL_PRIVACY,
2271 domain->name,
2272 &conn->lsa_pipe_tcp);
2273 if (!NT_STATUS_IS_OK(status)) {
2274 DEBUG(10,("cli_rpc_pipe_open_schannel failed: %s\n",
2275 nt_errstr(status)));
2276 goto done;
2279 done:
2280 if (!NT_STATUS_IS_OK(status)) {
2281 TALLOC_FREE(conn->lsa_pipe_tcp);
2282 return status;
2285 *cli = conn->lsa_pipe_tcp;
2287 return status;
2290 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2291 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2293 struct winbindd_cm_conn *conn;
2294 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2295 struct netlogon_creds_CredentialState *p_creds;
2297 result = init_dc_connection_rpc(domain);
2298 if (!NT_STATUS_IS_OK(result))
2299 return result;
2301 conn = &domain->conn;
2303 if (rpccli_is_connected(conn->lsa_pipe)) {
2304 goto done;
2307 TALLOC_FREE(conn->lsa_pipe);
2309 if ((conn->cli->user_name[0] == '\0') ||
2310 (conn->cli->domain[0] == '\0') ||
2311 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2312 DEBUG(10, ("cm_connect_lsa: No no user available for "
2313 "domain %s, trying schannel\n", conn->cli->domain));
2314 goto schannel;
2317 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2318 * authenticated LSA pipe with sign & seal. */
2319 result = cli_rpc_pipe_open_spnego_ntlmssp
2320 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2321 DCERPC_AUTH_LEVEL_PRIVACY,
2322 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2323 &conn->lsa_pipe);
2325 if (!NT_STATUS_IS_OK(result)) {
2326 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2327 "domain %s using NTLMSSP authenticated pipe: user "
2328 "%s\\%s. Error was %s. Trying schannel.\n",
2329 domain->name, conn->cli->domain,
2330 conn->cli->user_name, nt_errstr(result)));
2331 goto schannel;
2334 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2335 "NTLMSSP authenticated pipe: user %s\\%s\n",
2336 domain->name, conn->cli->domain, conn->cli->user_name ));
2338 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2339 SEC_FLAG_MAXIMUM_ALLOWED,
2340 &conn->lsa_policy);
2341 if (NT_STATUS_IS_OK(result)) {
2342 goto done;
2345 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2346 "schannel\n"));
2348 TALLOC_FREE(conn->lsa_pipe);
2350 schannel:
2352 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2354 if (!cm_get_schannel_creds(domain, &p_creds)) {
2355 /* If this call fails - conn->cli can now be NULL ! */
2356 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2357 "for domain %s, trying anon\n", domain->name));
2358 goto anonymous;
2360 result = cli_rpc_pipe_open_schannel_with_key
2361 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2362 DCERPC_AUTH_LEVEL_PRIVACY,
2363 domain->name, &p_creds, &conn->lsa_pipe);
2365 if (!NT_STATUS_IS_OK(result)) {
2366 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2367 "domain %s using schannel. Error was %s\n",
2368 domain->name, nt_errstr(result) ));
2369 goto anonymous;
2371 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2372 "schannel.\n", domain->name ));
2374 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2375 SEC_FLAG_MAXIMUM_ALLOWED,
2376 &conn->lsa_policy);
2377 if (NT_STATUS_IS_OK(result)) {
2378 goto done;
2381 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2382 "anonymous\n"));
2384 TALLOC_FREE(conn->lsa_pipe);
2386 anonymous:
2388 result = cli_rpc_pipe_open_noauth(conn->cli,
2389 &ndr_table_lsarpc.syntax_id,
2390 &conn->lsa_pipe);
2391 if (!NT_STATUS_IS_OK(result)) {
2392 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2393 goto done;
2396 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2397 SEC_FLAG_MAXIMUM_ALLOWED,
2398 &conn->lsa_policy);
2399 done:
2400 if (!NT_STATUS_IS_OK(result)) {
2401 invalidate_cm_connection(conn);
2402 return result;
2405 *cli = conn->lsa_pipe;
2406 *lsa_policy = conn->lsa_policy;
2407 return result;
2410 /****************************************************************************
2411 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2412 session key stored in conn->netlogon_pipe->dc->sess_key.
2413 ****************************************************************************/
2415 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2416 struct rpc_pipe_client **cli)
2418 struct winbindd_cm_conn *conn;
2419 NTSTATUS result;
2421 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2422 uint8 mach_pwd[16];
2423 enum netr_SchannelType sec_chan_type;
2424 const char *account_name;
2425 struct rpc_pipe_client *netlogon_pipe = NULL;
2427 *cli = NULL;
2429 result = init_dc_connection_rpc(domain);
2430 if (!NT_STATUS_IS_OK(result)) {
2431 return result;
2434 conn = &domain->conn;
2436 if (rpccli_is_connected(conn->netlogon_pipe)) {
2437 *cli = conn->netlogon_pipe;
2438 return NT_STATUS_OK;
2441 TALLOC_FREE(conn->netlogon_pipe);
2443 result = cli_rpc_pipe_open_noauth(conn->cli,
2444 &ndr_table_netlogon.syntax_id,
2445 &netlogon_pipe);
2446 if (!NT_STATUS_IS_OK(result)) {
2447 return result;
2450 if ((!IS_DC) && (!domain->primary)) {
2451 /* Clear the schannel request bit and drop down */
2452 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2453 goto no_schannel;
2456 if (lp_client_schannel() != False) {
2457 neg_flags |= NETLOGON_NEG_SCHANNEL;
2460 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2461 &sec_chan_type))
2463 TALLOC_FREE(netlogon_pipe);
2464 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2467 result = rpccli_netlogon_setup_creds(
2468 netlogon_pipe,
2469 domain->dcname, /* server name. */
2470 domain->name, /* domain name */
2471 global_myname(), /* client name */
2472 account_name, /* machine account */
2473 mach_pwd, /* machine password */
2474 sec_chan_type, /* from get_trust_pw */
2475 &neg_flags);
2477 if (!NT_STATUS_IS_OK(result)) {
2478 TALLOC_FREE(netlogon_pipe);
2479 return result;
2482 if ((lp_client_schannel() == True) &&
2483 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2484 DEBUG(3, ("Server did not offer schannel\n"));
2485 TALLOC_FREE(netlogon_pipe);
2486 return NT_STATUS_ACCESS_DENIED;
2489 no_schannel:
2490 if ((lp_client_schannel() == False) ||
2491 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2493 * NetSamLogonEx only works for schannel
2495 domain->can_do_samlogon_ex = False;
2497 /* We're done - just keep the existing connection to NETLOGON
2498 * open */
2499 conn->netlogon_pipe = netlogon_pipe;
2500 *cli = conn->netlogon_pipe;
2501 return NT_STATUS_OK;
2504 /* Using the credentials from the first pipe, open a signed and sealed
2505 second netlogon pipe. The session key is stored in the schannel
2506 part of the new pipe auth struct.
2509 result = cli_rpc_pipe_open_schannel_with_key(
2510 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2511 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2512 &conn->netlogon_pipe);
2514 /* We can now close the initial netlogon pipe. */
2515 TALLOC_FREE(netlogon_pipe);
2517 if (!NT_STATUS_IS_OK(result)) {
2518 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2519 "was %s\n", nt_errstr(result)));
2521 invalidate_cm_connection(conn);
2522 return result;
2526 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2527 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2528 * supported). We used to only try SamLogonEx for AD, but
2529 * Samba DCs can also do it. And because we don't distinguish
2530 * between Samba and NT4, always try it once.
2532 domain->can_do_samlogon_ex = true;
2534 *cli = conn->netlogon_pipe;
2535 return NT_STATUS_OK;