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
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
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
63 #include "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/cli_netlogon.h"
65 #include "rpc_client/cli_netlogon.h"
66 #include "../librpc/gen_ndr/cli_samr.h"
67 #include "../librpc/gen_ndr/cli_lsa.h"
68 #include "rpc_client/cli_lsarpc.h"
69 #include "../librpc/gen_ndr/cli_dssetup.h"
70 #include "libads/sitename_cache.h"
71 #include "librpc/gen_ndr/messaging.h"
72 #include "libsmb/clidgram.h"
77 #define DBGC_CLASS DBGC_WINBIND
81 struct sockaddr_storage ss;
84 extern struct winbindd_methods reconnect_methods;
85 extern bool override_logfile;
87 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
88 static void set_dc_type_and_flags( struct winbindd_domain *domain );
89 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
90 struct dc_name_ip **dcs, int *num_dcs);
92 /****************************************************************
93 Child failed to find DC's. Reschedule check.
94 ****************************************************************/
96 static void msg_failed_to_go_online(struct messaging_context *msg,
99 struct server_id server_id,
102 struct winbindd_domain *domain;
103 const char *domainname = (const char *)data->data;
105 if (data->data == NULL || data->length == 0) {
109 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
111 for (domain = domain_list(); domain; domain = domain->next) {
112 if (domain->internal) {
116 if (strequal(domain->name, domainname)) {
117 if (domain->online) {
118 /* We're already online, ignore. */
119 DEBUG(5,("msg_fail_to_go_online: domain %s "
120 "already online.\n", domainname));
124 /* Reschedule the online check. */
125 set_domain_offline(domain);
131 /****************************************************************
132 Actually cause a reconnect from a message.
133 ****************************************************************/
135 static void msg_try_to_go_online(struct messaging_context *msg,
138 struct server_id server_id,
141 struct winbindd_domain *domain;
142 const char *domainname = (const char *)data->data;
144 if (data->data == NULL || data->length == 0) {
148 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
150 for (domain = domain_list(); domain; domain = domain->next) {
151 if (domain->internal) {
155 if (strequal(domain->name, domainname)) {
157 if (domain->online) {
158 /* We're already online, ignore. */
159 DEBUG(5,("msg_try_to_go_online: domain %s "
160 "already online.\n", domainname));
164 /* This call takes care of setting the online
165 flag to true if we connected, or re-adding
166 the offline handler if false. Bypasses online
167 check so always does network calls. */
169 init_dc_connection_network(domain);
175 /****************************************************************
176 Fork a child to try and contact a DC. Do this as contacting a
177 DC requires blocking lookups and we don't want to block our
179 ****************************************************************/
181 static bool fork_child_dc_connect(struct winbindd_domain *domain)
183 struct dc_name_ip *dcs = NULL;
185 TALLOC_CTX *mem_ctx = NULL;
186 pid_t parent_pid = sys_getpid();
189 if (domain->dc_probe_pid != (pid_t)-1) {
191 * We might already have a DC probe
192 * child working, check.
194 if (process_exists_by_pid(domain->dc_probe_pid)) {
195 DEBUG(10,("fork_child_dc_connect: pid %u already "
196 "checking for DC's.\n",
197 (unsigned int)domain->dc_probe_pid));
200 domain->dc_probe_pid = (pid_t)-1;
203 domain->dc_probe_pid = sys_fork();
205 if (domain->dc_probe_pid == (pid_t)-1) {
206 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
210 if (domain->dc_probe_pid != (pid_t)0) {
212 messaging_register(winbind_messaging_context(), NULL,
213 MSG_WINBIND_TRY_TO_GO_ONLINE,
214 msg_try_to_go_online);
215 messaging_register(winbind_messaging_context(), NULL,
216 MSG_WINBIND_FAILED_TO_GO_ONLINE,
217 msg_failed_to_go_online);
223 /* Leave messages blocked - we will never process one. */
225 if (!override_logfile) {
226 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
227 DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
232 if (!winbindd_reinit_after_fork(lfile)) {
233 messaging_send_buf(winbind_messaging_context(),
234 pid_to_procid(parent_pid),
235 MSG_WINBIND_FAILED_TO_GO_ONLINE,
236 (uint8 *)domain->name,
237 strlen(domain->name)+1);
242 mem_ctx = talloc_init("fork_child_dc_connect");
244 DEBUG(0,("talloc_init failed.\n"));
245 messaging_send_buf(winbind_messaging_context(),
246 pid_to_procid(parent_pid),
247 MSG_WINBIND_FAILED_TO_GO_ONLINE,
248 (uint8 *)domain->name,
249 strlen(domain->name)+1);
253 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
254 /* Still offline ? Can't find DC's. */
255 messaging_send_buf(winbind_messaging_context(),
256 pid_to_procid(parent_pid),
257 MSG_WINBIND_FAILED_TO_GO_ONLINE,
258 (uint8 *)domain->name,
259 strlen(domain->name)+1);
263 /* We got a DC. Send a message to our parent to get it to
264 try and do the same. */
266 messaging_send_buf(winbind_messaging_context(),
267 pid_to_procid(parent_pid),
268 MSG_WINBIND_TRY_TO_GO_ONLINE,
269 (uint8 *)domain->name,
270 strlen(domain->name)+1);
274 /****************************************************************
275 Handler triggered if we're offline to try and detect a DC.
276 ****************************************************************/
278 static void check_domain_online_handler(struct event_context *ctx,
279 struct timed_event *te,
283 struct winbindd_domain *domain =
284 (struct winbindd_domain *)private_data;
286 DEBUG(10,("check_domain_online_handler: called for domain "
287 "%s (online = %s)\n", domain->name,
288 domain->online ? "True" : "False" ));
290 TALLOC_FREE(domain->check_online_event);
292 /* Are we still in "startup" mode ? */
294 if (domain->startup && (now.tv_sec > domain->startup_time + 30)) {
295 /* No longer in "startup" mode. */
296 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
298 domain->startup = False;
301 /* We've been told to stay offline, so stay
304 if (get_global_winbindd_state_offline()) {
305 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
310 /* Fork a child to test if it can contact a DC.
311 If it can then send ourselves a message to
312 cause a reconnect. */
314 fork_child_dc_connect(domain);
317 /****************************************************************
318 If we're still offline setup the timeout check.
319 ****************************************************************/
321 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
323 int wbr = lp_winbind_reconnect_delay();
325 if (domain->startup) {
326 domain->check_online_timeout = 10;
327 } else if (domain->check_online_timeout < wbr) {
328 domain->check_online_timeout = wbr;
332 /****************************************************************
333 Set domain offline and also add handler to put us back online
335 ****************************************************************/
337 void set_domain_offline(struct winbindd_domain *domain)
339 DEBUG(10,("set_domain_offline: called for domain %s\n",
342 TALLOC_FREE(domain->check_online_event);
344 if (domain->internal) {
345 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
350 domain->online = False;
352 /* Offline domains are always initialized. They're
353 re-initialized when they go back online. */
355 domain->initialized = True;
357 /* We only add the timeout handler that checks and
358 allows us to go back online when we've not
359 been told to remain offline. */
361 if (get_global_winbindd_state_offline()) {
362 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
367 /* If we're in startup mode, check again in 10 seconds, not in
368 lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
370 calc_new_online_timeout_check(domain);
372 domain->check_online_event = event_add_timed(winbind_event_context(),
374 timeval_current_ofs(domain->check_online_timeout,0),
375 check_domain_online_handler,
378 /* The above *has* to succeed for winbindd to work. */
379 if (!domain->check_online_event) {
380 smb_panic("set_domain_offline: failed to add online handler");
383 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
386 /* Send an offline message to the idmap child when our
387 primary domain goes offline */
389 if ( domain->primary ) {
390 struct winbindd_child *idmap = idmap_child();
392 if ( idmap->pid != 0 ) {
393 messaging_send_buf(winbind_messaging_context(),
394 pid_to_procid(idmap->pid),
396 (uint8 *)domain->name,
397 strlen(domain->name)+1);
404 /****************************************************************
405 Set domain online - if allowed.
406 ****************************************************************/
408 static void set_domain_online(struct winbindd_domain *domain)
410 DEBUG(10,("set_domain_online: called for domain %s\n",
413 if (domain->internal) {
414 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
419 if (get_global_winbindd_state_offline()) {
420 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
425 winbindd_set_locator_kdc_envs(domain);
427 /* If we are waiting to get a krb5 ticket, trigger immediately. */
428 ccache_regain_all_now();
430 /* Ok, we're out of any startup mode now... */
431 domain->startup = False;
433 if (domain->online == False) {
434 /* We were offline - now we're online. We default to
435 using the MS-RPC backend if we started offline,
436 and if we're going online for the first time we
437 should really re-initialize the backends and the
438 checks to see if we're talking to an AD or NT domain.
441 domain->initialized = False;
443 /* 'reconnect_methods' is the MS-RPC backend. */
444 if (domain->backend == &reconnect_methods) {
445 domain->backend = NULL;
449 /* Ensure we have no online timeout checks. */
450 domain->check_online_timeout = 0;
451 TALLOC_FREE(domain->check_online_event);
453 /* Ensure we ignore any pending child messages. */
454 messaging_deregister(winbind_messaging_context(),
455 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
456 messaging_deregister(winbind_messaging_context(),
457 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
459 domain->online = True;
461 /* Send an online message to the idmap child when our
462 primary domain comes online */
464 if ( domain->primary ) {
465 struct winbindd_child *idmap = idmap_child();
467 if ( idmap->pid != 0 ) {
468 messaging_send_buf(winbind_messaging_context(),
469 pid_to_procid(idmap->pid),
471 (uint8 *)domain->name,
472 strlen(domain->name)+1);
479 /****************************************************************
480 Requested to set a domain online.
481 ****************************************************************/
483 void set_domain_online_request(struct winbindd_domain *domain)
487 DEBUG(10,("set_domain_online_request: called for domain %s\n",
490 if (get_global_winbindd_state_offline()) {
491 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
496 if (domain->internal) {
497 DEBUG(10, ("set_domain_online_request: Internal domains are "
502 /* We've been told it's safe to go online and
503 try and connect to a DC. But I don't believe it
504 because network manager seems to lie.
505 Wait at least 5 seconds. Heuristics suck... */
510 /* Go into "startup" mode again. */
511 domain->startup_time = tev.tv_sec;
512 domain->startup = True;
516 if (!domain->check_online_event) {
517 /* If we've come from being globally offline we
518 don't have a check online event handler set.
519 We need to add one now we're trying to go
522 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
526 TALLOC_FREE(domain->check_online_event);
528 domain->check_online_event = event_add_timed(winbind_event_context(),
531 check_domain_online_handler,
534 /* The above *has* to succeed for winbindd to work. */
535 if (!domain->check_online_event) {
536 smb_panic("set_domain_online_request: failed to add online handler");
540 /****************************************************************
541 Add -ve connection cache entries for domain and realm.
542 ****************************************************************/
544 static void winbind_add_failed_connection_entry(
545 const struct winbindd_domain *domain,
549 add_failed_connection_entry(domain->name, server, result);
550 /* If this was the saf name for the last thing we talked to,
552 saf_delete(domain->name);
553 if (*domain->alt_name) {
554 add_failed_connection_entry(domain->alt_name, server, result);
555 saf_delete(domain->alt_name);
557 winbindd_unset_locator_kdc_env(domain);
560 /* Choose between anonymous or authenticated connections. We need to use
561 an authenticated connection if DCs have the RestrictAnonymous registry
562 entry set > 0, or the "Additional restrictions for anonymous
563 connections" set in the win2k Local Security Policy.
565 Caller to free() result in domain, username, password
568 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
570 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
571 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
572 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
574 if (*username && **username) {
576 if (!*domain || !**domain)
577 *domain = smb_xstrdup(lp_workgroup());
579 if (!*password || !**password)
580 *password = smb_xstrdup("");
582 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
583 *domain, *username));
586 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
587 *username = smb_xstrdup("");
588 *domain = smb_xstrdup("");
589 *password = smb_xstrdup("");
593 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
595 struct sockaddr_storage *dc_ss)
597 struct winbindd_domain *our_domain = NULL;
598 struct rpc_pipe_client *netlogon_pipe = NULL;
602 unsigned int orig_timeout;
603 const char *tmp = NULL;
606 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
613 if (domain->primary) {
617 our_domain = find_our_domain();
619 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
623 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
624 if (!NT_STATUS_IS_OK(result)) {
625 talloc_destroy(mem_ctx);
629 /* This call can take a long time - allow the server to time out.
630 35 seconds should do it. */
632 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
634 if (our_domain->active_directory) {
635 struct netr_DsRGetDCNameInfo *domain_info = NULL;
637 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
646 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
648 mem_ctx, domain_info->dc_unc);
650 DEBUG(0, ("talloc_strdup failed\n"));
651 talloc_destroy(mem_ctx);
654 if (strlen(domain->alt_name) == 0) {
655 fstrcpy(domain->alt_name,
656 domain_info->domain_name);
658 if (strlen(domain->forest_name) == 0) {
659 fstrcpy(domain->forest_name,
660 domain_info->forest_name);
664 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
671 /* And restore our original timeout. */
672 rpccli_set_timeout(netlogon_pipe, orig_timeout);
674 if (!NT_STATUS_IS_OK(result)) {
675 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
677 talloc_destroy(mem_ctx);
681 if (!W_ERROR_IS_OK(werr)) {
682 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
684 talloc_destroy(mem_ctx);
688 /* rpccli_netr_GetAnyDCName gives us a name with \\ */
689 p = strip_hostname(tmp);
693 talloc_destroy(mem_ctx);
695 DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
697 if (!resolve_name(dcname, dc_ss, 0x20, true)) {
705 * Helper function to assemble trust password and account name
707 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
708 char **machine_password,
709 char **machine_account,
710 char **machine_krb5_principal)
712 const char *account_name;
713 const char *name = NULL;
715 /* If we are a DC and this is not our own domain */
720 struct winbindd_domain *our_domain = find_our_domain();
723 return NT_STATUS_INVALID_SERVER_STATE;
725 name = our_domain->name;
728 if (!get_trust_pw_clear(name, machine_password,
729 &account_name, NULL))
731 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
734 if ((machine_account != NULL) &&
735 (asprintf(machine_account, "%s$", account_name) == -1))
737 return NT_STATUS_NO_MEMORY;
740 /* For now assume our machine account only exists in our domain */
742 if (machine_krb5_principal != NULL)
744 struct winbindd_domain *our_domain = find_our_domain();
747 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
750 if (asprintf(machine_krb5_principal, "%s$@%s",
751 account_name, our_domain->alt_name) == -1)
753 return NT_STATUS_NO_MEMORY;
756 strupper_m(*machine_krb5_principal);
762 /************************************************************************
763 Given a fd with a just-connected TCP connection to a DC, open a connection
765 ************************************************************************/
767 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
769 const char *controller,
770 struct cli_state **cli,
773 char *machine_password = NULL;
774 char *machine_krb5_principal = NULL;
775 char *machine_account = NULL;
776 char *ipc_username = NULL;
777 char *ipc_domain = NULL;
778 char *ipc_password = NULL;
780 struct named_mutex *mutex;
782 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
784 struct sockaddr peeraddr;
785 socklen_t peeraddr_len;
787 struct sockaddr_in *peeraddr_in =
788 (struct sockaddr_in *)(void *)&peeraddr;
790 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
791 controller, domain->name ));
795 mutex = grab_named_mutex(talloc_tos(), controller,
796 WINBIND_SERVER_MUTEX_WAIT_TIME);
798 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
800 result = NT_STATUS_POSSIBLE_DEADLOCK;
804 if ((*cli = cli_initialise()) == NULL) {
805 DEBUG(1, ("Could not cli_initialize\n"));
806 result = NT_STATUS_NO_MEMORY;
810 (*cli)->timeout = 10000; /* 10 seconds */
812 fstrcpy((*cli)->desthost, controller);
813 (*cli)->use_kerberos = True;
815 peeraddr_len = sizeof(peeraddr);
817 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
818 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
820 result = NT_STATUS_UNSUCCESSFUL;
824 if ((peeraddr_len != sizeof(struct sockaddr_in))
826 && (peeraddr_len != sizeof(struct sockaddr_in6))
829 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
831 result = NT_STATUS_UNSUCCESSFUL;
835 if ((peeraddr_in->sin_family != PF_INET)
837 && (peeraddr_in->sin_family != PF_INET6)
840 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
841 peeraddr_in->sin_family));
842 result = NT_STATUS_UNSUCCESSFUL;
846 if (ntohs(peeraddr_in->sin_port) == 139) {
847 struct nmb_name calling;
848 struct nmb_name called;
850 make_nmb_name(&calling, global_myname(), 0x0);
851 make_nmb_name(&called, "*SMBSERVER", 0x20);
853 if (!cli_session_request(*cli, &calling, &called)) {
854 DEBUG(8, ("cli_session_request failed for %s\n",
856 result = NT_STATUS_UNSUCCESSFUL;
861 result = cli_negprot(*cli);
863 if (!NT_STATUS_IS_OK(result)) {
864 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
868 if (!is_dc_trusted_domain_situation(domain->name) &&
869 (*cli)->protocol >= PROTOCOL_NT1 &&
870 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
872 ADS_STATUS ads_status;
874 result = get_trust_creds(domain, &machine_password,
876 &machine_krb5_principal);
877 if (!NT_STATUS_IS_OK(result)) {
881 if (lp_security() == SEC_ADS) {
883 /* Try a krb5 session */
885 (*cli)->use_kerberos = True;
886 DEBUG(5, ("connecting to %s from %s with kerberos principal "
887 "[%s] and realm [%s]\n", controller, global_myname(),
888 machine_krb5_principal, domain->alt_name));
890 winbindd_set_locator_kdc_envs(domain);
892 ads_status = cli_session_setup_spnego(*cli,
893 machine_krb5_principal,
898 if (!ADS_ERR_OK(ads_status)) {
899 DEBUG(4,("failed kerberos session setup with %s\n",
900 ads_errstr(ads_status)));
903 result = ads_ntstatus(ads_status);
904 if (NT_STATUS_IS_OK(result)) {
905 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
906 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
907 if (!NT_STATUS_IS_OK(result)) {
910 goto session_setup_done;
914 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
915 (*cli)->use_kerberos = False;
917 DEBUG(5, ("connecting to %s from %s with username "
918 "[%s]\\[%s]\n", controller, global_myname(),
919 lp_workgroup(), machine_account));
921 ads_status = cli_session_setup_spnego(*cli,
926 if (!ADS_ERR_OK(ads_status)) {
927 DEBUG(4, ("authenticated session setup failed with %s\n",
928 ads_errstr(ads_status)));
931 result = ads_ntstatus(ads_status);
932 if (NT_STATUS_IS_OK(result)) {
933 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
934 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
935 if (!NT_STATUS_IS_OK(result)) {
938 goto session_setup_done;
942 /* Fall back to non-kerberos session setup with auth_user */
944 (*cli)->use_kerberos = False;
946 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
948 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
949 (strlen(ipc_username) > 0)) {
951 /* Only try authenticated if we have a username */
953 DEBUG(5, ("connecting to %s from %s with username "
954 "[%s]\\[%s]\n", controller, global_myname(),
955 ipc_domain, ipc_username));
957 if (NT_STATUS_IS_OK(cli_session_setup(
959 ipc_password, strlen(ipc_password)+1,
960 ipc_password, strlen(ipc_password)+1,
962 /* Successful logon with given username. */
963 result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
964 if (!NT_STATUS_IS_OK(result)) {
967 goto session_setup_done;
969 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
970 ipc_domain, ipc_username ));
976 /* Fall back to anonymous connection, this might fail later */
977 DEBUG(10,("cm_prepare_connection: falling back to anonymous "
978 "connection for DC %s\n",
981 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
983 DEBUG(5, ("Connected anonymously\n"));
984 result = cli_init_creds(*cli, "", "", "");
985 if (!NT_STATUS_IS_OK(result)) {
988 goto session_setup_done;
991 result = cli_nt_error(*cli);
993 if (NT_STATUS_IS_OK(result))
994 result = NT_STATUS_UNSUCCESSFUL;
996 /* We can't session setup */
1002 /* cache the server name for later connections */
1004 saf_store( domain->name, (*cli)->desthost );
1005 if (domain->alt_name && (*cli)->use_kerberos) {
1006 saf_store( domain->alt_name, (*cli)->desthost );
1009 winbindd_set_locator_kdc_envs(domain);
1011 result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
1013 if (!NT_STATUS_IS_OK(result)) {
1014 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1021 /* set the domain if empty; needed for schannel connections */
1022 if ( !(*cli)->domain[0] ) {
1023 result = cli_set_domain((*cli), domain->name);
1024 if (!NT_STATUS_IS_OK(result)) {
1029 result = NT_STATUS_OK;
1033 SAFE_FREE(machine_account);
1034 SAFE_FREE(machine_password);
1035 SAFE_FREE(machine_krb5_principal);
1036 SAFE_FREE(ipc_username);
1037 SAFE_FREE(ipc_domain);
1038 SAFE_FREE(ipc_password);
1040 if (!NT_STATUS_IS_OK(result)) {
1041 winbind_add_failed_connection_entry(domain, controller, result);
1042 if ((*cli) != NULL) {
1051 /*******************************************************************
1052 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1055 Keeps the list unique by not adding duplicate entries.
1057 @param[in] mem_ctx talloc memory context to allocate from
1058 @param[in] domain_name domain of the DC
1059 @param[in] dcname name of the DC to add to the list
1060 @param[in] pss Internet address and port pair to add to the list
1061 @param[in,out] dcs array of dc_name_ip structures to add to
1062 @param[in,out] num_dcs number of dcs returned in the dcs array
1063 @return true if the list was added to, false otherwise
1064 *******************************************************************/
1066 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1067 const char *dcname, struct sockaddr_storage *pss,
1068 struct dc_name_ip **dcs, int *num)
1072 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1073 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1077 /* Make sure there's no duplicates in the list */
1078 for (i=0; i<*num; i++)
1080 (struct sockaddr *)(void *)&(*dcs)[i].ss,
1081 (struct sockaddr *)(void *)pss))
1084 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1089 fstrcpy((*dcs)[*num].name, dcname);
1090 (*dcs)[*num].ss = *pss;
1095 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1096 struct sockaddr_storage *pss, uint16 port,
1097 struct sockaddr_storage **addrs, int *num)
1099 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1101 if (*addrs == NULL) {
1106 (*addrs)[*num] = *pss;
1107 set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1113 /*******************************************************************
1114 convert an ip to a name
1115 *******************************************************************/
1117 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1118 const struct winbindd_domain *domain,
1119 struct sockaddr_storage *pss,
1122 struct ip_service ip_list;
1123 uint32_t nt_version = NETLOGON_NT_VERSION_1;
1129 /* For active directory servers, try to get the ldap server name.
1130 None of these failures should be considered critical for now */
1132 if (lp_security() == SEC_ADS) {
1134 ADS_STATUS ads_status;
1135 char addr[INET6_ADDRSTRLEN];
1137 print_sockaddr(addr, sizeof(addr), pss);
1139 ads = ads_init(domain->alt_name, domain->name, addr);
1140 ads->auth.flags |= ADS_AUTH_NO_BIND;
1142 ads_status = ads_connect(ads);
1143 if (ADS_ERR_OK(ads_status)) {
1144 /* We got a cldap packet. */
1145 fstrcpy(name, ads->config.ldap_server_name);
1146 namecache_store(name, 0x20, 1, &ip_list);
1148 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1150 if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1151 if (ads_closest_dc(ads)) {
1152 char *sitename = sitename_fetch(ads->config.realm);
1154 /* We're going to use this KDC for this realm/domain.
1155 If we are using sites, then force the krb5 libs
1158 create_local_private_krb5_conf_for_domain(domain->alt_name,
1164 SAFE_FREE(sitename);
1166 /* use an off site KDC */
1167 create_local_private_krb5_conf_for_domain(domain->alt_name,
1173 winbindd_set_locator_kdc_envs(domain);
1175 /* Ensure we contact this DC also. */
1176 saf_store( domain->name, name);
1177 saf_store( domain->alt_name, name);
1180 ads_destroy( &ads );
1184 ads_destroy( &ads );
1188 /* try GETDC requests next */
1190 if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1191 pss, domain->name, &domain->sid,
1193 const char *dc_name = NULL;
1196 for (i=0; i<5; i++) {
1197 if (receive_getdc_response(mem_ctx, pss, domain->name,
1200 fstrcpy(name, dc_name);
1201 namecache_store(name, 0x20, 1, &ip_list);
1208 /* try node status request */
1210 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1211 namecache_store(name, 0x20, 1, &ip_list);
1217 /*******************************************************************
1218 Retrieve a list of IP addresses for domain controllers.
1220 The array is sorted in the preferred connection order.
1222 @param[in] mem_ctx talloc memory context to allocate from
1223 @param[in] domain domain to retrieve DCs for
1224 @param[out] dcs array of dcs that will be returned
1225 @param[out] num_dcs number of dcs returned in the dcs array
1227 *******************************************************************/
1229 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1230 struct dc_name_ip **dcs, int *num_dcs)
1233 struct sockaddr_storage ss;
1234 struct ip_service *ip_list = NULL;
1235 int iplist_size = 0;
1238 enum security_types sec = (enum security_types)lp_security();
1240 is_our_domain = strequal(domain->name, lp_workgroup());
1242 /* If not our domain, get the preferred DC, by asking our primary DC */
1244 && get_dc_name_via_netlogon(domain, dcname, &ss)
1245 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1248 char addr[INET6_ADDRSTRLEN];
1249 print_sockaddr(addr, sizeof(addr), &ss);
1250 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1255 if (sec == SEC_ADS) {
1256 char *sitename = NULL;
1258 /* We need to make sure we know the local site before
1259 doing any DNS queries, as this will restrict the
1260 get_sorted_dc_list() call below to only fetching
1261 DNS records for the correct site. */
1263 /* Find any DC to get the site record.
1264 We deliberately don't care about the
1267 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1269 sitename = sitename_fetch(domain->alt_name);
1272 /* Do the site-specific AD dns lookup first. */
1273 get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1274 &iplist_size, True);
1276 /* Add ips to the DC array. We don't look up the name
1277 of the DC in this function, but we fill in the char*
1278 of the ip now to make the failed connection cache
1280 for ( i=0; i<iplist_size; i++ ) {
1281 char addr[INET6_ADDRSTRLEN];
1282 print_sockaddr(addr, sizeof(addr),
1284 add_one_dc_unique(mem_ctx,
1293 SAFE_FREE(sitename);
1297 /* Now we add DCs from the main AD DNS lookup. */
1298 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1299 &iplist_size, True);
1301 for ( i=0; i<iplist_size; i++ ) {
1302 char addr[INET6_ADDRSTRLEN];
1303 print_sockaddr(addr, sizeof(addr),
1305 add_one_dc_unique(mem_ctx,
1317 /* Try standard netbios queries if no ADS */
1318 if (*num_dcs == 0) {
1319 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1322 for ( i=0; i<iplist_size; i++ ) {
1323 char addr[INET6_ADDRSTRLEN];
1324 print_sockaddr(addr, sizeof(addr),
1326 add_one_dc_unique(mem_ctx,
1341 /*******************************************************************
1342 Find and make a connection to a DC in the given domain.
1344 @param[in] mem_ctx talloc memory context to allocate from
1345 @param[in] domain domain to find a dc in
1346 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1347 @param[out] pss DC Internet address and port
1348 @param[out] fd fd of the open socket connected to the newly found dc
1349 @return true when a DC connection is made, false otherwise
1350 *******************************************************************/
1352 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1353 struct winbindd_domain *domain,
1354 fstring dcname, struct sockaddr_storage *pss, int *fd)
1356 struct dc_name_ip *dcs = NULL;
1359 const char **dcnames = NULL;
1360 int num_dcnames = 0;
1362 struct sockaddr_storage *addrs = NULL;
1370 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1373 for (i=0; i<num_dcs; i++) {
1375 if (!add_string_to_array(mem_ctx, dcs[i].name,
1376 &dcnames, &num_dcnames)) {
1379 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1380 &addrs, &num_addrs)) {
1384 if (!add_string_to_array(mem_ctx, dcs[i].name,
1385 &dcnames, &num_dcnames)) {
1388 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1389 &addrs, &num_addrs)) {
1394 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1397 if ((addrs == NULL) || (dcnames == NULL))
1400 /* 5 second timeout. */
1401 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1402 for (i=0; i<num_dcs; i++) {
1403 char ab[INET6_ADDRSTRLEN];
1404 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1405 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1406 "domain %s address %s. Error was %s\n",
1407 domain->name, ab, strerror(errno) ));
1408 winbind_add_failed_connection_entry(domain,
1409 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1414 *pss = addrs[fd_index];
1416 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1417 /* Ok, we've got a name for the DC */
1418 fstrcpy(dcname, dcnames[fd_index]);
1422 /* Try to figure out the name */
1423 if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1427 /* We can not continue without the DC's name */
1428 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1429 NT_STATUS_UNSUCCESSFUL);
1431 /* Throw away all arrays as we're doing this again. */
1435 TALLOC_FREE(dcnames);
1447 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1448 struct winbindd_cm_conn *new_conn)
1450 TALLOC_CTX *mem_ctx;
1452 char *saf_servername = saf_fetch( domain->name );
1455 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1456 SAFE_FREE(saf_servername);
1457 set_domain_offline(domain);
1458 return NT_STATUS_NO_MEMORY;
1461 /* we have to check the server affinity cache here since
1462 later we select a DC based on response time and not preference */
1464 /* Check the negative connection cache
1465 before talking to it. It going down may have
1466 triggered the reconnection. */
1468 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1470 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1471 saf_servername, domain->name ));
1473 /* convert an ip address to a name */
1474 if (is_ipaddress( saf_servername ) ) {
1476 struct sockaddr_storage ss;
1478 if (!interpret_string_addr(&ss, saf_servername,
1480 return NT_STATUS_UNSUCCESSFUL;
1482 if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1483 fstrcpy( domain->dcname, saf_name );
1485 winbind_add_failed_connection_entry(
1486 domain, saf_servername,
1487 NT_STATUS_UNSUCCESSFUL);
1490 fstrcpy( domain->dcname, saf_servername );
1493 SAFE_FREE( saf_servername );
1496 for (retries = 0; retries < 3; retries++) {
1500 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1502 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1503 domain->dcname, domain->name ));
1506 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1507 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1509 struct sockaddr_storage *addrs = NULL;
1513 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1514 set_domain_offline(domain);
1515 talloc_destroy(mem_ctx);
1516 return NT_STATUS_NO_MEMORY;
1518 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1519 set_domain_offline(domain);
1520 talloc_destroy(mem_ctx);
1521 return NT_STATUS_NO_MEMORY;
1524 /* 5 second timeout. */
1525 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1531 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1533 /* This is the one place where we will
1534 set the global winbindd offline state
1535 to true, if a "WINBINDD_OFFLINE" entry
1536 is found in the winbindd cache. */
1537 set_global_winbindd_state_offline();
1541 new_conn->cli = NULL;
1543 result = cm_prepare_connection(domain, fd, domain->dcname,
1544 &new_conn->cli, &retry);
1550 if (NT_STATUS_IS_OK(result)) {
1552 winbindd_set_locator_kdc_envs(domain);
1554 if (domain->online == False) {
1555 /* We're changing state from offline to online. */
1556 set_global_winbindd_state_online();
1558 set_domain_online(domain);
1560 /* Ensure we setup the retry handler. */
1561 set_domain_offline(domain);
1564 talloc_destroy(mem_ctx);
1568 /* Close down all open pipes on a connection. */
1570 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1572 /* We're closing down a possibly dead
1573 connection. Don't have impossibly long (10s) timeouts. */
1576 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1579 if (conn->samr_pipe != NULL) {
1580 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1581 rpccli_samr_Close(conn->samr_pipe, talloc_tos(),
1582 &conn->sam_connect_handle);
1584 TALLOC_FREE(conn->samr_pipe);
1585 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1587 cli_set_timeout(conn->cli, 500);
1591 if (conn->lsa_pipe != NULL) {
1592 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1593 rpccli_lsa_Close(conn->lsa_pipe, talloc_tos(),
1596 TALLOC_FREE(conn->lsa_pipe);
1597 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1599 cli_set_timeout(conn->cli, 500);
1603 if (conn->lsa_pipe_tcp != NULL) {
1604 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1605 rpccli_lsa_Close(conn->lsa_pipe, talloc_tos(),
1608 TALLOC_FREE(conn->lsa_pipe_tcp);
1609 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1611 cli_set_timeout(conn->cli, 500);
1615 if (conn->netlogon_pipe != NULL) {
1616 TALLOC_FREE(conn->netlogon_pipe);
1617 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1619 cli_set_timeout(conn->cli, 500);
1624 cli_shutdown(conn->cli);
1630 void close_conns_after_fork(void)
1632 struct winbindd_domain *domain;
1634 for (domain = domain_list(); domain; domain = domain->next) {
1635 struct cli_state *cli = domain->conn.cli;
1638 * first close the low level SMB TCP connection
1639 * so that we don't generate any SMBclose
1640 * requests in invalidate_cm_connection()
1642 if (cli && cli->fd != -1) {
1643 close(domain->conn.cli->fd);
1644 domain->conn.cli->fd = -1;
1647 invalidate_cm_connection(&domain->conn);
1651 static bool connection_ok(struct winbindd_domain *domain)
1655 ok = cli_state_is_connected(domain->conn.cli);
1657 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1658 domain->dcname, domain->name));
1662 if (domain->online == False) {
1663 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1670 /* Initialize a new connection up to the RPC BIND.
1671 Bypass online status check so always does network calls. */
1673 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1677 /* Internal connections never use the network. */
1678 if (domain->internal) {
1679 domain->initialized = True;
1680 return NT_STATUS_OK;
1683 if (!winbindd_can_contact_domain(domain)) {
1684 invalidate_cm_connection(&domain->conn);
1685 domain->initialized = True;
1686 return NT_STATUS_OK;
1689 if (connection_ok(domain)) {
1690 if (!domain->initialized) {
1691 set_dc_type_and_flags(domain);
1693 return NT_STATUS_OK;
1696 invalidate_cm_connection(&domain->conn);
1698 result = cm_open_connection(domain, &domain->conn);
1700 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1701 set_dc_type_and_flags(domain);
1707 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1709 if (domain->internal) {
1710 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1713 if (domain->initialized && !domain->online) {
1714 /* We check for online status elsewhere. */
1715 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1718 return init_dc_connection_network(domain);
1721 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1725 status = init_dc_connection(domain);
1726 if (!NT_STATUS_IS_OK(status)) {
1730 if (!domain->internal && domain->conn.cli == NULL) {
1731 /* happens for trusted domains without inbound trust */
1732 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1735 return NT_STATUS_OK;
1738 /******************************************************************************
1739 Set the trust flags (direction and forest location) for a domain
1740 ******************************************************************************/
1742 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1744 struct winbindd_domain *our_domain;
1745 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1746 struct netr_DomainTrustList trusts;
1748 uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1749 NETR_TRUST_FLAG_OUTBOUND |
1750 NETR_TRUST_FLAG_INBOUND);
1751 struct rpc_pipe_client *cli;
1752 TALLOC_CTX *mem_ctx = NULL;
1754 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1756 /* Our primary domain doesn't need to worry about trust flags.
1757 Force it to go through the network setup */
1758 if ( domain->primary ) {
1762 our_domain = find_our_domain();
1764 if ( !connection_ok(our_domain) ) {
1765 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1769 /* This won't work unless our domain is AD */
1771 if ( !our_domain->active_directory ) {
1775 /* Use DsEnumerateDomainTrusts to get us the trust direction
1778 result = cm_connect_netlogon(our_domain, &cli);
1780 if (!NT_STATUS_IS_OK(result)) {
1781 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1782 "a connection to %s for PIPE_NETLOGON (%s)\n",
1783 domain->name, nt_errstr(result)));
1787 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1788 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1792 result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1797 if (!NT_STATUS_IS_OK(result)) {
1798 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1799 "failed to query trusted domain list: %s\n",
1800 nt_errstr(result)));
1801 talloc_destroy(mem_ctx);
1805 /* Now find the domain name and get the flags */
1807 for ( i=0; i<trusts.count; i++ ) {
1808 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1809 domain->domain_flags = trusts.array[i].trust_flags;
1810 domain->domain_type = trusts.array[i].trust_type;
1811 domain->domain_trust_attribs = trusts.array[i].trust_attributes;
1813 if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1814 domain->active_directory = True;
1816 /* This flag is only set if the domain is *our*
1817 primary domain and the primary domain is in
1820 domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1822 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1823 "native mode.\n", domain->name,
1824 domain->native_mode ? "" : "NOT "));
1826 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1827 "running active directory.\n", domain->name,
1828 domain->active_directory ? "" : "NOT "));
1831 domain->initialized = True;
1837 talloc_destroy( mem_ctx );
1839 return domain->initialized;
1842 /******************************************************************************
1843 We can 'sense' certain things about the DC by it's replies to certain
1846 This tells us if this particular remote server is Active Directory, and if it
1848 ******************************************************************************/
1850 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1854 TALLOC_CTX *mem_ctx = NULL;
1855 struct rpc_pipe_client *cli = NULL;
1856 struct policy_handle pol;
1857 union dssetup_DsRoleInfo info;
1858 union lsa_PolicyInformation *lsa_info = NULL;
1860 if (!connection_ok(domain)) {
1864 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1867 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1871 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1873 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1874 &ndr_table_dssetup.syntax_id,
1877 if (!NT_STATUS_IS_OK(result)) {
1878 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1879 "PI_DSSETUP on domain %s: (%s)\n",
1880 domain->name, nt_errstr(result)));
1882 /* if this is just a non-AD domain we need to continue
1883 * identifying so that we can in the end return with
1884 * domain->initialized = True - gd */
1889 result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1890 DS_ROLE_BASIC_INFORMATION,
1895 if (!NT_STATUS_IS_OK(result)) {
1896 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1897 "on domain %s failed: (%s)\n",
1898 domain->name, nt_errstr(result)));
1900 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1901 * every opcode on the DSSETUP pipe, continue with
1902 * no_dssetup mode here as well to get domain->initialized
1905 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1909 TALLOC_FREE(mem_ctx);
1913 if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1914 !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1915 domain->native_mode = True;
1917 domain->native_mode = False;
1921 result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1922 &ndr_table_lsarpc.syntax_id, &cli);
1924 if (!NT_STATUS_IS_OK(result)) {
1925 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1926 "PI_LSARPC on domain %s: (%s)\n",
1927 domain->name, nt_errstr(result)));
1929 TALLOC_FREE(mem_ctx);
1933 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1934 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1936 if (NT_STATUS_IS_OK(result)) {
1937 /* This particular query is exactly what Win2k clients use
1938 to determine that the DC is active directory */
1939 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1941 LSA_POLICY_INFO_DNS,
1945 if (NT_STATUS_IS_OK(result)) {
1946 domain->active_directory = True;
1948 if (lsa_info->dns.name.string) {
1949 fstrcpy(domain->name, lsa_info->dns.name.string);
1952 if (lsa_info->dns.dns_domain.string) {
1953 fstrcpy(domain->alt_name,
1954 lsa_info->dns.dns_domain.string);
1957 /* See if we can set some domain trust flags about
1960 if (lsa_info->dns.dns_forest.string) {
1961 fstrcpy(domain->forest_name,
1962 lsa_info->dns.dns_forest.string);
1964 if (strequal(domain->forest_name, domain->alt_name)) {
1965 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1969 if (lsa_info->dns.sid) {
1970 sid_copy(&domain->sid, lsa_info->dns.sid);
1973 domain->active_directory = False;
1975 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1976 SEC_FLAG_MAXIMUM_ALLOWED,
1979 if (!NT_STATUS_IS_OK(result)) {
1983 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1985 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1988 if (NT_STATUS_IS_OK(result)) {
1990 if (lsa_info->account_domain.name.string) {
1991 fstrcpy(domain->name,
1992 lsa_info->account_domain.name.string);
1995 if (lsa_info->account_domain.sid) {
1996 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2002 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2003 domain->name, domain->native_mode ? "" : "NOT "));
2005 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2006 domain->name, domain->active_directory ? "" : "NOT "));
2008 domain->can_do_ncacn_ip_tcp = domain->active_directory;
2012 TALLOC_FREE(mem_ctx);
2014 domain->initialized = True;
2017 /**********************************************************************
2018 Set the domain_flags (trust attributes, domain operating modes, etc...
2019 ***********************************************************************/
2021 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2023 /* we always have to contact our primary domain */
2025 if ( domain->primary ) {
2026 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2027 "primary domain\n"));
2028 set_dc_type_and_flags_connect( domain );
2032 /* Use our DC to get the information if possible */
2034 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2035 /* Otherwise, fallback to contacting the
2037 set_dc_type_and_flags_connect( domain );
2045 /**********************************************************************
2046 ***********************************************************************/
2048 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2049 struct netlogon_creds_CredentialState **ppdc)
2051 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2052 struct rpc_pipe_client *netlogon_pipe;
2054 if (lp_client_schannel() == False) {
2055 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;;
2058 result = cm_connect_netlogon(domain, &netlogon_pipe);
2059 if (!NT_STATUS_IS_OK(result)) {
2063 /* Return a pointer to the struct netlogon_creds_CredentialState from the
2066 if (!domain->conn.netlogon_pipe->dc) {
2067 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2070 *ppdc = domain->conn.netlogon_pipe->dc;
2071 return NT_STATUS_OK;
2074 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2075 struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2077 struct winbindd_cm_conn *conn;
2078 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2079 struct netlogon_creds_CredentialState *p_creds;
2080 char *machine_password = NULL;
2081 char *machine_account = NULL;
2082 char *domain_name = NULL;
2084 if (sid_check_is_domain(&domain->sid)) {
2085 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2088 result = init_dc_connection_rpc(domain);
2089 if (!NT_STATUS_IS_OK(result)) {
2093 conn = &domain->conn;
2095 if (rpccli_is_connected(conn->samr_pipe)) {
2099 TALLOC_FREE(conn->samr_pipe);
2102 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2103 * sign and sealed pipe using the machine account password by
2104 * preference. If we can't - try schannel, if that fails, try
2108 if ((conn->cli->user_name[0] == '\0') ||
2109 (conn->cli->domain[0] == '\0') ||
2110 (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2112 result = get_trust_creds(domain, &machine_password,
2113 &machine_account, NULL);
2114 if (!NT_STATUS_IS_OK(result)) {
2115 DEBUG(10, ("cm_connect_sam: No no user available for "
2116 "domain %s, trying schannel\n", conn->cli->domain));
2119 domain_name = domain->name;
2121 machine_password = SMB_STRDUP(conn->cli->password);
2122 machine_account = SMB_STRDUP(conn->cli->user_name);
2123 domain_name = conn->cli->domain;
2126 if (!machine_password || !machine_account) {
2127 result = NT_STATUS_NO_MEMORY;
2131 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2132 authenticated SAMR pipe with sign & seal. */
2133 result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2134 &ndr_table_samr.syntax_id,
2136 DCERPC_AUTH_LEVEL_PRIVACY,
2142 if (!NT_STATUS_IS_OK(result)) {
2143 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2144 "pipe for domain %s using NTLMSSP "
2145 "authenticated pipe: user %s\\%s. Error was "
2146 "%s\n", domain->name, domain_name,
2147 machine_account, nt_errstr(result)));
2151 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2152 "domain %s using NTLMSSP authenticated "
2153 "pipe: user %s\\%s\n", domain->name,
2154 domain_name, machine_account));
2156 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2157 conn->samr_pipe->desthost,
2158 SEC_FLAG_MAXIMUM_ALLOWED,
2159 &conn->sam_connect_handle);
2160 if (NT_STATUS_IS_OK(result)) {
2163 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2164 "failed for domain %s, error was %s. Trying schannel\n",
2165 domain->name, nt_errstr(result) ));
2166 TALLOC_FREE(conn->samr_pipe);
2170 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2172 result = cm_get_schannel_creds(domain, &p_creds);
2173 if (!NT_STATUS_IS_OK(result)) {
2174 /* If this call fails - conn->cli can now be NULL ! */
2175 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2176 "for domain %s (error %s), trying anon\n",
2178 nt_errstr(result) ));
2181 result = cli_rpc_pipe_open_schannel_with_key
2182 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2183 DCERPC_AUTH_LEVEL_PRIVACY,
2184 domain->name, &p_creds, &conn->samr_pipe);
2186 if (!NT_STATUS_IS_OK(result)) {
2187 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2188 "domain %s using schannel. Error was %s\n",
2189 domain->name, nt_errstr(result) ));
2192 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2193 "schannel.\n", domain->name ));
2195 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2196 conn->samr_pipe->desthost,
2197 SEC_FLAG_MAXIMUM_ALLOWED,
2198 &conn->sam_connect_handle);
2199 if (NT_STATUS_IS_OK(result)) {
2202 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2203 "for domain %s, error was %s. Trying anonymous\n",
2204 domain->name, nt_errstr(result) ));
2205 TALLOC_FREE(conn->samr_pipe);
2209 /* Finally fall back to anonymous. */
2210 result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2213 if (!NT_STATUS_IS_OK(result)) {
2217 result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2218 conn->samr_pipe->desthost,
2219 SEC_FLAG_MAXIMUM_ALLOWED,
2220 &conn->sam_connect_handle);
2221 if (!NT_STATUS_IS_OK(result)) {
2222 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2223 "for domain %s Error was %s\n",
2224 domain->name, nt_errstr(result) ));
2229 result = rpccli_samr_OpenDomain(conn->samr_pipe,
2231 &conn->sam_connect_handle,
2232 SEC_FLAG_MAXIMUM_ALLOWED,
2234 &conn->sam_domain_handle);
2238 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2240 * if we got access denied, we might just have no access rights
2241 * to talk to the remote samr server server (e.g. when we are a
2242 * PDC and we are connecting a w2k8 pdc via an interdomain
2243 * trust). In that case do not invalidate the whole connection
2246 TALLOC_FREE(conn->samr_pipe);
2247 ZERO_STRUCT(conn->sam_domain_handle);
2249 } else if (!NT_STATUS_IS_OK(result)) {
2250 invalidate_cm_connection(conn);
2254 *cli = conn->samr_pipe;
2255 *sam_handle = conn->sam_domain_handle;
2256 SAFE_FREE(machine_password);
2257 SAFE_FREE(machine_account);
2261 /**********************************************************************
2262 open an schanneld ncacn_ip_tcp connection to LSA
2263 ***********************************************************************/
2265 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2266 TALLOC_CTX *mem_ctx,
2267 struct rpc_pipe_client **cli)
2269 struct winbindd_cm_conn *conn;
2270 struct netlogon_creds_CredentialState *creds;
2273 DEBUG(10,("cm_connect_lsa_tcp\n"));
2275 status = init_dc_connection_rpc(domain);
2276 if (!NT_STATUS_IS_OK(status)) {
2280 conn = &domain->conn;
2282 if (conn->lsa_pipe_tcp &&
2283 conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2284 conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2285 rpccli_is_connected(conn->lsa_pipe_tcp)) {
2289 TALLOC_FREE(conn->lsa_pipe_tcp);
2291 status = cm_get_schannel_creds(domain, &creds);
2292 if (!NT_STATUS_IS_OK(status)) {
2296 status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2297 &ndr_table_lsarpc.syntax_id,
2299 DCERPC_AUTH_LEVEL_PRIVACY,
2302 &conn->lsa_pipe_tcp);
2303 if (!NT_STATUS_IS_OK(status)) {
2304 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2305 nt_errstr(status)));
2310 if (!NT_STATUS_IS_OK(status)) {
2311 TALLOC_FREE(conn->lsa_pipe_tcp);
2315 *cli = conn->lsa_pipe_tcp;
2320 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2321 struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2323 struct winbindd_cm_conn *conn;
2324 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2325 struct netlogon_creds_CredentialState *p_creds;
2327 result = init_dc_connection_rpc(domain);
2328 if (!NT_STATUS_IS_OK(result))
2331 conn = &domain->conn;
2333 if (rpccli_is_connected(conn->lsa_pipe)) {
2337 TALLOC_FREE(conn->lsa_pipe);
2339 if ((conn->cli->user_name[0] == '\0') ||
2340 (conn->cli->domain[0] == '\0') ||
2341 (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2342 DEBUG(10, ("cm_connect_lsa: No no user available for "
2343 "domain %s, trying schannel\n", conn->cli->domain));
2347 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2348 * authenticated LSA pipe with sign & seal. */
2349 result = cli_rpc_pipe_open_spnego_ntlmssp
2350 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2351 DCERPC_AUTH_LEVEL_PRIVACY,
2352 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2355 if (!NT_STATUS_IS_OK(result)) {
2356 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2357 "domain %s using NTLMSSP authenticated pipe: user "
2358 "%s\\%s. Error was %s. Trying schannel.\n",
2359 domain->name, conn->cli->domain,
2360 conn->cli->user_name, nt_errstr(result)));
2364 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2365 "NTLMSSP authenticated pipe: user %s\\%s\n",
2366 domain->name, conn->cli->domain, conn->cli->user_name ));
2368 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2369 SEC_FLAG_MAXIMUM_ALLOWED,
2371 if (NT_STATUS_IS_OK(result)) {
2375 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2378 TALLOC_FREE(conn->lsa_pipe);
2382 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2384 result = cm_get_schannel_creds(domain, &p_creds);
2385 if (!NT_STATUS_IS_OK(result)) {
2386 /* If this call fails - conn->cli can now be NULL ! */
2387 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2388 "for domain %s (error %s), trying anon\n",
2390 nt_errstr(result) ));
2393 result = cli_rpc_pipe_open_schannel_with_key
2394 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2395 DCERPC_AUTH_LEVEL_PRIVACY,
2396 domain->name, &p_creds, &conn->lsa_pipe);
2398 if (!NT_STATUS_IS_OK(result)) {
2399 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2400 "domain %s using schannel. Error was %s\n",
2401 domain->name, nt_errstr(result) ));
2404 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2405 "schannel.\n", domain->name ));
2407 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2408 SEC_FLAG_MAXIMUM_ALLOWED,
2410 if (NT_STATUS_IS_OK(result)) {
2414 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2417 TALLOC_FREE(conn->lsa_pipe);
2421 result = cli_rpc_pipe_open_noauth(conn->cli,
2422 &ndr_table_lsarpc.syntax_id,
2424 if (!NT_STATUS_IS_OK(result)) {
2425 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2429 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2430 SEC_FLAG_MAXIMUM_ALLOWED,
2433 if (!NT_STATUS_IS_OK(result)) {
2434 invalidate_cm_connection(conn);
2438 *cli = conn->lsa_pipe;
2439 *lsa_policy = conn->lsa_policy;
2443 /****************************************************************************
2444 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2445 session key stored in conn->netlogon_pipe->dc->sess_key.
2446 ****************************************************************************/
2448 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2449 struct rpc_pipe_client **cli)
2451 struct winbindd_cm_conn *conn;
2454 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2456 enum netr_SchannelType sec_chan_type;
2457 const char *account_name;
2458 struct rpc_pipe_client *netlogon_pipe = NULL;
2462 result = init_dc_connection_rpc(domain);
2463 if (!NT_STATUS_IS_OK(result)) {
2467 conn = &domain->conn;
2469 if (rpccli_is_connected(conn->netlogon_pipe)) {
2470 *cli = conn->netlogon_pipe;
2471 return NT_STATUS_OK;
2474 TALLOC_FREE(conn->netlogon_pipe);
2476 result = cli_rpc_pipe_open_noauth(conn->cli,
2477 &ndr_table_netlogon.syntax_id,
2479 if (!NT_STATUS_IS_OK(result)) {
2483 if ((!IS_DC) && (!domain->primary)) {
2484 /* Clear the schannel request bit and drop down */
2485 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2489 if (lp_client_schannel() != False) {
2490 neg_flags |= NETLOGON_NEG_SCHANNEL;
2493 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2496 TALLOC_FREE(netlogon_pipe);
2497 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2500 result = rpccli_netlogon_setup_creds(
2502 domain->dcname, /* server name. */
2503 domain->name, /* domain name */
2504 global_myname(), /* client name */
2505 account_name, /* machine account */
2506 mach_pwd, /* machine password */
2507 sec_chan_type, /* from get_trust_pw */
2510 if (!NT_STATUS_IS_OK(result)) {
2511 TALLOC_FREE(netlogon_pipe);
2515 if ((lp_client_schannel() == True) &&
2516 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2517 DEBUG(3, ("Server did not offer schannel\n"));
2518 TALLOC_FREE(netlogon_pipe);
2519 return NT_STATUS_ACCESS_DENIED;
2523 if ((lp_client_schannel() == False) ||
2524 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2526 * NetSamLogonEx only works for schannel
2528 domain->can_do_samlogon_ex = False;
2530 /* We're done - just keep the existing connection to NETLOGON
2532 conn->netlogon_pipe = netlogon_pipe;
2533 *cli = conn->netlogon_pipe;
2534 return NT_STATUS_OK;
2537 /* Using the credentials from the first pipe, open a signed and sealed
2538 second netlogon pipe. The session key is stored in the schannel
2539 part of the new pipe auth struct.
2542 result = cli_rpc_pipe_open_schannel_with_key(
2543 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2544 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2545 &conn->netlogon_pipe);
2547 /* We can now close the initial netlogon pipe. */
2548 TALLOC_FREE(netlogon_pipe);
2550 if (!NT_STATUS_IS_OK(result)) {
2551 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2552 "was %s\n", nt_errstr(result)));
2554 invalidate_cm_connection(conn);
2559 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2560 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2561 * supported). We used to only try SamLogonEx for AD, but
2562 * Samba DCs can also do it. And because we don't distinguish
2563 * between Samba and NT4, always try it once.
2565 domain->can_do_samlogon_ex = true;
2567 *cli = conn->netlogon_pipe;
2568 return NT_STATUS_OK;