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
65 #define DBGC_CLASS DBGC_WINBIND
69 struct sockaddr_storage ss;
72 extern struct winbindd_methods reconnect_methods;
73 extern bool override_logfile;
75 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
76 static void set_dc_type_and_flags( struct winbindd_domain *domain );
77 static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
78 struct dc_name_ip **dcs, int *num_dcs);
80 /****************************************************************
81 Child failed to find DC's. Reschedule check.
82 ****************************************************************/
84 static void msg_failed_to_go_online(struct messaging_context *msg,
87 struct server_id server_id,
90 struct winbindd_domain *domain;
91 const char *domainname = (const char *)data->data;
93 if (data->data == NULL || data->length == 0) {
97 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
99 for (domain = domain_list(); domain; domain = domain->next) {
100 if (domain->internal) {
104 if (strequal(domain->name, domainname)) {
105 if (domain->online) {
106 /* We're already online, ignore. */
107 DEBUG(5,("msg_fail_to_go_online: domain %s "
108 "already online.\n", domainname));
112 /* Reschedule the online check. */
113 set_domain_offline(domain);
119 /****************************************************************
120 Actually cause a reconnect from a message.
121 ****************************************************************/
123 static void msg_try_to_go_online(struct messaging_context *msg,
126 struct server_id server_id,
129 struct winbindd_domain *domain;
130 const char *domainname = (const char *)data->data;
132 if (data->data == NULL || data->length == 0) {
136 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
138 for (domain = domain_list(); domain; domain = domain->next) {
139 if (domain->internal) {
143 if (strequal(domain->name, domainname)) {
145 if (domain->online) {
146 /* We're already online, ignore. */
147 DEBUG(5,("msg_try_to_go_online: domain %s "
148 "already online.\n", domainname));
152 /* This call takes care of setting the online
153 flag to true if we connected, or re-adding
154 the offline handler if false. Bypasses online
155 check so always does network calls. */
157 init_dc_connection_network(domain);
163 /****************************************************************
164 Fork a child to try and contact a DC. Do this as contacting a
165 DC requires blocking lookups and we don't want to block our
167 ****************************************************************/
169 static bool fork_child_dc_connect(struct winbindd_domain *domain)
171 struct dc_name_ip *dcs = NULL;
173 TALLOC_CTX *mem_ctx = NULL;
175 pid_t parent_pid = sys_getpid();
180 child_pid = sys_fork();
182 if (child_pid == -1) {
183 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
187 if (child_pid != 0) {
189 messaging_register(winbind_messaging_context(), NULL,
190 MSG_WINBIND_TRY_TO_GO_ONLINE,
191 msg_try_to_go_online);
192 messaging_register(winbind_messaging_context(), NULL,
193 MSG_WINBIND_FAILED_TO_GO_ONLINE,
194 msg_failed_to_go_online);
200 /* Leave messages blocked - we will never process one. */
202 /* tdb needs special fork handling */
203 if (tdb_reopen_all(1) == -1) {
204 DEBUG(0,("tdb_reopen_all failed.\n"));
208 close_conns_after_fork();
210 if (!override_logfile) {
212 if (asprintf(&logfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) > 0) {
213 lp_set_logfile(logfile);
219 mem_ctx = talloc_init("fork_child_dc_connect");
221 DEBUG(0,("talloc_init failed.\n"));
225 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
226 /* Still offline ? Can't find DC's. */
227 messaging_send_buf(winbind_messaging_context(),
228 pid_to_procid(parent_pid),
229 MSG_WINBIND_FAILED_TO_GO_ONLINE,
230 (uint8 *)domain->name,
231 strlen(domain->name)+1);
235 /* We got a DC. Send a message to our parent to get it to
236 try and do the same. */
238 messaging_send_buf(winbind_messaging_context(),
239 pid_to_procid(parent_pid),
240 MSG_WINBIND_TRY_TO_GO_ONLINE,
241 (uint8 *)domain->name,
242 strlen(domain->name)+1);
246 /****************************************************************
247 Handler triggered if we're offline to try and detect a DC.
248 ****************************************************************/
250 static void check_domain_online_handler(struct event_context *ctx,
251 struct timed_event *te,
252 const struct timeval *now,
255 struct winbindd_domain *domain =
256 (struct winbindd_domain *)private_data;
258 DEBUG(10,("check_domain_online_handler: called for domain "
259 "%s (online = %s)\n", domain->name,
260 domain->online ? "True" : "False" ));
262 TALLOC_FREE(domain->check_online_event);
264 /* Are we still in "startup" mode ? */
266 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
267 /* No longer in "startup" mode. */
268 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
270 domain->startup = False;
273 /* We've been told to stay offline, so stay
276 if (get_global_winbindd_state_offline()) {
277 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
282 /* Fork a child to test if it can contact a DC.
283 If it can then send ourselves a message to
284 cause a reconnect. */
286 fork_child_dc_connect(domain);
289 /****************************************************************
290 If we're still offline setup the timeout check.
291 ****************************************************************/
293 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
295 int wbc = lp_winbind_cache_time();
297 if (domain->startup) {
298 domain->check_online_timeout = 10;
299 } else if (domain->check_online_timeout < wbc) {
300 domain->check_online_timeout = wbc;
304 /****************************************************************
305 Set domain offline and also add handler to put us back online
307 ****************************************************************/
309 void set_domain_offline(struct winbindd_domain *domain)
311 DEBUG(10,("set_domain_offline: called for domain %s\n",
314 TALLOC_FREE(domain->check_online_event);
316 if (domain->internal) {
317 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
322 domain->online = False;
324 /* Offline domains are always initialized. They're
325 re-initialized when they go back online. */
327 domain->initialized = True;
329 /* We only add the timeout handler that checks and
330 allows us to go back online when we've not
331 been told to remain offline. */
333 if (get_global_winbindd_state_offline()) {
334 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
339 /* If we're in statup mode, check again in 10 seconds, not in
340 lp_winbind_cache_time() seconds (which is 5 mins by default). */
342 calc_new_online_timeout_check(domain);
344 domain->check_online_event = event_add_timed(winbind_event_context(),
346 timeval_current_ofs(domain->check_online_timeout,0),
347 "check_domain_online_handler",
348 check_domain_online_handler,
351 /* The above *has* to succeed for winbindd to work. */
352 if (!domain->check_online_event) {
353 smb_panic("set_domain_offline: failed to add online handler");
356 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
359 /* Send an offline message to the idmap child when our
360 primary domain goes offline */
362 if ( domain->primary ) {
363 struct winbindd_child *idmap = idmap_child();
365 if ( idmap->pid != 0 ) {
366 messaging_send_buf(winbind_messaging_context(),
367 pid_to_procid(idmap->pid),
369 (uint8 *)domain->name,
370 strlen(domain->name)+1);
377 /****************************************************************
378 Set domain online - if allowed.
379 ****************************************************************/
381 static void set_domain_online(struct winbindd_domain *domain)
385 DEBUG(10,("set_domain_online: called for domain %s\n",
388 if (domain->internal) {
389 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
394 if (get_global_winbindd_state_offline()) {
395 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
400 winbindd_set_locator_kdc_envs(domain);
402 /* If we are waiting to get a krb5 ticket, trigger immediately. */
404 set_event_dispatch_time(winbind_event_context(),
405 "krb5_ticket_gain_handler", now);
407 /* Ok, we're out of any startup mode now... */
408 domain->startup = False;
410 if (domain->online == False) {
411 /* We were offline - now we're online. We default to
412 using the MS-RPC backend if we started offline,
413 and if we're going online for the first time we
414 should really re-initialize the backends and the
415 checks to see if we're talking to an AD or NT domain.
418 domain->initialized = False;
420 /* 'reconnect_methods' is the MS-RPC backend. */
421 if (domain->backend == &reconnect_methods) {
422 domain->backend = NULL;
426 /* Ensure we have no online timeout checks. */
427 domain->check_online_timeout = 0;
428 TALLOC_FREE(domain->check_online_event);
430 /* Ensure we ignore any pending child messages. */
431 messaging_deregister(winbind_messaging_context(),
432 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
433 messaging_deregister(winbind_messaging_context(),
434 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
436 domain->online = True;
438 /* Send an online message to the idmap child when our
439 primary domain comes online */
441 if ( domain->primary ) {
442 struct winbindd_child *idmap = idmap_child();
444 if ( idmap->pid != 0 ) {
445 messaging_send_buf(winbind_messaging_context(),
446 pid_to_procid(idmap->pid),
448 (uint8 *)domain->name,
449 strlen(domain->name)+1);
456 /****************************************************************
457 Requested to set a domain online.
458 ****************************************************************/
460 void set_domain_online_request(struct winbindd_domain *domain)
464 DEBUG(10,("set_domain_online_request: called for domain %s\n",
467 if (get_global_winbindd_state_offline()) {
468 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
473 /* We've been told it's safe to go online and
474 try and connect to a DC. But I don't believe it
475 because network manager seems to lie.
476 Wait at least 5 seconds. Heuristics suck... */
478 if (!domain->check_online_event) {
479 /* If we've come from being globally offline we
480 don't have a check online event handler set.
481 We need to add one now we're trying to go
484 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
487 domain->check_online_event = event_add_timed(winbind_event_context(),
489 timeval_current_ofs(5, 0),
490 "check_domain_online_handler",
491 check_domain_online_handler,
494 /* The above *has* to succeed for winbindd to work. */
495 if (!domain->check_online_event) {
496 smb_panic("set_domain_online_request: failed to add online handler");
502 /* Go into "startup" mode again. */
503 domain->startup_time = tev.tv_sec;
504 domain->startup = True;
508 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
511 /****************************************************************
512 Add -ve connection cache entries for domain and realm.
513 ****************************************************************/
515 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
519 add_failed_connection_entry(domain->name, server, result);
520 /* If this was the saf name for the last thing we talked to,
522 saf_delete(domain->name);
523 if (*domain->alt_name) {
524 add_failed_connection_entry(domain->alt_name, server, result);
525 saf_delete(domain->alt_name);
527 winbindd_unset_locator_kdc_env(domain);
530 /* Choose between anonymous or authenticated connections. We need to use
531 an authenticated connection if DCs have the RestrictAnonymous registry
532 entry set > 0, or the "Additional restrictions for anonymous
533 connections" set in the win2k Local Security Policy.
535 Caller to free() result in domain, username, password
538 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
540 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
541 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
542 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
544 if (*username && **username) {
546 if (!*domain || !**domain)
547 *domain = smb_xstrdup(lp_workgroup());
549 if (!*password || !**password)
550 *password = smb_xstrdup("");
552 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
553 *domain, *username));
556 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
557 *username = smb_xstrdup("");
558 *domain = smb_xstrdup("");
559 *password = smb_xstrdup("");
563 static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
565 struct sockaddr_storage *dc_ss)
567 struct winbindd_domain *our_domain = NULL;
568 struct rpc_pipe_client *netlogon_pipe = NULL;
572 unsigned int orig_timeout;
576 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
583 if (domain->primary) {
587 our_domain = find_our_domain();
589 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
593 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
594 if (!NT_STATUS_IS_OK(result)) {
595 talloc_destroy(mem_ctx);
599 /* This call can take a long time - allow the server to time out.
600 35 seconds should do it. */
602 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
604 werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
607 /* And restore our original timeout. */
608 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
610 talloc_destroy(mem_ctx);
612 if (!W_ERROR_IS_OK(werr)) {
613 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
618 /* cli_netlogon_getanydcname gives us a name with \\ */
629 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
631 if (!resolve_name(dcname, dc_ss, 0x20)) {
638 /************************************************************************
639 Given a fd with a just-connected TCP connection to a DC, open a connection
641 ************************************************************************/
643 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
645 const char *controller,
646 struct cli_state **cli,
649 char *machine_password, *machine_krb5_principal, *machine_account;
650 char *ipc_username, *ipc_domain, *ipc_password;
654 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
656 struct sockaddr peeraddr;
657 socklen_t peeraddr_len;
659 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
661 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
662 controller, domain->name ));
664 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
667 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
668 SAFE_FREE(machine_password);
669 return NT_STATUS_NO_MEMORY;
672 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
674 SAFE_FREE(machine_account);
675 SAFE_FREE(machine_password);
676 return NT_STATUS_NO_MEMORY;
679 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
683 got_mutex = secrets_named_mutex(controller,
684 WINBIND_SERVER_MUTEX_WAIT_TIME);
687 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
689 result = NT_STATUS_POSSIBLE_DEADLOCK;
693 if ((*cli = cli_initialise()) == NULL) {
694 DEBUG(1, ("Could not cli_initialize\n"));
695 result = NT_STATUS_NO_MEMORY;
699 (*cli)->timeout = 10000; /* 10 seconds */
701 fstrcpy((*cli)->desthost, controller);
702 (*cli)->use_kerberos = True;
704 peeraddr_len = sizeof(peeraddr);
706 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
707 (peeraddr_len != sizeof(struct sockaddr_in)) ||
708 (peeraddr_in->sin_family != PF_INET))
710 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
711 result = NT_STATUS_UNSUCCESSFUL;
715 if (ntohs(peeraddr_in->sin_port) == 139) {
716 struct nmb_name calling;
717 struct nmb_name called;
719 make_nmb_name(&calling, global_myname(), 0x0);
720 make_nmb_name(&called, "*SMBSERVER", 0x20);
722 if (!cli_session_request(*cli, &calling, &called)) {
723 DEBUG(8, ("cli_session_request failed for %s\n",
725 result = NT_STATUS_UNSUCCESSFUL;
730 cli_setup_signing_state(*cli, Undefined);
732 if (!cli_negprot(*cli)) {
733 DEBUG(1, ("cli_negprot failed\n"));
734 result = NT_STATUS_UNSUCCESSFUL;
738 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
739 ADS_STATUS ads_status;
741 if (lp_security() == SEC_ADS) {
743 /* Try a krb5 session */
745 (*cli)->use_kerberos = True;
746 DEBUG(5, ("connecting to %s from %s with kerberos principal "
747 "[%s]\n", controller, global_myname(),
748 machine_krb5_principal));
750 winbindd_set_locator_kdc_envs(domain);
752 ads_status = cli_session_setup_spnego(*cli,
753 machine_krb5_principal,
757 if (!ADS_ERR_OK(ads_status)) {
758 DEBUG(4,("failed kerberos session setup with %s\n",
759 ads_errstr(ads_status)));
762 result = ads_ntstatus(ads_status);
763 if (NT_STATUS_IS_OK(result)) {
764 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
765 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
766 goto session_setup_done;
770 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
771 (*cli)->use_kerberos = False;
773 DEBUG(5, ("connecting to %s from %s with username "
774 "[%s]\\[%s]\n", controller, global_myname(),
775 lp_workgroup(), machine_account));
777 ads_status = cli_session_setup_spnego(*cli,
781 if (!ADS_ERR_OK(ads_status)) {
782 DEBUG(4, ("authenticated session setup failed with %s\n",
783 ads_errstr(ads_status)));
786 result = ads_ntstatus(ads_status);
787 if (NT_STATUS_IS_OK(result)) {
788 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
789 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
790 goto session_setup_done;
794 /* Fall back to non-kerberos session setup */
796 (*cli)->use_kerberos = False;
798 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
799 (strlen(ipc_username) > 0)) {
801 /* Only try authenticated if we have a username */
803 DEBUG(5, ("connecting to %s from %s with username "
804 "[%s]\\[%s]\n", controller, global_myname(),
805 ipc_domain, ipc_username));
807 if (NT_STATUS_IS_OK(cli_session_setup(
809 ipc_password, strlen(ipc_password)+1,
810 ipc_password, strlen(ipc_password)+1,
812 /* Successful logon with given username. */
813 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
814 goto session_setup_done;
816 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
817 ipc_domain, ipc_username ));
821 /* Fall back to anonymous connection, this might fail later */
823 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
825 DEBUG(5, ("Connected anonymously\n"));
826 cli_init_creds(*cli, "", "", "");
827 goto session_setup_done;
830 result = cli_nt_error(*cli);
832 if (NT_STATUS_IS_OK(result))
833 result = NT_STATUS_UNSUCCESSFUL;
835 /* We can't session setup */
841 /* cache the server name for later connections */
843 saf_store( domain->name, (*cli)->desthost );
844 if (domain->alt_name && (*cli)->use_kerberos) {
845 saf_store( domain->alt_name, (*cli)->desthost );
848 winbindd_set_locator_kdc_envs(domain);
850 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
852 result = cli_nt_error(*cli);
854 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
856 if (NT_STATUS_IS_OK(result))
857 result = NT_STATUS_UNSUCCESSFUL;
862 secrets_named_mutex_release(controller);
866 /* set the domain if empty; needed for schannel connections */
867 if ( !*(*cli)->domain ) {
868 fstrcpy( (*cli)->domain, domain->name );
871 result = NT_STATUS_OK;
875 secrets_named_mutex_release(controller);
878 SAFE_FREE(machine_account);
879 SAFE_FREE(machine_password);
880 SAFE_FREE(machine_krb5_principal);
881 SAFE_FREE(ipc_username);
882 SAFE_FREE(ipc_domain);
883 SAFE_FREE(ipc_password);
885 if (!NT_STATUS_IS_OK(result)) {
886 winbind_add_failed_connection_entry(domain, controller, result);
887 if ((*cli) != NULL) {
896 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
897 const char *dcname, struct sockaddr_storage *pss,
898 struct dc_name_ip **dcs, int *num)
900 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
901 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
905 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
910 fstrcpy((*dcs)[*num].name, dcname);
911 (*dcs)[*num].ss = *pss;
916 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
917 struct sockaddr_storage *pss, uint16 port,
918 struct sockaddr_storage **addrs, int *num)
920 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
922 if (*addrs == NULL) {
927 (*addrs)[*num] = *pss;
928 set_sockaddr_port(&(*addrs)[*num], port);
934 static void mailslot_name(struct in_addr dc_ip, fstring name)
936 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
939 static bool send_getdc_request(struct sockaddr_storage *dc_ss,
940 const char *domain_name,
944 struct in_addr dc_ip;
946 fstring my_acct_name;
949 if (dc_ss->ss_family != AF_INET) {
953 dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
954 mailslot_name(dc_ip, my_mailslot);
956 memset(outbuf, '\0', sizeof(outbuf));
960 SCVAL(p, 0, SAMLOGON);
963 SCVAL(p, 0, 0); /* Count pointer ... */
966 SIVAL(p, 0, 0); /* The sender's token ... */
969 p += dos_PutUniCode(p, global_myname(),
970 sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
971 fstr_sprintf(my_acct_name, "%s$", global_myname());
972 p += dos_PutUniCode(p, my_acct_name,
973 sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
975 if (strlen(my_mailslot)+1 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
979 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
980 p += strlen(my_mailslot)+1;
982 if (sizeof(outbuf) - PTR_DIFF(p, outbuf) < 8) {
989 SIVAL(p, 0, sid_size(sid));
992 p = ALIGN4(p, outbuf);
993 if (PTR_DIFF(p, outbuf) > sizeof(outbuf)) {
997 sid_linearize(p, sid_size(sid), sid);
998 if (sid_size(sid) + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
1005 SSVAL(p, 4, 0xffff);
1006 SSVAL(p, 6, 0xffff);
1009 return cli_send_mailslot(winbind_messaging_context(),
1010 False, "\\MAILSLOT\\NET\\NTLOGON", 0,
1011 outbuf, PTR_DIFF(p, outbuf),
1012 global_myname(), 0, domain_name, 0x1c,
1016 static bool receive_getdc_response(struct sockaddr_storage *dc_ss,
1017 const char *domain_name,
1020 struct packet_struct *packet;
1021 fstring my_mailslot;
1023 fstring dcname, user, domain;
1025 struct in_addr dc_ip;
1027 if (dc_ss->ss_family != AF_INET) {
1030 dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
1031 mailslot_name(dc_ip, my_mailslot);
1033 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
1035 if (packet == NULL) {
1036 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
1040 DEBUG(5, ("Received packet for %s\n", my_mailslot));
1042 buf = packet->packet.dgram.data;
1043 len = packet->packet.dgram.datasize;
1046 /* 70 is a completely arbitrary value to make sure
1047 the SVAL below does not read uninitialized memory */
1048 DEBUG(3, ("GetDC got short response\n"));
1052 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1053 p = buf+SVAL(buf, smb_vwv10);
1055 if (CVAL(p,0) != SAMLOGON_R) {
1056 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
1061 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1062 STR_TERMINATE|STR_NOALIGN);
1063 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1064 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1065 STR_TERMINATE|STR_NOALIGN);
1066 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1067 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1068 STR_TERMINATE|STR_NOALIGN);
1069 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1071 if (!strequal(domain, domain_name)) {
1072 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1073 domain_name, domain));
1078 if (*p == '\\') p += 1;
1079 if (*p == '\\') p += 1;
1081 fstrcpy(dc_name, p);
1083 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1089 /*******************************************************************
1090 convert an ip to a name
1091 *******************************************************************/
1093 static bool dcip_to_name(const struct winbindd_domain *domain,
1094 struct sockaddr_storage *pss,
1097 struct ip_service ip_list;
1103 /* For active directory servers, try to get the ldap server name.
1104 None of these failures should be considered critical for now */
1106 if (lp_security() == SEC_ADS) {
1108 char addr[INET6_ADDRSTRLEN];
1110 print_sockaddr(addr, sizeof(addr), pss);
1112 ads = ads_init(domain->alt_name, domain->name, NULL);
1113 ads->auth.flags |= ADS_AUTH_NO_BIND;
1115 if (ads_try_connect(ads, addr)) {
1116 /* We got a cldap packet. */
1117 fstrcpy(name, ads->config.ldap_server_name);
1118 namecache_store(name, 0x20, 1, &ip_list);
1120 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1122 if (domain->primary && (ads->config.flags & ADS_KDC)) {
1123 if (ads_closest_dc(ads)) {
1124 char *sitename = sitename_fetch(ads->config.realm);
1126 /* We're going to use this KDC for this realm/domain.
1127 If we are using sites, then force the krb5 libs
1130 create_local_private_krb5_conf_for_domain(domain->alt_name,
1135 SAFE_FREE(sitename);
1137 /* use an off site KDC */
1138 create_local_private_krb5_conf_for_domain(domain->alt_name,
1143 winbindd_set_locator_kdc_envs(domain);
1145 /* Ensure we contact this DC also. */
1146 saf_store( domain->name, name);
1147 saf_store( domain->alt_name, name);
1150 ads_destroy( &ads );
1154 ads_destroy( &ads );
1158 /* try GETDC requests next */
1160 if (send_getdc_request(pss, domain->name, &domain->sid)) {
1163 for (i=0; i<5; i++) {
1164 if (receive_getdc_response(pss, domain->name, name)) {
1165 namecache_store(name, 0x20, 1, &ip_list);
1172 /* try node status request */
1174 if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1175 namecache_store(name, 0x20, 1, &ip_list);
1181 /*******************************************************************
1182 Retreive a list of IP address for domain controllers. Fill in
1183 the dcs[] with results.
1184 *******************************************************************/
1186 static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1187 struct dc_name_ip **dcs, int *num_dcs)
1190 struct sockaddr_storage ss;
1191 struct ip_service *ip_list = NULL;
1192 int iplist_size = 0;
1195 enum security_types sec = (enum security_types)lp_security();
1197 is_our_domain = strequal(domain->name, lp_workgroup());
1200 && get_dc_name_via_netlogon(domain, dcname, &ss)
1201 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs, num_dcs) )
1203 char addr[INET6_ADDRSTRLEN];
1204 print_sockaddr(addr, sizeof(addr), &ss);
1205 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1210 if (sec == SEC_ADS) {
1211 char *sitename = NULL;
1213 /* We need to make sure we know the local site before
1214 doing any DNS queries, as this will restrict the
1215 get_sorted_dc_list() call below to only fetching
1216 DNS records for the correct site. */
1218 /* Find any DC to get the site record.
1219 We deliberately don't care about the
1222 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1224 sitename = sitename_fetch(domain->alt_name);
1227 /* Do the site-specific AD dns lookup first. */
1228 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1230 for ( i=0; i<iplist_size; i++ ) {
1231 char addr[INET6_ADDRSTRLEN];
1232 print_sockaddr(addr, sizeof(addr),
1234 add_one_dc_unique(mem_ctx,
1243 SAFE_FREE(sitename);
1247 /* Now we add DCs from the main AD dns lookup. */
1248 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1250 for ( i=0; i<iplist_size; i++ ) {
1251 char addr[INET6_ADDRSTRLEN];
1252 print_sockaddr(addr, sizeof(addr),
1254 add_one_dc_unique(mem_ctx,
1263 /* try standard netbios queries if no ADS */
1265 if (iplist_size==0) {
1266 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1269 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1271 /* now add to the dc array. We'll wait until the last minute
1272 to look up the name of the DC. But we fill in the char* for
1273 the ip now in to make the failed connection cache work */
1275 for ( i=0; i<iplist_size; i++ ) {
1276 char addr[INET6_ADDRSTRLEN];
1277 print_sockaddr(addr, sizeof(addr),
1279 add_one_dc_unique(mem_ctx, domain->name, addr,
1280 &ip_list[i].ss, dcs, num_dcs);
1283 SAFE_FREE( ip_list );
1288 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1289 const struct winbindd_domain *domain,
1290 fstring dcname, struct sockaddr_storage *pss, int *fd)
1292 struct dc_name_ip *dcs = NULL;
1295 const char **dcnames = NULL;
1296 int num_dcnames = 0;
1298 struct sockaddr_storage *addrs = NULL;
1304 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1307 for (i=0; i<num_dcs; i++) {
1309 if (!add_string_to_array(mem_ctx, dcs[i].name,
1310 &dcnames, &num_dcnames)) {
1313 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1314 &addrs, &num_addrs)) {
1318 if (!add_string_to_array(mem_ctx, dcs[i].name,
1319 &dcnames, &num_dcnames)) {
1322 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1323 &addrs, &num_addrs)) {
1328 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1331 if ((addrs == NULL) || (dcnames == NULL))
1334 /* 5 second timeout. */
1335 if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1336 for (i=0; i<num_dcs; i++) {
1337 char ab[INET6_ADDRSTRLEN];
1338 print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1339 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1340 "domain %s address %s. Error was %s\n",
1341 domain->name, ab, strerror(errno) ));
1342 winbind_add_failed_connection_entry(domain,
1343 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1348 *pss = addrs[fd_index];
1350 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1351 /* Ok, we've got a name for the DC */
1352 fstrcpy(dcname, dcnames[fd_index]);
1356 /* Try to figure out the name */
1357 if (dcip_to_name(domain, pss, dcname)) {
1361 /* We can not continue without the DC's name */
1362 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1363 NT_STATUS_UNSUCCESSFUL);
1367 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1368 struct winbindd_cm_conn *new_conn)
1370 TALLOC_CTX *mem_ctx;
1372 char *saf_servername = saf_fetch( domain->name );
1375 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1376 SAFE_FREE(saf_servername);
1377 set_domain_offline(domain);
1378 return NT_STATUS_NO_MEMORY;
1381 /* we have to check the server affinity cache here since
1382 later we selecte a DC based on response time and not preference */
1384 /* Check the negative connection cache
1385 before talking to it. It going down may have
1386 triggered the reconnection. */
1388 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1390 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1391 saf_servername, domain->name ));
1393 /* convert an ip address to a name */
1394 if (is_ipaddress( saf_servername ) ) {
1396 struct sockaddr_storage ss;
1398 if (!interpret_string_addr(&ss, saf_servername,
1400 return NT_STATUS_UNSUCCESSFUL;
1402 if (dcip_to_name( domain, &ss, saf_name )) {
1403 fstrcpy( domain->dcname, saf_name );
1405 winbind_add_failed_connection_entry(
1406 domain, saf_servername,
1407 NT_STATUS_UNSUCCESSFUL);
1410 fstrcpy( domain->dcname, saf_servername );
1413 SAFE_FREE( saf_servername );
1416 for (retries = 0; retries < 3; retries++) {
1420 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1422 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1423 domain->dcname, domain->name ));
1426 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1427 && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1429 struct sockaddr_storage *addrs = NULL;
1433 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1434 set_domain_offline(domain);
1435 talloc_destroy(mem_ctx);
1436 return NT_STATUS_NO_MEMORY;
1438 if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1439 set_domain_offline(domain);
1440 talloc_destroy(mem_ctx);
1441 return NT_STATUS_NO_MEMORY;
1444 /* 5 second timeout. */
1445 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1451 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1453 /* This is the one place where we will
1454 set the global winbindd offline state
1455 to true, if a "WINBINDD_OFFLINE" entry
1456 is found in the winbindd cache. */
1457 set_global_winbindd_state_offline();
1461 new_conn->cli = NULL;
1463 result = cm_prepare_connection(domain, fd, domain->dcname,
1464 &new_conn->cli, &retry);
1470 if (NT_STATUS_IS_OK(result)) {
1472 winbindd_set_locator_kdc_envs(domain);
1474 if (domain->online == False) {
1475 /* We're changing state from offline to online. */
1476 set_global_winbindd_state_online();
1478 set_domain_online(domain);
1480 /* Ensure we setup the retry handler. */
1481 set_domain_offline(domain);
1484 talloc_destroy(mem_ctx);
1488 /* Close down all open pipes on a connection. */
1490 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1492 /* We're closing down a possibly dead
1493 connection. Don't have impossibly long (10s) timeouts. */
1496 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1499 if (conn->samr_pipe != NULL) {
1500 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1501 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1503 cli_set_timeout(conn->cli, 500);
1506 conn->samr_pipe = NULL;
1509 if (conn->lsa_pipe != NULL) {
1510 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1511 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1513 cli_set_timeout(conn->cli, 500);
1516 conn->lsa_pipe = NULL;
1519 if (conn->netlogon_pipe != NULL) {
1520 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1521 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1523 cli_set_timeout(conn->cli, 500);
1526 conn->netlogon_pipe = NULL;
1530 cli_shutdown(conn->cli);
1536 void close_conns_after_fork(void)
1538 struct winbindd_domain *domain;
1540 for (domain = domain_list(); domain; domain = domain->next) {
1541 if (domain->conn.cli == NULL)
1544 if (domain->conn.cli->fd == -1)
1547 close(domain->conn.cli->fd);
1548 domain->conn.cli->fd = -1;
1552 static bool connection_ok(struct winbindd_domain *domain)
1554 if (domain->conn.cli == NULL) {
1555 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1556 "cli!\n", domain->dcname, domain->name));
1560 if (!domain->conn.cli->initialised) {
1561 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1562 "initialised!\n", domain->dcname, domain->name));
1566 if (domain->conn.cli->fd == -1) {
1567 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1568 "never started (fd == -1)\n",
1569 domain->dcname, domain->name));
1573 if (domain->online == False) {
1574 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1581 /* Initialize a new connection up to the RPC BIND.
1582 Bypass online status check so always does network calls. */
1584 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1588 /* Internal connections never use the network. */
1589 if (domain->internal) {
1590 domain->initialized = True;
1591 return NT_STATUS_OK;
1594 if (connection_ok(domain)) {
1595 if (!domain->initialized) {
1596 set_dc_type_and_flags(domain);
1598 return NT_STATUS_OK;
1601 invalidate_cm_connection(&domain->conn);
1603 result = cm_open_connection(domain, &domain->conn);
1605 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1606 set_dc_type_and_flags(domain);
1612 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1614 if (domain->initialized && !domain->online) {
1615 /* We check for online status elsewhere. */
1616 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1619 return init_dc_connection_network(domain);
1622 /******************************************************************************
1623 Set the trust flags (direction and forest location) for a domain
1624 ******************************************************************************/
1626 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1628 struct winbindd_domain *our_domain;
1629 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1630 struct ds_domain_trust *domains = NULL;
1633 uint32 flags = (DS_DOMAIN_IN_FOREST |
1634 DS_DOMAIN_DIRECT_OUTBOUND |
1635 DS_DOMAIN_DIRECT_INBOUND);
1636 struct rpc_pipe_client *cli;
1637 TALLOC_CTX *mem_ctx = NULL;
1639 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1641 /* Our primary domain doesn't need to worry about trust flags.
1642 Force it to go through the network setup */
1643 if ( domain->primary ) {
1647 our_domain = find_our_domain();
1649 if ( !connection_ok(our_domain) ) {
1650 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1654 /* This won't work unless our domain is AD */
1656 if ( !our_domain->active_directory ) {
1660 /* Use DsEnumerateDomainTrusts to get us the trust direction
1663 result = cm_connect_netlogon(our_domain, &cli);
1665 if (!NT_STATUS_IS_OK(result)) {
1666 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1667 "a connection to %s for PIPE_NETLOGON (%s)\n",
1668 domain->name, nt_errstr(result)));
1672 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1673 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1677 result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
1680 (unsigned int *)&count);
1682 /* Now find the domain name and get the flags */
1684 for ( i=0; i<count; i++ ) {
1685 if ( strequal( domain->name, domains[i].netbios_domain ) ) {
1686 domain->domain_flags = domains[i].flags;
1687 domain->domain_type = domains[i].trust_type;
1688 domain->domain_trust_attribs = domains[i].trust_attributes;
1690 if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
1691 domain->active_directory = True;
1693 /* This flag is only set if the domain is *our*
1694 primary domain and the primary domain is in
1697 domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
1699 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1700 "native mode.\n", domain->name,
1701 domain->native_mode ? "" : "NOT "));
1703 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1704 "running active directory.\n", domain->name,
1705 domain->active_directory ? "" : "NOT "));
1708 domain->initialized = True;
1710 if ( !winbindd_can_contact_domain( domain) )
1711 domain->internal = True;
1717 talloc_destroy( mem_ctx );
1719 return domain->initialized;
1722 /******************************************************************************
1723 We can 'sense' certain things about the DC by it's replies to certain
1726 This tells us if this particular remote server is Active Directory, and if it
1728 ******************************************************************************/
1730 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1734 TALLOC_CTX *mem_ctx = NULL;
1735 struct rpc_pipe_client *cli;
1738 char *domain_name = NULL;
1739 char *dns_name = NULL;
1740 char *forest_name = NULL;
1741 DOM_SID *dom_sid = NULL;
1745 if (!connection_ok(domain)) {
1749 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1752 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1756 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1758 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1762 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1763 "PI_LSARPC_DS on domain %s: (%s)\n",
1764 domain->name, nt_errstr(result)));
1766 /* if this is just a non-AD domain we need to continue
1767 * identifying so that we can in the end return with
1768 * domain->initialized = True - gd */
1773 result = rpccli_ds_getprimarydominfo(cli, mem_ctx,
1774 DsRolePrimaryDomainInfoBasic,
1776 cli_rpc_pipe_close(cli);
1778 if (!NT_STATUS_IS_OK(result)) {
1779 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1780 "on domain %s failed: (%s)\n",
1781 domain->name, nt_errstr(result)));
1783 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1784 * every opcode on the LSARPC_DS pipe, continue with
1785 * no_lsarpc_ds mode here as well to get domain->initialized
1788 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1792 TALLOC_FREE(mem_ctx);
1796 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1797 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1798 domain->native_mode = True;
1800 domain->native_mode = False;
1804 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1807 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1808 "PI_LSARPC on domain %s: (%s)\n",
1809 domain->name, nt_errstr(result)));
1810 cli_rpc_pipe_close(cli);
1811 TALLOC_FREE(mem_ctx);
1815 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1816 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1818 if (NT_STATUS_IS_OK(result)) {
1819 /* This particular query is exactly what Win2k clients use
1820 to determine that the DC is active directory */
1821 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1823 &dns_name, &forest_name,
1827 if (NT_STATUS_IS_OK(result)) {
1828 domain->active_directory = True;
1831 fstrcpy(domain->name, domain_name);
1834 fstrcpy(domain->alt_name, dns_name);
1837 fstrcpy(domain->forest_name, forest_name);
1840 sid_copy(&domain->sid, dom_sid);
1842 domain->active_directory = False;
1844 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1845 SEC_RIGHTS_MAXIMUM_ALLOWED,
1848 if (!NT_STATUS_IS_OK(result))
1851 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1852 &pol, 5, &domain_name,
1855 if (NT_STATUS_IS_OK(result)) {
1857 fstrcpy(domain->name, domain_name);
1860 sid_copy(&domain->sid, dom_sid);
1865 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1866 domain->name, domain->native_mode ? "" : "NOT "));
1868 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1869 domain->name, domain->active_directory ? "" : "NOT "));
1871 cli_rpc_pipe_close(cli);
1873 TALLOC_FREE(mem_ctx);
1875 domain->initialized = True;
1878 /**********************************************************************
1879 Set the domain_flags (trust attributes, domain operating modes, etc...
1880 ***********************************************************************/
1882 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1884 /* we always have to contact our primary domain */
1886 if ( domain->primary ) {
1887 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1888 "primary domain\n"));
1889 set_dc_type_and_flags_connect( domain );
1893 /* Use our DC to get the information if possible */
1895 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1896 /* Otherwise, fallback to contacting the
1898 set_dc_type_and_flags_connect( domain );
1906 /**********************************************************************
1907 ***********************************************************************/
1909 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1910 struct dcinfo **ppdc)
1913 struct rpc_pipe_client *netlogon_pipe;
1915 if (lp_client_schannel() == False) {
1919 result = cm_connect_netlogon(domain, &netlogon_pipe);
1920 if (!NT_STATUS_IS_OK(result)) {
1924 /* Return a pointer to the struct dcinfo from the
1927 *ppdc = domain->conn.netlogon_pipe->dc;
1931 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1932 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1934 struct winbindd_cm_conn *conn;
1935 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1937 struct dcinfo *p_dcinfo;
1939 result = init_dc_connection(domain);
1940 if (!NT_STATUS_IS_OK(result)) {
1944 conn = &domain->conn;
1946 if (conn->samr_pipe != NULL) {
1951 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1952 * sign and sealed pipe using the machine account password by
1953 * preference. If we can't - try schannel, if that fails, try
1957 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1958 if ((conn->cli->user_name[0] == '\0') ||
1959 (conn->cli->domain[0] == '\0') ||
1960 (conn_pwd[0] == '\0')) {
1961 DEBUG(10, ("cm_connect_sam: No no user available for "
1962 "domain %s, trying schannel\n", conn->cli->domain));
1966 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1967 authenticated SAMR pipe with sign & seal. */
1969 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1970 PIPE_AUTH_LEVEL_PRIVACY,
1972 conn->cli->user_name,
1975 if (conn->samr_pipe == NULL) {
1976 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1977 "pipe for domain %s using NTLMSSP "
1978 "authenticated pipe: user %s\\%s. Error was "
1979 "%s\n", domain->name, conn->cli->domain,
1980 conn->cli->user_name, nt_errstr(result)));
1984 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1985 "domain %s using NTLMSSP authenticated "
1986 "pipe: user %s\\%s\n", domain->name,
1987 conn->cli->domain, conn->cli->user_name ));
1989 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1990 SEC_RIGHTS_MAXIMUM_ALLOWED,
1991 &conn->sam_connect_handle);
1992 if (NT_STATUS_IS_OK(result)) {
1995 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1996 "failed for domain %s, error was %s. Trying schannel\n",
1997 domain->name, nt_errstr(result) ));
1998 cli_rpc_pipe_close(conn->samr_pipe);
2002 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2004 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2005 /* If this call fails - conn->cli can now be NULL ! */
2006 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2007 "for domain %s, trying anon\n", domain->name));
2010 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
2011 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
2012 domain->name, p_dcinfo, &result);
2014 if (conn->samr_pipe == NULL) {
2015 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2016 "domain %s using schannel. Error was %s\n",
2017 domain->name, nt_errstr(result) ));
2020 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2021 "schannel.\n", domain->name ));
2023 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
2024 SEC_RIGHTS_MAXIMUM_ALLOWED,
2025 &conn->sam_connect_handle);
2026 if (NT_STATUS_IS_OK(result)) {
2029 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
2030 "for domain %s, error was %s. Trying anonymous\n",
2031 domain->name, nt_errstr(result) ));
2032 cli_rpc_pipe_close(conn->samr_pipe);
2036 /* Finally fall back to anonymous. */
2037 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
2040 if (conn->samr_pipe == NULL) {
2041 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2045 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
2046 SEC_RIGHTS_MAXIMUM_ALLOWED,
2047 &conn->sam_connect_handle);
2048 if (!NT_STATUS_IS_OK(result)) {
2049 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
2050 "for domain %s Error was %s\n",
2051 domain->name, nt_errstr(result) ));
2056 result = rpccli_samr_open_domain(conn->samr_pipe,
2058 &conn->sam_connect_handle,
2059 SEC_RIGHTS_MAXIMUM_ALLOWED,
2061 &conn->sam_domain_handle);
2065 if (!NT_STATUS_IS_OK(result)) {
2066 invalidate_cm_connection(conn);
2070 *cli = conn->samr_pipe;
2071 *sam_handle = conn->sam_domain_handle;
2075 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2076 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2078 struct winbindd_cm_conn *conn;
2079 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2081 struct dcinfo *p_dcinfo;
2083 result = init_dc_connection(domain);
2084 if (!NT_STATUS_IS_OK(result))
2087 conn = &domain->conn;
2089 if (conn->lsa_pipe != NULL) {
2093 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2094 if ((conn->cli->user_name[0] == '\0') ||
2095 (conn->cli->domain[0] == '\0') ||
2096 (conn_pwd[0] == '\0')) {
2097 DEBUG(10, ("cm_connect_lsa: No no user available for "
2098 "domain %s, trying schannel\n", conn->cli->domain));
2102 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2103 * authenticated LSA pipe with sign & seal. */
2104 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
2105 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2106 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
2108 if (conn->lsa_pipe == NULL) {
2109 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2110 "domain %s using NTLMSSP authenticated pipe: user "
2111 "%s\\%s. Error was %s. Trying schannel.\n",
2112 domain->name, conn->cli->domain,
2113 conn->cli->user_name, nt_errstr(result)));
2117 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2118 "NTLMSSP authenticated pipe: user %s\\%s\n",
2119 domain->name, conn->cli->domain, conn->cli->user_name ));
2121 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2122 SEC_RIGHTS_MAXIMUM_ALLOWED,
2124 if (NT_STATUS_IS_OK(result)) {
2128 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2131 cli_rpc_pipe_close(conn->lsa_pipe);
2135 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2137 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2138 /* If this call fails - conn->cli can now be NULL ! */
2139 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2140 "for domain %s, trying anon\n", domain->name));
2143 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2144 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2145 domain->name, p_dcinfo, &result);
2147 if (conn->lsa_pipe == NULL) {
2148 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2149 "domain %s using schannel. Error was %s\n",
2150 domain->name, nt_errstr(result) ));
2153 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2154 "schannel.\n", domain->name ));
2156 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2157 SEC_RIGHTS_MAXIMUM_ALLOWED,
2159 if (NT_STATUS_IS_OK(result)) {
2163 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2166 cli_rpc_pipe_close(conn->lsa_pipe);
2170 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2172 if (conn->lsa_pipe == NULL) {
2173 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2177 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2178 SEC_RIGHTS_MAXIMUM_ALLOWED,
2181 if (!NT_STATUS_IS_OK(result)) {
2182 invalidate_cm_connection(conn);
2186 *cli = conn->lsa_pipe;
2187 *lsa_policy = conn->lsa_policy;
2191 /****************************************************************************
2192 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2193 session key stored in conn->netlogon_pipe->dc->sess_key.
2194 ****************************************************************************/
2196 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2197 struct rpc_pipe_client **cli)
2199 struct winbindd_cm_conn *conn;
2202 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2204 uint32 sec_chan_type;
2205 const char *account_name;
2206 struct rpc_pipe_client *netlogon_pipe = NULL;
2210 result = init_dc_connection(domain);
2211 if (!NT_STATUS_IS_OK(result)) {
2215 conn = &domain->conn;
2217 if (conn->netlogon_pipe != NULL) {
2218 *cli = conn->netlogon_pipe;
2219 return NT_STATUS_OK;
2222 if ((IS_DC || domain->primary) && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
2223 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2226 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2228 if (netlogon_pipe == NULL) {
2232 if ((!IS_DC) && (!domain->primary)) {
2233 /* Clear the schannel request bit and drop down */
2234 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2238 if (lp_client_schannel() != False) {
2239 neg_flags |= NETLOGON_NEG_SCHANNEL;
2242 /* if we are a DC and this is a trusted domain, then we need to use our
2243 domain name in the net_req_auth2() request */
2246 && !strequal(domain->name, lp_workgroup())
2247 && lp_allow_trusted_domains() )
2249 account_name = lp_workgroup();
2251 account_name = domain->primary ?
2252 global_myname() : domain->name;
2255 if (account_name == NULL) {
2256 cli_rpc_pipe_close(netlogon_pipe);
2257 return NT_STATUS_NO_MEMORY;
2260 result = rpccli_netlogon_setup_creds(
2262 domain->dcname, /* server name. */
2263 domain->name, /* domain name */
2264 global_myname(), /* client name */
2265 account_name, /* machine account */
2266 mach_pwd, /* machine password */
2267 sec_chan_type, /* from get_trust_pw */
2270 if (!NT_STATUS_IS_OK(result)) {
2271 cli_rpc_pipe_close(netlogon_pipe);
2275 if ((lp_client_schannel() == True) &&
2276 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2277 DEBUG(3, ("Server did not offer schannel\n"));
2278 cli_rpc_pipe_close(netlogon_pipe);
2279 return NT_STATUS_ACCESS_DENIED;
2283 if ((lp_client_schannel() == False) ||
2284 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2285 /* We're done - just keep the existing connection to NETLOGON
2287 conn->netlogon_pipe = netlogon_pipe;
2288 *cli = conn->netlogon_pipe;
2289 return NT_STATUS_OK;
2292 /* Using the credentials from the first pipe, open a signed and sealed
2293 second netlogon pipe. The session key is stored in the schannel
2294 part of the new pipe auth struct.
2297 conn->netlogon_pipe =
2298 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2300 PIPE_AUTH_LEVEL_PRIVACY,
2305 /* We can now close the initial netlogon pipe. */
2306 cli_rpc_pipe_close(netlogon_pipe);
2308 if (conn->netlogon_pipe == NULL) {
2309 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2310 "was %s\n", nt_errstr(result)));
2312 /* make sure we return something besides OK */
2313 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2316 *cli = conn->netlogon_pipe;
2317 return NT_STATUS_OK;