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
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 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
213 lp_set_logfile(logfile);
217 mem_ctx = talloc_init("fork_child_dc_connect");
219 DEBUG(0,("talloc_init failed.\n"));
223 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
224 /* Still offline ? Can't find DC's. */
225 messaging_send_buf(winbind_messaging_context(),
226 pid_to_procid(parent_pid),
227 MSG_WINBIND_FAILED_TO_GO_ONLINE,
228 (uint8 *)domain->name,
229 strlen(domain->name)+1);
233 /* We got a DC. Send a message to our parent to get it to
234 try and do the same. */
236 messaging_send_buf(winbind_messaging_context(),
237 pid_to_procid(parent_pid),
238 MSG_WINBIND_TRY_TO_GO_ONLINE,
239 (uint8 *)domain->name,
240 strlen(domain->name)+1);
244 /****************************************************************
245 Handler triggered if we're offline to try and detect a DC.
246 ****************************************************************/
248 static void check_domain_online_handler(struct event_context *ctx,
249 struct timed_event *te,
250 const struct timeval *now,
253 struct winbindd_domain *domain =
254 (struct winbindd_domain *)private_data;
256 DEBUG(10,("check_domain_online_handler: called for domain "
257 "%s (online = %s)\n", domain->name,
258 domain->online ? "True" : "False" ));
260 TALLOC_FREE(domain->check_online_event);
262 /* Are we still in "startup" mode ? */
264 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
265 /* No longer in "startup" mode. */
266 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
268 domain->startup = False;
271 /* We've been told to stay offline, so stay
274 if (get_global_winbindd_state_offline()) {
275 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
280 /* Fork a child to test if it can contact a DC.
281 If it can then send ourselves a message to
282 cause a reconnect. */
284 fork_child_dc_connect(domain);
287 /****************************************************************
288 If we're still offline setup the timeout check.
289 ****************************************************************/
291 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
293 int wbc = lp_winbind_cache_time();
295 if (domain->startup) {
296 domain->check_online_timeout = 10;
297 } else if (domain->check_online_timeout < wbc) {
298 domain->check_online_timeout = wbc;
302 /****************************************************************
303 Set domain offline and also add handler to put us back online
305 ****************************************************************/
307 void set_domain_offline(struct winbindd_domain *domain)
309 DEBUG(10,("set_domain_offline: called for domain %s\n",
312 TALLOC_FREE(domain->check_online_event);
314 if (domain->internal) {
315 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
320 domain->online = False;
322 /* Offline domains are always initialized. They're
323 re-initialized when they go back online. */
325 domain->initialized = True;
327 /* We only add the timeout handler that checks and
328 allows us to go back online when we've not
329 been told to remain offline. */
331 if (get_global_winbindd_state_offline()) {
332 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
337 /* If we're in statup mode, check again in 10 seconds, not in
338 lp_winbind_cache_time() seconds (which is 5 mins by default). */
340 calc_new_online_timeout_check(domain);
342 domain->check_online_event = event_add_timed(winbind_event_context(),
344 timeval_current_ofs(domain->check_online_timeout,0),
345 "check_domain_online_handler",
346 check_domain_online_handler,
349 /* The above *has* to succeed for winbindd to work. */
350 if (!domain->check_online_event) {
351 smb_panic("set_domain_offline: failed to add online handler");
354 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
357 /* Send an offline message to the idmap child when our
358 primary domain goes offline */
360 if ( domain->primary ) {
361 struct winbindd_child *idmap = idmap_child();
363 if ( idmap->pid != 0 ) {
364 messaging_send_buf(winbind_messaging_context(),
365 pid_to_procid(idmap->pid),
367 (uint8 *)domain->name,
368 strlen(domain->name)+1);
375 /****************************************************************
376 Set domain online - if allowed.
377 ****************************************************************/
379 static void set_domain_online(struct winbindd_domain *domain)
383 DEBUG(10,("set_domain_online: called for domain %s\n",
386 if (domain->internal) {
387 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
392 if (get_global_winbindd_state_offline()) {
393 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
398 winbindd_set_locator_kdc_envs(domain);
400 /* If we are waiting to get a krb5 ticket, trigger immediately. */
402 set_event_dispatch_time(winbind_event_context(),
403 "krb5_ticket_gain_handler", now);
405 /* Ok, we're out of any startup mode now... */
406 domain->startup = False;
408 if (domain->online == False) {
409 /* We were offline - now we're online. We default to
410 using the MS-RPC backend if we started offline,
411 and if we're going online for the first time we
412 should really re-initialize the backends and the
413 checks to see if we're talking to an AD or NT domain.
416 domain->initialized = False;
418 /* 'reconnect_methods' is the MS-RPC backend. */
419 if (domain->backend == &reconnect_methods) {
420 domain->backend = NULL;
424 /* Ensure we have no online timeout checks. */
425 domain->check_online_timeout = 0;
426 TALLOC_FREE(domain->check_online_event);
428 /* Ensure we ignore any pending child messages. */
429 messaging_deregister(winbind_messaging_context(),
430 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
431 messaging_deregister(winbind_messaging_context(),
432 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
434 domain->online = True;
436 /* Send an online message to the idmap child when our
437 primary domain comes online */
439 if ( domain->primary ) {
440 struct winbindd_child *idmap = idmap_child();
442 if ( idmap->pid != 0 ) {
443 messaging_send_buf(winbind_messaging_context(),
444 pid_to_procid(idmap->pid),
446 (uint8 *)domain->name,
447 strlen(domain->name)+1);
454 /****************************************************************
455 Requested to set a domain online.
456 ****************************************************************/
458 void set_domain_online_request(struct winbindd_domain *domain)
462 DEBUG(10,("set_domain_online_request: called for domain %s\n",
465 if (get_global_winbindd_state_offline()) {
466 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
471 /* We've been told it's safe to go online and
472 try and connect to a DC. But I don't believe it
473 because network manager seems to lie.
474 Wait at least 5 seconds. Heuristics suck... */
476 if (!domain->check_online_event) {
477 /* If we've come from being globally offline we
478 don't have a check online event handler set.
479 We need to add one now we're trying to go
482 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
485 domain->check_online_event = event_add_timed(winbind_event_context(),
487 timeval_current_ofs(5, 0),
488 "check_domain_online_handler",
489 check_domain_online_handler,
492 /* The above *has* to succeed for winbindd to work. */
493 if (!domain->check_online_event) {
494 smb_panic("set_domain_online_request: failed to add online handler");
500 /* Go into "startup" mode again. */
501 domain->startup_time = tev.tv_sec;
502 domain->startup = True;
506 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
509 /****************************************************************
510 Add -ve connection cache entries for domain and realm.
511 ****************************************************************/
513 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
517 add_failed_connection_entry(domain->name, server, result);
518 /* If this was the saf name for the last thing we talked to,
520 saf_delete(domain->name);
521 if (*domain->alt_name) {
522 add_failed_connection_entry(domain->alt_name, server, result);
523 saf_delete(domain->alt_name);
525 winbindd_unset_locator_kdc_env(domain);
528 /* Choose between anonymous or authenticated connections. We need to use
529 an authenticated connection if DCs have the RestrictAnonymous registry
530 entry set > 0, or the "Additional restrictions for anonymous
531 connections" set in the win2k Local Security Policy.
533 Caller to free() result in domain, username, password
536 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
538 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
539 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
540 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
542 if (*username && **username) {
544 if (!*domain || !**domain)
545 *domain = smb_xstrdup(lp_workgroup());
547 if (!*password || !**password)
548 *password = smb_xstrdup("");
550 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
551 *domain, *username));
554 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
555 *username = smb_xstrdup("");
556 *domain = smb_xstrdup("");
557 *password = smb_xstrdup("");
561 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
562 fstring dcname, struct in_addr *dc_ip)
564 struct winbindd_domain *our_domain = NULL;
565 struct rpc_pipe_client *netlogon_pipe = NULL;
569 unsigned int orig_timeout;
573 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
580 if (domain->primary) {
584 our_domain = find_our_domain();
586 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
590 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
591 if (!NT_STATUS_IS_OK(result)) {
592 talloc_destroy(mem_ctx);
596 /* This call can take a long time - allow the server to time out.
597 35 seconds should do it. */
599 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
601 werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
604 /* And restore our original timeout. */
605 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
607 talloc_destroy(mem_ctx);
609 if (!W_ERROR_IS_OK(werr)) {
610 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
615 /* cli_netlogon_getanydcname gives us a name with \\ */
626 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
628 if (!resolve_name(dcname, dc_ip, 0x20)) {
635 /************************************************************************
636 Given a fd with a just-connected TCP connection to a DC, open a connection
638 ************************************************************************/
640 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
642 const char *controller,
643 struct cli_state **cli,
646 char *machine_password, *machine_krb5_principal, *machine_account;
647 char *ipc_username, *ipc_domain, *ipc_password;
651 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
653 struct sockaddr peeraddr;
654 socklen_t peeraddr_len;
656 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
658 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
659 controller, domain->name ));
661 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
664 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
665 SAFE_FREE(machine_password);
666 return NT_STATUS_NO_MEMORY;
669 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
671 SAFE_FREE(machine_account);
672 SAFE_FREE(machine_password);
673 return NT_STATUS_NO_MEMORY;
676 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
680 got_mutex = secrets_named_mutex(controller,
681 WINBIND_SERVER_MUTEX_WAIT_TIME);
684 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
686 result = NT_STATUS_POSSIBLE_DEADLOCK;
690 if ((*cli = cli_initialise()) == NULL) {
691 DEBUG(1, ("Could not cli_initialize\n"));
692 result = NT_STATUS_NO_MEMORY;
696 (*cli)->timeout = 10000; /* 10 seconds */
698 fstrcpy((*cli)->desthost, controller);
699 (*cli)->use_kerberos = True;
701 peeraddr_len = sizeof(peeraddr);
703 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
704 (peeraddr_len != sizeof(struct sockaddr_in)) ||
705 (peeraddr_in->sin_family != PF_INET))
707 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
708 result = NT_STATUS_UNSUCCESSFUL;
712 if (ntohs(peeraddr_in->sin_port) == 139) {
713 struct nmb_name calling;
714 struct nmb_name called;
716 make_nmb_name(&calling, global_myname(), 0x0);
717 make_nmb_name(&called, "*SMBSERVER", 0x20);
719 if (!cli_session_request(*cli, &calling, &called)) {
720 DEBUG(8, ("cli_session_request failed for %s\n",
722 result = NT_STATUS_UNSUCCESSFUL;
727 cli_setup_signing_state(*cli, Undefined);
729 if (!cli_negprot(*cli)) {
730 DEBUG(1, ("cli_negprot failed\n"));
731 result = NT_STATUS_UNSUCCESSFUL;
735 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
736 ADS_STATUS ads_status;
738 if (lp_security() == SEC_ADS) {
740 /* Try a krb5 session */
742 (*cli)->use_kerberos = True;
743 DEBUG(5, ("connecting to %s from %s with kerberos principal "
744 "[%s]\n", controller, global_myname(),
745 machine_krb5_principal));
747 winbindd_set_locator_kdc_envs(domain);
749 ads_status = cli_session_setup_spnego(*cli,
750 machine_krb5_principal,
754 if (!ADS_ERR_OK(ads_status)) {
755 DEBUG(4,("failed kerberos session setup with %s\n",
756 ads_errstr(ads_status)));
759 result = ads_ntstatus(ads_status);
760 if (NT_STATUS_IS_OK(result)) {
761 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
762 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
763 goto session_setup_done;
767 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
768 (*cli)->use_kerberos = False;
770 DEBUG(5, ("connecting to %s from %s with username "
771 "[%s]\\[%s]\n", controller, global_myname(),
772 lp_workgroup(), machine_account));
774 ads_status = cli_session_setup_spnego(*cli,
778 if (!ADS_ERR_OK(ads_status)) {
779 DEBUG(4, ("authenticated session setup failed with %s\n",
780 ads_errstr(ads_status)));
783 result = ads_ntstatus(ads_status);
784 if (NT_STATUS_IS_OK(result)) {
785 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
786 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
787 goto session_setup_done;
791 /* Fall back to non-kerberos session setup */
793 (*cli)->use_kerberos = False;
795 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
796 (strlen(ipc_username) > 0)) {
798 /* Only try authenticated if we have a username */
800 DEBUG(5, ("connecting to %s from %s with username "
801 "[%s]\\[%s]\n", controller, global_myname(),
802 ipc_domain, ipc_username));
804 if (NT_STATUS_IS_OK(cli_session_setup(
806 ipc_password, strlen(ipc_password)+1,
807 ipc_password, strlen(ipc_password)+1,
809 /* Successful logon with given username. */
810 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
811 goto session_setup_done;
813 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
814 ipc_domain, ipc_username ));
818 /* Fall back to anonymous connection, this might fail later */
820 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
822 DEBUG(5, ("Connected anonymously\n"));
823 cli_init_creds(*cli, "", "", "");
824 goto session_setup_done;
827 result = cli_nt_error(*cli);
829 if (NT_STATUS_IS_OK(result))
830 result = NT_STATUS_UNSUCCESSFUL;
832 /* We can't session setup */
838 /* cache the server name for later connections */
840 saf_store( domain->name, (*cli)->desthost );
841 if (domain->alt_name && (*cli)->use_kerberos) {
842 saf_store( domain->alt_name, (*cli)->desthost );
845 winbindd_set_locator_kdc_envs(domain);
847 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
849 result = cli_nt_error(*cli);
851 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
853 if (NT_STATUS_IS_OK(result))
854 result = NT_STATUS_UNSUCCESSFUL;
859 secrets_named_mutex_release(controller);
863 /* set the domain if empty; needed for schannel connections */
864 if ( !*(*cli)->domain ) {
865 fstrcpy( (*cli)->domain, domain->name );
868 result = NT_STATUS_OK;
872 secrets_named_mutex_release(controller);
875 SAFE_FREE(machine_account);
876 SAFE_FREE(machine_password);
877 SAFE_FREE(machine_krb5_principal);
878 SAFE_FREE(ipc_username);
879 SAFE_FREE(ipc_domain);
880 SAFE_FREE(ipc_password);
882 if (!NT_STATUS_IS_OK(result)) {
883 winbind_add_failed_connection_entry(domain, controller, result);
884 if ((*cli) != NULL) {
893 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
894 const char *dcname, struct in_addr ip,
895 struct dc_name_ip **dcs, int *num)
897 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
898 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
902 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
907 fstrcpy((*dcs)[*num].name, dcname);
908 (*dcs)[*num].ip = ip;
913 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
914 struct in_addr ip, uint16 port,
915 struct sockaddr_in **addrs, int *num)
917 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
919 if (*addrs == NULL) {
924 (*addrs)[*num].sin_family = PF_INET;
925 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
926 (*addrs)[*num].sin_port = htons(port);
932 static void mailslot_name(struct in_addr dc_ip, fstring name)
934 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
937 static BOOL send_getdc_request(struct in_addr dc_ip,
938 const char *domain_name,
943 fstring my_acct_name;
946 mailslot_name(dc_ip, my_mailslot);
948 memset(outbuf, '\0', sizeof(outbuf));
952 SCVAL(p, 0, SAMLOGON);
955 SCVAL(p, 0, 0); /* Count pointer ... */
958 SIVAL(p, 0, 0); /* The sender's token ... */
961 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
962 fstr_sprintf(my_acct_name, "%s$", global_myname());
963 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
965 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
966 p += strlen(my_mailslot)+1;
971 SIVAL(p, 0, sid_size(sid));
974 p = ALIGN4(p, outbuf);
976 sid_linearize(p, sid_size(sid), sid);
984 return cli_send_mailslot(winbind_messaging_context(),
985 False, "\\MAILSLOT\\NET\\NTLOGON", 0,
986 outbuf, PTR_DIFF(p, outbuf),
987 global_myname(), 0, domain_name, 0x1c,
991 static BOOL receive_getdc_response(struct in_addr dc_ip,
992 const char *domain_name,
995 struct packet_struct *packet;
998 fstring dcname, user, domain;
1001 mailslot_name(dc_ip, my_mailslot);
1003 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
1005 if (packet == NULL) {
1006 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
1010 DEBUG(5, ("Received packet for %s\n", my_mailslot));
1012 buf = packet->packet.dgram.data;
1013 len = packet->packet.dgram.datasize;
1016 /* 70 is a completely arbitrary value to make sure
1017 the SVAL below does not read uninitialized memory */
1018 DEBUG(3, ("GetDC got short response\n"));
1022 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1023 p = buf+SVAL(buf, smb_vwv10);
1025 if (CVAL(p,0) != SAMLOGON_R) {
1026 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
1031 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1032 STR_TERMINATE|STR_NOALIGN);
1033 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1034 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1035 STR_TERMINATE|STR_NOALIGN);
1036 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1037 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1038 STR_TERMINATE|STR_NOALIGN);
1039 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1041 if (!strequal(domain, domain_name)) {
1042 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1043 domain_name, domain));
1048 if (*p == '\\') p += 1;
1049 if (*p == '\\') p += 1;
1051 fstrcpy(dc_name, p);
1053 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1059 /*******************************************************************
1060 convert an ip to a name
1061 *******************************************************************/
1063 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1065 struct ip_service ip_list;
1071 /* For active directory servers, try to get the ldap server name.
1072 None of these failures should be considered critical for now */
1074 if (lp_security() == SEC_ADS) {
1077 ads = ads_init(domain->alt_name, domain->name, NULL);
1078 ads->auth.flags |= ADS_AUTH_NO_BIND;
1080 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1081 /* We got a cldap packet. */
1082 fstrcpy(name, ads->config.ldap_server_name);
1083 namecache_store(name, 0x20, 1, &ip_list);
1085 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1087 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1088 char *sitename = sitename_fetch(ads->config.realm);
1090 /* We're going to use this KDC for this realm/domain.
1091 If we are using sites, then force the krb5 libs
1094 create_local_private_krb5_conf_for_domain(domain->alt_name,
1099 winbindd_set_locator_kdc_envs(domain);
1101 SAFE_FREE(sitename);
1102 /* Ensure we contact this DC also. */
1103 saf_store( domain->name, name);
1104 saf_store( domain->alt_name, name);
1107 ads_destroy( &ads );
1111 ads_destroy( &ads );
1115 /* try GETDC requests next */
1117 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1120 for (i=0; i<5; i++) {
1121 if (receive_getdc_response(ip, domain->name, name)) {
1122 namecache_store(name, 0x20, 1, &ip_list);
1129 /* try node status request */
1131 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1132 namecache_store(name, 0x20, 1, &ip_list);
1138 /*******************************************************************
1139 Retreive a list of IP address for domain controllers. Fill in
1140 the dcs[] with results.
1141 *******************************************************************/
1143 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1144 struct dc_name_ip **dcs, int *num_dcs)
1148 struct ip_service *ip_list = NULL;
1149 int iplist_size = 0;
1152 enum security_types sec = (enum security_types)lp_security();
1154 is_our_domain = strequal(domain->name, lp_workgroup());
1157 && get_dc_name_via_netlogon(domain, dcname, &ip)
1158 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1160 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1161 dcname, inet_ntoa(ip)));
1165 if (sec == SEC_ADS) {
1166 char *sitename = NULL;
1168 /* We need to make sure we know the local site before
1169 doing any DNS queries, as this will restrict the
1170 get_sorted_dc_list() call below to only fetching
1171 DNS records for the correct site. */
1173 /* Find any DC to get the site record.
1174 We deliberately don't care about the
1177 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1179 sitename = sitename_fetch(domain->alt_name);
1182 /* Do the site-specific AD dns lookup first. */
1183 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1185 for ( i=0; i<iplist_size; i++ ) {
1186 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1187 ip_list[i].ip, dcs, num_dcs);
1191 SAFE_FREE(sitename);
1195 /* Now we add DCs from the main AD dns lookup. */
1196 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1198 for ( i=0; i<iplist_size; i++ ) {
1199 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1200 ip_list[i].ip, dcs, num_dcs);
1204 /* try standard netbios queries if no ADS */
1206 if (iplist_size==0) {
1207 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1210 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1212 /* now add to the dc array. We'll wait until the last minute
1213 to look up the name of the DC. But we fill in the char* for
1214 the ip now in to make the failed connection cache work */
1216 for ( i=0; i<iplist_size; i++ ) {
1217 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1218 ip_list[i].ip, dcs, num_dcs);
1221 SAFE_FREE( ip_list );
1226 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1227 const struct winbindd_domain *domain,
1228 fstring dcname, struct sockaddr_in *addr, int *fd)
1230 struct dc_name_ip *dcs = NULL;
1233 const char **dcnames = NULL;
1234 int num_dcnames = 0;
1236 struct sockaddr_in *addrs = NULL;
1242 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1245 for (i=0; i<num_dcs; i++) {
1247 if (!add_string_to_array(mem_ctx, dcs[i].name,
1248 &dcnames, &num_dcnames)) {
1251 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1252 &addrs, &num_addrs)) {
1256 if (!add_string_to_array(mem_ctx, dcs[i].name,
1257 &dcnames, &num_dcnames)) {
1260 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1261 &addrs, &num_addrs)) {
1266 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1269 if ((addrs == NULL) || (dcnames == NULL))
1272 /* 5 second timeout. */
1273 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1275 for (i=0; i<num_dcs; i++) {
1276 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1277 "domain %s address %s. Error was %s\n",
1278 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1279 winbind_add_failed_connection_entry(domain,
1280 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1285 *addr = addrs[fd_index];
1287 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1288 /* Ok, we've got a name for the DC */
1289 fstrcpy(dcname, dcnames[fd_index]);
1293 /* Try to figure out the name */
1294 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1298 /* We can not continue without the DC's name */
1299 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1300 NT_STATUS_UNSUCCESSFUL);
1304 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1305 struct winbindd_cm_conn *new_conn)
1307 TALLOC_CTX *mem_ctx;
1309 char *saf_servername = saf_fetch( domain->name );
1312 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1313 SAFE_FREE(saf_servername);
1314 set_domain_offline(domain);
1315 return NT_STATUS_NO_MEMORY;
1318 /* we have to check the server affinity cache here since
1319 later we selecte a DC based on response time and not preference */
1321 /* Check the negative connection cache
1322 before talking to it. It going down may have
1323 triggered the reconnection. */
1325 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1327 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1328 saf_servername, domain->name ));
1330 /* convert an ip address to a name */
1331 if ( is_ipaddress( saf_servername ) ) {
1335 ip = *interpret_addr2( saf_servername );
1336 if (dcip_to_name( domain, ip, saf_name )) {
1337 fstrcpy( domain->dcname, saf_name );
1339 winbind_add_failed_connection_entry(
1340 domain, saf_servername,
1341 NT_STATUS_UNSUCCESSFUL);
1344 fstrcpy( domain->dcname, saf_servername );
1347 SAFE_FREE( saf_servername );
1350 for (retries = 0; retries < 3; retries++) {
1355 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1357 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1358 domain->dcname, domain->name ));
1361 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1362 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1364 struct sockaddr_in *addrs = NULL;
1368 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1369 set_domain_offline(domain);
1370 talloc_destroy(mem_ctx);
1371 return NT_STATUS_NO_MEMORY;
1373 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1374 set_domain_offline(domain);
1375 talloc_destroy(mem_ctx);
1376 return NT_STATUS_NO_MEMORY;
1379 /* 5 second timeout. */
1380 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1386 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1388 /* This is the one place where we will
1389 set the global winbindd offline state
1390 to true, if a "WINBINDD_OFFLINE" entry
1391 is found in the winbindd cache. */
1392 set_global_winbindd_state_offline();
1396 new_conn->cli = NULL;
1398 result = cm_prepare_connection(domain, fd, domain->dcname,
1399 &new_conn->cli, &retry);
1405 if (NT_STATUS_IS_OK(result)) {
1407 winbindd_set_locator_kdc_envs(domain);
1409 if (domain->online == False) {
1410 /* We're changing state from offline to online. */
1411 set_global_winbindd_state_online();
1413 set_domain_online(domain);
1415 /* Ensure we setup the retry handler. */
1416 set_domain_offline(domain);
1419 talloc_destroy(mem_ctx);
1423 /* Close down all open pipes on a connection. */
1425 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1427 /* We're closing down a possibly dead
1428 connection. Don't have impossibly long (10s) timeouts. */
1431 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1434 if (conn->samr_pipe != NULL) {
1435 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1436 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1438 cli_set_timeout(conn->cli, 500);
1441 conn->samr_pipe = NULL;
1444 if (conn->lsa_pipe != NULL) {
1445 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1446 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1448 cli_set_timeout(conn->cli, 500);
1451 conn->lsa_pipe = NULL;
1454 if (conn->netlogon_pipe != NULL) {
1455 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1456 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1458 cli_set_timeout(conn->cli, 500);
1461 conn->netlogon_pipe = NULL;
1465 cli_shutdown(conn->cli);
1471 void close_conns_after_fork(void)
1473 struct winbindd_domain *domain;
1475 for (domain = domain_list(); domain; domain = domain->next) {
1476 if (domain->conn.cli == NULL)
1479 if (domain->conn.cli->fd == -1)
1482 close(domain->conn.cli->fd);
1483 domain->conn.cli->fd = -1;
1487 static BOOL connection_ok(struct winbindd_domain *domain)
1489 if (domain->conn.cli == NULL) {
1490 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1491 "cli!\n", domain->dcname, domain->name));
1495 if (!domain->conn.cli->initialised) {
1496 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1497 "initialised!\n", domain->dcname, domain->name));
1501 if (domain->conn.cli->fd == -1) {
1502 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1503 "never started (fd == -1)\n",
1504 domain->dcname, domain->name));
1508 if (domain->online == False) {
1509 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1516 /* Initialize a new connection up to the RPC BIND.
1517 Bypass online status check so always does network calls. */
1519 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1523 /* Internal connections never use the network. */
1524 if (domain->internal) {
1525 domain->initialized = True;
1526 return NT_STATUS_OK;
1529 if (connection_ok(domain)) {
1530 if (!domain->initialized) {
1531 set_dc_type_and_flags(domain);
1533 return NT_STATUS_OK;
1536 invalidate_cm_connection(&domain->conn);
1538 result = cm_open_connection(domain, &domain->conn);
1540 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1541 set_dc_type_and_flags(domain);
1547 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1549 if (domain->initialized && !domain->online) {
1550 /* We check for online status elsewhere. */
1551 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1554 return init_dc_connection_network(domain);
1557 /******************************************************************************
1558 Set the trust flags (direction and forest location) for a domain
1559 ******************************************************************************/
1561 static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1563 struct winbindd_domain *our_domain;
1564 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1565 struct ds_domain_trust *domains = NULL;
1568 uint32 flags = (DS_DOMAIN_IN_FOREST |
1569 DS_DOMAIN_DIRECT_OUTBOUND |
1570 DS_DOMAIN_DIRECT_INBOUND);
1571 struct rpc_pipe_client *cli;
1572 TALLOC_CTX *mem_ctx = NULL;
1574 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1576 /* Our primary domain doesn't need to worry about trust flags.
1577 Force it to go through the network setup */
1578 if ( domain->primary ) {
1582 our_domain = find_our_domain();
1584 if ( !connection_ok(our_domain) ) {
1585 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1589 /* This won't work unless our domain is AD */
1591 if ( !our_domain->active_directory ) {
1595 /* Use DsEnumerateDomainTrusts to get us the trust direction
1598 result = cm_connect_netlogon(our_domain, &cli);
1600 if (!NT_STATUS_IS_OK(result)) {
1601 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1602 "a connection to %s for PIPE_NETLOGON (%s)\n",
1603 domain->name, nt_errstr(result)));
1607 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1608 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1612 result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
1615 (unsigned int *)&count);
1617 /* Now find the domain name and get the flags */
1619 for ( i=0; i<count; i++ ) {
1620 if ( strequal( domain->name, domains[i].netbios_domain ) ) {
1621 domain->domain_flags = domains[i].flags;
1622 domain->domain_type = domains[i].trust_type;
1623 domain->domain_trust_attribs = domains[i].trust_attributes;
1625 if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
1626 domain->active_directory = True;
1628 /* This flag is only set if the domain is *our*
1629 primary domain and the primary domain is in
1632 domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
1634 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1635 "native mode.\n", domain->name,
1636 domain->native_mode ? "" : "NOT "));
1638 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1639 "running active directory.\n", domain->name,
1640 domain->active_directory ? "" : "NOT "));
1643 domain->initialized = True;
1645 if ( !winbindd_can_contact_domain( domain) )
1646 domain->internal = True;
1652 talloc_destroy( mem_ctx );
1654 return domain->initialized;
1657 /******************************************************************************
1658 We can 'sense' certain things about the DC by it's replies to certain
1661 This tells us if this particular remote server is Active Directory, and if it
1663 ******************************************************************************/
1665 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1669 TALLOC_CTX *mem_ctx = NULL;
1670 struct rpc_pipe_client *cli;
1673 char *domain_name = NULL;
1674 char *dns_name = NULL;
1675 char *forest_name = NULL;
1676 DOM_SID *dom_sid = NULL;
1680 if (!connection_ok(domain)) {
1684 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1686 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1690 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1691 "PI_LSARPC_DS on domain %s: (%s)\n",
1692 domain->name, nt_errstr(result)));
1694 /* if this is just a non-AD domain we need to continue
1695 * identifying so that we can in the end return with
1696 * domain->initialized = True - gd */
1701 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1702 DsRolePrimaryDomainInfoBasic,
1704 cli_rpc_pipe_close(cli);
1706 if (!NT_STATUS_IS_OK(result)) {
1707 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1708 "on domain %s failed: (%s)\n",
1709 domain->name, nt_errstr(result)));
1713 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1714 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1715 domain->native_mode = True;
1717 domain->native_mode = False;
1721 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1724 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1725 "PI_LSARPC on domain %s: (%s)\n",
1726 domain->name, nt_errstr(result)));
1727 cli_rpc_pipe_close(cli);
1731 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1734 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1735 cli_rpc_pipe_close(cli);
1739 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1740 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1742 if (NT_STATUS_IS_OK(result)) {
1743 /* This particular query is exactly what Win2k clients use
1744 to determine that the DC is active directory */
1745 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1747 &dns_name, &forest_name,
1751 if (NT_STATUS_IS_OK(result)) {
1752 domain->active_directory = True;
1755 fstrcpy(domain->name, domain_name);
1758 fstrcpy(domain->alt_name, dns_name);
1761 fstrcpy(domain->forest_name, forest_name);
1764 sid_copy(&domain->sid, dom_sid);
1766 domain->active_directory = False;
1768 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1769 SEC_RIGHTS_MAXIMUM_ALLOWED,
1772 if (!NT_STATUS_IS_OK(result))
1775 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1776 &pol, 5, &domain_name,
1779 if (NT_STATUS_IS_OK(result)) {
1781 fstrcpy(domain->name, domain_name);
1784 sid_copy(&domain->sid, dom_sid);
1789 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1790 domain->name, domain->native_mode ? "" : "NOT "));
1792 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1793 domain->name, domain->active_directory ? "" : "NOT "));
1795 cli_rpc_pipe_close(cli);
1797 talloc_destroy(mem_ctx);
1799 domain->initialized = True;
1802 /**********************************************************************
1803 Set the domain_flags (trust attributes, domain operating modes, etc...
1804 ***********************************************************************/
1806 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1808 /* we always have to contact our primary domain */
1810 if ( domain->primary ) {
1811 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1812 "primary domain\n"));
1813 set_dc_type_and_flags_connect( domain );
1817 /* Use our DC to get the information if possible */
1819 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1820 /* Otherwise, fallback to contacting the
1822 set_dc_type_and_flags_connect( domain );
1830 /**********************************************************************
1831 ***********************************************************************/
1833 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1834 struct dcinfo **ppdc)
1837 struct rpc_pipe_client *netlogon_pipe;
1839 if (lp_client_schannel() == False) {
1843 result = cm_connect_netlogon(domain, &netlogon_pipe);
1844 if (!NT_STATUS_IS_OK(result)) {
1848 /* Return a pointer to the struct dcinfo from the
1851 *ppdc = domain->conn.netlogon_pipe->dc;
1855 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1856 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1858 struct winbindd_cm_conn *conn;
1859 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1861 struct dcinfo *p_dcinfo;
1863 result = init_dc_connection(domain);
1864 if (!NT_STATUS_IS_OK(result)) {
1868 conn = &domain->conn;
1870 if (conn->samr_pipe != NULL) {
1875 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1876 * sign and sealed pipe using the machine account password by
1877 * preference. If we can't - try schannel, if that fails, try
1881 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1882 if ((conn->cli->user_name[0] == '\0') ||
1883 (conn->cli->domain[0] == '\0') ||
1884 (conn_pwd[0] == '\0')) {
1885 DEBUG(10, ("cm_connect_sam: No no user available for "
1886 "domain %s, trying schannel\n", conn->cli->domain));
1890 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1891 authenticated SAMR pipe with sign & seal. */
1893 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1894 PIPE_AUTH_LEVEL_PRIVACY,
1896 conn->cli->user_name,
1899 if (conn->samr_pipe == NULL) {
1900 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1901 "pipe for domain %s using NTLMSSP "
1902 "authenticated pipe: user %s\\%s. Error was "
1903 "%s\n", domain->name, conn->cli->domain,
1904 conn->cli->user_name, nt_errstr(result)));
1908 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1909 "domain %s using NTLMSSP authenticated "
1910 "pipe: user %s\\%s\n", domain->name,
1911 conn->cli->domain, conn->cli->user_name ));
1913 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1914 SEC_RIGHTS_MAXIMUM_ALLOWED,
1915 &conn->sam_connect_handle);
1916 if (NT_STATUS_IS_OK(result)) {
1919 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1920 "failed for domain %s, error was %s. Trying schannel\n",
1921 domain->name, nt_errstr(result) ));
1922 cli_rpc_pipe_close(conn->samr_pipe);
1926 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1928 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1929 /* If this call fails - conn->cli can now be NULL ! */
1930 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1931 "for domain %s, trying anon\n", domain->name));
1934 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1935 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1936 domain->name, p_dcinfo, &result);
1938 if (conn->samr_pipe == NULL) {
1939 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1940 "domain %s using schannel. Error was %s\n",
1941 domain->name, nt_errstr(result) ));
1944 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1945 "schannel.\n", domain->name ));
1947 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1948 SEC_RIGHTS_MAXIMUM_ALLOWED,
1949 &conn->sam_connect_handle);
1950 if (NT_STATUS_IS_OK(result)) {
1953 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1954 "for domain %s, error was %s. Trying anonymous\n",
1955 domain->name, nt_errstr(result) ));
1956 cli_rpc_pipe_close(conn->samr_pipe);
1960 /* Finally fall back to anonymous. */
1961 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1964 if (conn->samr_pipe == NULL) {
1965 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1969 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1970 SEC_RIGHTS_MAXIMUM_ALLOWED,
1971 &conn->sam_connect_handle);
1972 if (!NT_STATUS_IS_OK(result)) {
1973 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1974 "for domain %s Error was %s\n",
1975 domain->name, nt_errstr(result) ));
1980 result = rpccli_samr_open_domain(conn->samr_pipe,
1982 &conn->sam_connect_handle,
1983 SEC_RIGHTS_MAXIMUM_ALLOWED,
1985 &conn->sam_domain_handle);
1989 if (!NT_STATUS_IS_OK(result)) {
1990 invalidate_cm_connection(conn);
1994 *cli = conn->samr_pipe;
1995 *sam_handle = conn->sam_domain_handle;
1999 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2000 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2002 struct winbindd_cm_conn *conn;
2003 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2005 struct dcinfo *p_dcinfo;
2007 result = init_dc_connection(domain);
2008 if (!NT_STATUS_IS_OK(result))
2011 conn = &domain->conn;
2013 if (conn->lsa_pipe != NULL) {
2017 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2018 if ((conn->cli->user_name[0] == '\0') ||
2019 (conn->cli->domain[0] == '\0') ||
2020 (conn_pwd[0] == '\0')) {
2021 DEBUG(10, ("cm_connect_lsa: No no user available for "
2022 "domain %s, trying schannel\n", conn->cli->domain));
2026 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2027 * authenticated LSA pipe with sign & seal. */
2028 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
2029 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2030 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
2032 if (conn->lsa_pipe == NULL) {
2033 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2034 "domain %s using NTLMSSP authenticated pipe: user "
2035 "%s\\%s. Error was %s. Trying schannel.\n",
2036 domain->name, conn->cli->domain,
2037 conn->cli->user_name, nt_errstr(result)));
2041 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2042 "NTLMSSP authenticated pipe: user %s\\%s\n",
2043 domain->name, conn->cli->domain, conn->cli->user_name ));
2045 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2046 SEC_RIGHTS_MAXIMUM_ALLOWED,
2048 if (NT_STATUS_IS_OK(result)) {
2052 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2055 cli_rpc_pipe_close(conn->lsa_pipe);
2059 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2061 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2062 /* If this call fails - conn->cli can now be NULL ! */
2063 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2064 "for domain %s, trying anon\n", domain->name));
2067 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2068 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2069 domain->name, p_dcinfo, &result);
2071 if (conn->lsa_pipe == NULL) {
2072 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2073 "domain %s using schannel. Error was %s\n",
2074 domain->name, nt_errstr(result) ));
2077 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2078 "schannel.\n", domain->name ));
2080 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2081 SEC_RIGHTS_MAXIMUM_ALLOWED,
2083 if (NT_STATUS_IS_OK(result)) {
2087 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2090 cli_rpc_pipe_close(conn->lsa_pipe);
2094 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2096 if (conn->lsa_pipe == NULL) {
2097 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2101 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2102 SEC_RIGHTS_MAXIMUM_ALLOWED,
2105 if (!NT_STATUS_IS_OK(result)) {
2106 invalidate_cm_connection(conn);
2110 *cli = conn->lsa_pipe;
2111 *lsa_policy = conn->lsa_policy;
2115 /****************************************************************************
2116 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2117 session key stored in conn->netlogon_pipe->dc->sess_key.
2118 ****************************************************************************/
2120 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2121 struct rpc_pipe_client **cli)
2123 struct winbindd_cm_conn *conn;
2126 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2128 uint32 sec_chan_type;
2129 const char *account_name;
2130 struct rpc_pipe_client *netlogon_pipe = NULL;
2134 result = init_dc_connection(domain);
2135 if (!NT_STATUS_IS_OK(result)) {
2139 conn = &domain->conn;
2141 if (conn->netlogon_pipe != NULL) {
2142 *cli = conn->netlogon_pipe;
2143 return NT_STATUS_OK;
2146 if (domain->primary && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
2147 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2150 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2152 if (netlogon_pipe == NULL) {
2156 if ( !domain->primary ) {
2157 /* Clear the schannel request bit and drop down */
2158 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2162 if (lp_client_schannel() != False) {
2163 neg_flags |= NETLOGON_NEG_SCHANNEL;
2166 /* if we are a DC and this is a trusted domain, then we need to use our
2167 domain name in the net_req_auth2() request */
2170 && !strequal(domain->name, lp_workgroup())
2171 && lp_allow_trusted_domains() )
2173 account_name = lp_workgroup();
2175 account_name = domain->primary ?
2176 global_myname() : domain->name;
2179 if (account_name == NULL) {
2180 cli_rpc_pipe_close(netlogon_pipe);
2181 return NT_STATUS_NO_MEMORY;
2184 result = rpccli_netlogon_setup_creds(
2186 domain->dcname, /* server name. */
2187 domain->name, /* domain name */
2188 global_myname(), /* client name */
2189 account_name, /* machine account */
2190 mach_pwd, /* machine password */
2191 sec_chan_type, /* from get_trust_pw */
2194 if (!NT_STATUS_IS_OK(result)) {
2195 cli_rpc_pipe_close(netlogon_pipe);
2199 if ((lp_client_schannel() == True) &&
2200 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2201 DEBUG(3, ("Server did not offer schannel\n"));
2202 cli_rpc_pipe_close(netlogon_pipe);
2203 return NT_STATUS_ACCESS_DENIED;
2207 if ((lp_client_schannel() == False) ||
2208 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2211 * NetSamLogonEx only works for schannel
2213 domain->can_do_samlogon_ex = False;
2215 /* We're done - just keep the existing connection to NETLOGON
2217 conn->netlogon_pipe = netlogon_pipe;
2218 *cli = conn->netlogon_pipe;
2219 return NT_STATUS_OK;
2222 /* Using the credentials from the first pipe, open a signed and sealed
2223 second netlogon pipe. The session key is stored in the schannel
2224 part of the new pipe auth struct.
2227 conn->netlogon_pipe =
2228 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2230 PIPE_AUTH_LEVEL_PRIVACY,
2235 /* We can now close the initial netlogon pipe. */
2236 cli_rpc_pipe_close(netlogon_pipe);
2238 if (conn->netlogon_pipe == NULL) {
2239 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2240 "was %s\n", nt_errstr(result)));
2242 /* make sure we return something besides OK */
2243 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2247 * Try NetSamLogonEx for AD domains
2249 domain->can_do_samlogon_ex = domain->active_directory;
2251 *cli = conn->netlogon_pipe;
2252 return NT_STATUS_OK;