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 /* If we are waiting to get a krb5 ticket, trigger immediately. */
400 set_event_dispatch_time(winbind_event_context(),
401 "krb5_ticket_gain_handler", now);
403 /* Ok, we're out of any startup mode now... */
404 domain->startup = False;
406 if (domain->online == False) {
407 /* We were offline - now we're online. We default to
408 using the MS-RPC backend if we started offline,
409 and if we're going online for the first time we
410 should really re-initialize the backends and the
411 checks to see if we're talking to an AD or NT domain.
414 domain->initialized = False;
416 /* 'reconnect_methods' is the MS-RPC backend. */
417 if (domain->backend == &reconnect_methods) {
418 domain->backend = NULL;
422 /* Ensure we have no online timeout checks. */
423 domain->check_online_timeout = 0;
424 TALLOC_FREE(domain->check_online_event);
426 /* Ensure we ignore any pending child messages. */
427 messaging_deregister(winbind_messaging_context(),
428 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
429 messaging_deregister(winbind_messaging_context(),
430 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
432 domain->online = True;
434 /* Send an online message to the idmap child when our
435 primary domain comes online */
437 if ( domain->primary ) {
438 struct winbindd_child *idmap = idmap_child();
440 if ( idmap->pid != 0 ) {
441 messaging_send_buf(winbind_messaging_context(),
442 pid_to_procid(idmap->pid),
444 (uint8 *)domain->name,
445 strlen(domain->name)+1);
452 /****************************************************************
453 Requested to set a domain online.
454 ****************************************************************/
456 void set_domain_online_request(struct winbindd_domain *domain)
460 DEBUG(10,("set_domain_online_request: called for domain %s\n",
463 if (get_global_winbindd_state_offline()) {
464 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
469 /* We've been told it's safe to go online and
470 try and connect to a DC. But I don't believe it
471 because network manager seems to lie.
472 Wait at least 5 seconds. Heuristics suck... */
474 if (!domain->check_online_event) {
475 /* If we've come from being globally offline we
476 don't have a check online event handler set.
477 We need to add one now we're trying to go
480 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
483 domain->check_online_event = event_add_timed(winbind_event_context(),
485 timeval_current_ofs(5, 0),
486 "check_domain_online_handler",
487 check_domain_online_handler,
490 /* The above *has* to succeed for winbindd to work. */
491 if (!domain->check_online_event) {
492 smb_panic("set_domain_online_request: failed to add online handler");
498 /* Go into "startup" mode again. */
499 domain->startup_time = tev.tv_sec;
500 domain->startup = True;
504 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
507 /****************************************************************
508 Add -ve connection cache entries for domain and realm.
509 ****************************************************************/
511 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
515 add_failed_connection_entry(domain->name, server, result);
516 /* If this was the saf name for the last thing we talked to,
518 saf_delete(domain->name);
519 if (*domain->alt_name) {
520 add_failed_connection_entry(domain->alt_name, server, result);
521 saf_delete(domain->alt_name);
525 /* Choose between anonymous or authenticated connections. We need to use
526 an authenticated connection if DCs have the RestrictAnonymous registry
527 entry set > 0, or the "Additional restrictions for anonymous
528 connections" set in the win2k Local Security Policy.
530 Caller to free() result in domain, username, password
533 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
535 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
536 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
537 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
539 if (*username && **username) {
541 if (!*domain || !**domain)
542 *domain = smb_xstrdup(lp_workgroup());
544 if (!*password || !**password)
545 *password = smb_xstrdup("");
547 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
548 *domain, *username));
551 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
552 *username = smb_xstrdup("");
553 *domain = smb_xstrdup("");
554 *password = smb_xstrdup("");
558 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
559 fstring dcname, struct in_addr *dc_ip)
561 struct winbindd_domain *our_domain = NULL;
562 struct rpc_pipe_client *netlogon_pipe = NULL;
566 unsigned int orig_timeout;
570 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
577 if (domain->primary) {
581 our_domain = find_our_domain();
583 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
587 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
588 if (!NT_STATUS_IS_OK(result)) {
589 talloc_destroy(mem_ctx);
593 /* This call can take a long time - allow the server to time out.
594 35 seconds should do it. */
596 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
598 werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
601 /* And restore our original timeout. */
602 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
604 talloc_destroy(mem_ctx);
606 if (!W_ERROR_IS_OK(werr)) {
607 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
612 /* cli_netlogon_getanydcname gives us a name with \\ */
623 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
625 if (!resolve_name(dcname, dc_ip, 0x20)) {
632 /************************************************************************
633 Given a fd with a just-connected TCP connection to a DC, open a connection
635 ************************************************************************/
637 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
639 const char *controller,
640 struct cli_state **cli,
643 char *machine_password, *machine_krb5_principal, *machine_account;
644 char *ipc_username, *ipc_domain, *ipc_password;
648 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
650 struct sockaddr peeraddr;
651 socklen_t peeraddr_len;
653 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
655 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
656 controller, domain->name ));
658 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
661 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
662 SAFE_FREE(machine_password);
663 return NT_STATUS_NO_MEMORY;
666 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
668 SAFE_FREE(machine_account);
669 SAFE_FREE(machine_password);
670 return NT_STATUS_NO_MEMORY;
673 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
677 got_mutex = secrets_named_mutex(controller,
678 WINBIND_SERVER_MUTEX_WAIT_TIME);
681 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
683 result = NT_STATUS_POSSIBLE_DEADLOCK;
687 if ((*cli = cli_initialise()) == NULL) {
688 DEBUG(1, ("Could not cli_initialize\n"));
689 result = NT_STATUS_NO_MEMORY;
693 (*cli)->timeout = 10000; /* 10 seconds */
695 fstrcpy((*cli)->desthost, controller);
696 (*cli)->use_kerberos = True;
698 peeraddr_len = sizeof(peeraddr);
700 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
701 (peeraddr_len != sizeof(struct sockaddr_in)) ||
702 (peeraddr_in->sin_family != PF_INET))
704 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
705 result = NT_STATUS_UNSUCCESSFUL;
709 if (ntohs(peeraddr_in->sin_port) == 139) {
710 struct nmb_name calling;
711 struct nmb_name called;
713 make_nmb_name(&calling, global_myname(), 0x0);
714 make_nmb_name(&called, "*SMBSERVER", 0x20);
716 if (!cli_session_request(*cli, &calling, &called)) {
717 DEBUG(8, ("cli_session_request failed for %s\n",
719 result = NT_STATUS_UNSUCCESSFUL;
724 cli_setup_signing_state(*cli, Undefined);
726 if (!cli_negprot(*cli)) {
727 DEBUG(1, ("cli_negprot failed\n"));
728 result = NT_STATUS_UNSUCCESSFUL;
732 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
733 ADS_STATUS ads_status;
735 if (lp_security() == SEC_ADS) {
737 /* Try a krb5 session */
739 (*cli)->use_kerberos = True;
740 DEBUG(5, ("connecting to %s from %s with kerberos principal "
741 "[%s]\n", controller, global_myname(),
742 machine_krb5_principal));
744 ads_status = cli_session_setup_spnego(*cli,
745 machine_krb5_principal,
749 if (!ADS_ERR_OK(ads_status)) {
750 DEBUG(4,("failed kerberos session setup with %s\n",
751 ads_errstr(ads_status)));
754 result = ads_ntstatus(ads_status);
755 if (NT_STATUS_IS_OK(result)) {
756 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
757 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
758 goto session_setup_done;
762 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
763 (*cli)->use_kerberos = False;
765 DEBUG(5, ("connecting to %s from %s with username "
766 "[%s]\\[%s]\n", controller, global_myname(),
767 lp_workgroup(), machine_account));
769 ads_status = cli_session_setup_spnego(*cli,
773 if (!ADS_ERR_OK(ads_status)) {
774 DEBUG(4, ("authenticated session setup failed with %s\n",
775 ads_errstr(ads_status)));
778 result = ads_ntstatus(ads_status);
779 if (NT_STATUS_IS_OK(result)) {
780 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
781 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
782 goto session_setup_done;
786 /* Fall back to non-kerberos session setup */
788 (*cli)->use_kerberos = False;
790 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
791 (strlen(ipc_username) > 0)) {
793 /* Only try authenticated if we have a username */
795 DEBUG(5, ("connecting to %s from %s with username "
796 "[%s]\\[%s]\n", controller, global_myname(),
797 ipc_domain, ipc_username));
799 if (NT_STATUS_IS_OK(cli_session_setup(
801 ipc_password, strlen(ipc_password)+1,
802 ipc_password, strlen(ipc_password)+1,
804 /* Successful logon with given username. */
805 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
806 goto session_setup_done;
808 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
809 ipc_domain, ipc_username ));
813 /* Fall back to anonymous connection, this might fail later */
815 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
817 DEBUG(5, ("Connected anonymously\n"));
818 cli_init_creds(*cli, "", "", "");
819 goto session_setup_done;
822 result = cli_nt_error(*cli);
824 if (NT_STATUS_IS_OK(result))
825 result = NT_STATUS_UNSUCCESSFUL;
827 /* We can't session setup */
833 /* cache the server name for later connections */
835 saf_store( domain->name, (*cli)->desthost );
836 if (domain->alt_name && (*cli)->use_kerberos) {
837 saf_store( domain->alt_name, (*cli)->desthost );
840 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
842 result = cli_nt_error(*cli);
844 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
846 if (NT_STATUS_IS_OK(result))
847 result = NT_STATUS_UNSUCCESSFUL;
852 secrets_named_mutex_release(controller);
856 /* set the domain if empty; needed for schannel connections */
857 if ( !*(*cli)->domain ) {
858 fstrcpy( (*cli)->domain, domain->name );
861 result = NT_STATUS_OK;
865 secrets_named_mutex_release(controller);
868 SAFE_FREE(machine_account);
869 SAFE_FREE(machine_password);
870 SAFE_FREE(machine_krb5_principal);
871 SAFE_FREE(ipc_username);
872 SAFE_FREE(ipc_domain);
873 SAFE_FREE(ipc_password);
875 if (!NT_STATUS_IS_OK(result)) {
876 winbind_add_failed_connection_entry(domain, controller, result);
877 if ((*cli) != NULL) {
886 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
887 const char *dcname, struct in_addr ip,
888 struct dc_name_ip **dcs, int *num)
890 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
891 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
895 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
900 fstrcpy((*dcs)[*num].name, dcname);
901 (*dcs)[*num].ip = ip;
906 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
907 struct in_addr ip, uint16 port,
908 struct sockaddr_in **addrs, int *num)
910 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
912 if (*addrs == NULL) {
917 (*addrs)[*num].sin_family = PF_INET;
918 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
919 (*addrs)[*num].sin_port = htons(port);
925 static void mailslot_name(struct in_addr dc_ip, fstring name)
927 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
930 static BOOL send_getdc_request(struct in_addr dc_ip,
931 const char *domain_name,
936 fstring my_acct_name;
939 mailslot_name(dc_ip, my_mailslot);
941 memset(outbuf, '\0', sizeof(outbuf));
945 SCVAL(p, 0, SAMLOGON);
948 SCVAL(p, 0, 0); /* Count pointer ... */
951 SIVAL(p, 0, 0); /* The sender's token ... */
954 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
955 fstr_sprintf(my_acct_name, "%s$", global_myname());
956 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
958 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
959 p += strlen(my_mailslot)+1;
964 SIVAL(p, 0, sid_size(sid));
967 p = ALIGN4(p, outbuf);
969 sid_linearize(p, sid_size(sid), sid);
977 return cli_send_mailslot(winbind_messaging_context(),
978 False, "\\MAILSLOT\\NET\\NTLOGON", 0,
979 outbuf, PTR_DIFF(p, outbuf),
980 global_myname(), 0, domain_name, 0x1c,
984 static BOOL receive_getdc_response(struct in_addr dc_ip,
985 const char *domain_name,
988 struct packet_struct *packet;
991 fstring dcname, user, domain;
994 mailslot_name(dc_ip, my_mailslot);
996 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
998 if (packet == NULL) {
999 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
1003 DEBUG(5, ("Received packet for %s\n", my_mailslot));
1005 buf = packet->packet.dgram.data;
1006 len = packet->packet.dgram.datasize;
1009 /* 70 is a completely arbitrary value to make sure
1010 the SVAL below does not read uninitialized memory */
1011 DEBUG(3, ("GetDC got short response\n"));
1015 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1016 p = buf+SVAL(buf, smb_vwv10);
1018 if (CVAL(p,0) != SAMLOGON_R) {
1019 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
1024 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1025 STR_TERMINATE|STR_NOALIGN);
1026 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1027 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1028 STR_TERMINATE|STR_NOALIGN);
1029 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1030 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1031 STR_TERMINATE|STR_NOALIGN);
1032 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1034 if (!strequal(domain, domain_name)) {
1035 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1036 domain_name, domain));
1041 if (*p == '\\') p += 1;
1042 if (*p == '\\') p += 1;
1044 fstrcpy(dc_name, p);
1046 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1052 /*******************************************************************
1053 convert an ip to a name
1054 *******************************************************************/
1056 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1058 struct ip_service ip_list;
1064 /* For active directory servers, try to get the ldap server name.
1065 None of these failures should be considered critical for now */
1067 if (lp_security() == SEC_ADS) {
1070 ads = ads_init(domain->alt_name, domain->name, NULL);
1071 ads->auth.flags |= ADS_AUTH_NO_BIND;
1073 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1074 /* We got a cldap packet. */
1075 fstrcpy(name, ads->config.ldap_server_name);
1076 namecache_store(name, 0x20, 1, &ip_list);
1078 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1080 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1081 char *sitename = sitename_fetch(ads->config.realm);
1083 /* We're going to use this KDC for this realm/domain.
1084 If we are using sites, then force the krb5 libs
1087 create_local_private_krb5_conf_for_domain(domain->alt_name,
1092 SAFE_FREE(sitename);
1093 /* Ensure we contact this DC also. */
1094 saf_store( domain->name, name);
1095 saf_store( domain->alt_name, name);
1098 ads_destroy( &ads );
1102 ads_destroy( &ads );
1106 /* try GETDC requests next */
1108 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1111 for (i=0; i<5; i++) {
1112 if (receive_getdc_response(ip, domain->name, name)) {
1113 namecache_store(name, 0x20, 1, &ip_list);
1120 /* try node status request */
1122 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1123 namecache_store(name, 0x20, 1, &ip_list);
1129 /*******************************************************************
1130 Retreive a list of IP address for domain controllers. Fill in
1131 the dcs[] with results.
1132 *******************************************************************/
1134 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1135 struct dc_name_ip **dcs, int *num_dcs)
1139 struct ip_service *ip_list = NULL;
1140 int iplist_size = 0;
1143 enum security_types sec = (enum security_types)lp_security();
1145 is_our_domain = strequal(domain->name, lp_workgroup());
1148 && get_dc_name_via_netlogon(domain, dcname, &ip)
1149 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1151 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1152 dcname, inet_ntoa(ip)));
1156 if (sec == SEC_ADS) {
1157 char *sitename = NULL;
1159 /* We need to make sure we know the local site before
1160 doing any DNS queries, as this will restrict the
1161 get_sorted_dc_list() call below to only fetching
1162 DNS records for the correct site. */
1164 /* Find any DC to get the site record.
1165 We deliberately don't care about the
1168 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1170 sitename = sitename_fetch(domain->alt_name);
1173 /* Do the site-specific AD dns lookup first. */
1174 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1176 for ( i=0; i<iplist_size; i++ ) {
1177 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1178 ip_list[i].ip, dcs, num_dcs);
1182 SAFE_FREE(sitename);
1186 /* Now we add DCs from the main AD dns lookup. */
1187 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1189 for ( i=0; i<iplist_size; i++ ) {
1190 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1191 ip_list[i].ip, dcs, num_dcs);
1195 /* try standard netbios queries if no ADS */
1197 if (iplist_size==0) {
1198 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1201 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1203 /* now add to the dc array. We'll wait until the last minute
1204 to look up the name of the DC. But we fill in the char* for
1205 the ip now in to make the failed connection cache work */
1207 for ( i=0; i<iplist_size; i++ ) {
1208 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1209 ip_list[i].ip, dcs, num_dcs);
1212 SAFE_FREE( ip_list );
1217 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1218 const struct winbindd_domain *domain,
1219 fstring dcname, struct sockaddr_in *addr, int *fd)
1221 struct dc_name_ip *dcs = NULL;
1224 const char **dcnames = NULL;
1225 int num_dcnames = 0;
1227 struct sockaddr_in *addrs = NULL;
1233 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1236 for (i=0; i<num_dcs; i++) {
1238 if (!add_string_to_array(mem_ctx, dcs[i].name,
1239 &dcnames, &num_dcnames)) {
1242 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1243 &addrs, &num_addrs)) {
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, 139,
1252 &addrs, &num_addrs)) {
1257 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1260 if ((addrs == NULL) || (dcnames == NULL))
1263 /* 5 second timeout. */
1264 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1266 for (i=0; i<num_dcs; i++) {
1267 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1268 "domain %s address %s. Error was %s\n",
1269 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1270 winbind_add_failed_connection_entry(domain,
1271 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1276 *addr = addrs[fd_index];
1278 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1279 /* Ok, we've got a name for the DC */
1280 fstrcpy(dcname, dcnames[fd_index]);
1284 /* Try to figure out the name */
1285 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1289 /* We can not continue without the DC's name */
1290 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1291 NT_STATUS_UNSUCCESSFUL);
1295 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1296 struct winbindd_cm_conn *new_conn)
1298 TALLOC_CTX *mem_ctx;
1300 char *saf_servername = saf_fetch( domain->name );
1303 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1304 SAFE_FREE(saf_servername);
1305 set_domain_offline(domain);
1306 return NT_STATUS_NO_MEMORY;
1309 /* we have to check the server affinity cache here since
1310 later we selecte a DC based on response time and not preference */
1312 /* Check the negative connection cache
1313 before talking to it. It going down may have
1314 triggered the reconnection. */
1316 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1318 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1319 saf_servername, domain->name ));
1321 /* convert an ip address to a name */
1322 if ( is_ipaddress( saf_servername ) ) {
1326 ip = *interpret_addr2( saf_servername );
1327 if (dcip_to_name( domain, ip, saf_name )) {
1328 fstrcpy( domain->dcname, saf_name );
1330 winbind_add_failed_connection_entry(
1331 domain, saf_servername,
1332 NT_STATUS_UNSUCCESSFUL);
1335 fstrcpy( domain->dcname, saf_servername );
1338 SAFE_FREE( saf_servername );
1341 for (retries = 0; retries < 3; retries++) {
1346 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1348 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1349 domain->dcname, domain->name ));
1352 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1353 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1355 struct sockaddr_in *addrs = NULL;
1359 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1360 set_domain_offline(domain);
1361 talloc_destroy(mem_ctx);
1362 return NT_STATUS_NO_MEMORY;
1364 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1365 set_domain_offline(domain);
1366 talloc_destroy(mem_ctx);
1367 return NT_STATUS_NO_MEMORY;
1370 /* 5 second timeout. */
1371 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1377 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1379 /* This is the one place where we will
1380 set the global winbindd offline state
1381 to true, if a "WINBINDD_OFFLINE" entry
1382 is found in the winbindd cache. */
1383 set_global_winbindd_state_offline();
1387 new_conn->cli = NULL;
1389 result = cm_prepare_connection(domain, fd, domain->dcname,
1390 &new_conn->cli, &retry);
1396 if (NT_STATUS_IS_OK(result)) {
1397 if (domain->online == False) {
1398 /* We're changing state from offline to online. */
1399 set_global_winbindd_state_online();
1401 set_domain_online(domain);
1403 /* Ensure we setup the retry handler. */
1404 set_domain_offline(domain);
1407 talloc_destroy(mem_ctx);
1411 /* Close down all open pipes on a connection. */
1413 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1415 /* We're closing down a possibly dead
1416 connection. Don't have impossibly long (10s) timeouts. */
1419 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1422 if (conn->samr_pipe != NULL) {
1423 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1424 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1426 cli_set_timeout(conn->cli, 500);
1429 conn->samr_pipe = NULL;
1432 if (conn->lsa_pipe != NULL) {
1433 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1434 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1436 cli_set_timeout(conn->cli, 500);
1439 conn->lsa_pipe = NULL;
1442 if (conn->netlogon_pipe != NULL) {
1443 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1444 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1446 cli_set_timeout(conn->cli, 500);
1449 conn->netlogon_pipe = NULL;
1453 cli_shutdown(conn->cli);
1459 void close_conns_after_fork(void)
1461 struct winbindd_domain *domain;
1463 for (domain = domain_list(); domain; domain = domain->next) {
1464 if (domain->conn.cli == NULL)
1467 if (domain->conn.cli->fd == -1)
1470 close(domain->conn.cli->fd);
1471 domain->conn.cli->fd = -1;
1475 static BOOL connection_ok(struct winbindd_domain *domain)
1477 if (domain->conn.cli == NULL) {
1478 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1479 "cli!\n", domain->dcname, domain->name));
1483 if (!domain->conn.cli->initialised) {
1484 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1485 "initialised!\n", domain->dcname, domain->name));
1489 if (domain->conn.cli->fd == -1) {
1490 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1491 "never started (fd == -1)\n",
1492 domain->dcname, domain->name));
1496 if (domain->online == False) {
1497 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1504 /* Initialize a new connection up to the RPC BIND.
1505 Bypass online status check so always does network calls. */
1507 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1511 /* Internal connections never use the network. */
1512 if (domain->internal) {
1513 domain->initialized = True;
1514 return NT_STATUS_OK;
1517 if (connection_ok(domain)) {
1518 if (!domain->initialized) {
1519 set_dc_type_and_flags(domain);
1521 return NT_STATUS_OK;
1524 invalidate_cm_connection(&domain->conn);
1526 result = cm_open_connection(domain, &domain->conn);
1528 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1529 set_dc_type_and_flags(domain);
1535 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1537 if (domain->initialized && !domain->online) {
1538 /* We check for online status elsewhere. */
1539 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1542 return init_dc_connection_network(domain);
1545 /******************************************************************************
1546 Set the trust flags (direction and forest location) for a domain
1547 ******************************************************************************/
1549 static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1551 struct winbindd_domain *our_domain;
1552 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1553 struct ds_domain_trust *domains = NULL;
1556 uint32 flags = (DS_DOMAIN_IN_FOREST |
1557 DS_DOMAIN_DIRECT_OUTBOUND |
1558 DS_DOMAIN_DIRECT_INBOUND);
1559 struct rpc_pipe_client *cli;
1560 TALLOC_CTX *mem_ctx = NULL;
1562 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1564 /* Our primary domain doesn't need to worry about trust flags.
1565 Force it to go through the network setup */
1566 if ( domain->primary ) {
1570 our_domain = find_our_domain();
1572 if ( !connection_ok(our_domain) ) {
1573 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1577 /* This won't work unless our domain is AD */
1579 if ( !our_domain->active_directory ) {
1583 /* Use DsEnumerateDomainTrusts to get us the trust direction
1586 result = cm_connect_netlogon(our_domain, &cli);
1588 if (!NT_STATUS_IS_OK(result)) {
1589 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1590 "a connection to %s for PIPE_NETLOGON (%s)\n",
1591 domain->name, nt_errstr(result)));
1595 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1596 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1600 result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
1603 (unsigned int *)&count);
1605 /* Now find the domain name and get the flags */
1607 for ( i=0; i<count; i++ ) {
1608 if ( strequal( domain->name, domains[i].netbios_domain ) ) {
1609 domain->domain_flags = domains[i].flags;
1610 domain->domain_type = domains[i].trust_type;
1611 domain->domain_trust_attribs = domains[i].trust_attributes;
1613 if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
1614 domain->active_directory = True;
1616 /* This flag is only set if the domain is *our*
1617 primary domain and the primary domain is in
1620 domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
1622 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1623 "native mode.\n", domain->name,
1624 domain->native_mode ? "" : "NOT "));
1626 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1627 "running active directory.\n", domain->name,
1628 domain->active_directory ? "" : "NOT "));
1631 domain->initialized = True;
1633 if ( !winbindd_can_contact_domain( domain) )
1634 domain->internal = True;
1640 talloc_destroy( mem_ctx );
1642 return domain->initialized;
1645 /******************************************************************************
1646 We can 'sense' certain things about the DC by it's replies to certain
1649 This tells us if this particular remote server is Active Directory, and if it
1651 ******************************************************************************/
1653 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1657 TALLOC_CTX *mem_ctx = NULL;
1658 struct rpc_pipe_client *cli;
1661 char *domain_name = NULL;
1662 char *dns_name = NULL;
1663 char *forest_name = NULL;
1664 DOM_SID *dom_sid = NULL;
1668 if (!connection_ok(domain)) {
1672 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1674 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1678 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1679 "PI_LSARPC_DS on domain %s: (%s)\n",
1680 domain->name, nt_errstr(result)));
1682 /* if this is just a non-AD domain we need to continue
1683 * identifying so that we can in the end return with
1684 * domain->initialized = True - gd */
1689 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1690 DsRolePrimaryDomainInfoBasic,
1692 cli_rpc_pipe_close(cli);
1694 if (!NT_STATUS_IS_OK(result)) {
1695 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1696 "on domain %s failed: (%s)\n",
1697 domain->name, nt_errstr(result)));
1701 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1702 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1703 domain->native_mode = True;
1705 domain->native_mode = False;
1709 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1712 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1713 "PI_LSARPC on domain %s: (%s)\n",
1714 domain->name, nt_errstr(result)));
1715 cli_rpc_pipe_close(cli);
1719 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1722 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1723 cli_rpc_pipe_close(cli);
1727 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1728 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1730 if (NT_STATUS_IS_OK(result)) {
1731 /* This particular query is exactly what Win2k clients use
1732 to determine that the DC is active directory */
1733 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1735 &dns_name, &forest_name,
1739 if (NT_STATUS_IS_OK(result)) {
1740 domain->active_directory = True;
1743 fstrcpy(domain->name, domain_name);
1746 fstrcpy(domain->alt_name, dns_name);
1749 fstrcpy(domain->forest_name, forest_name);
1752 sid_copy(&domain->sid, dom_sid);
1754 domain->active_directory = False;
1756 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1757 SEC_RIGHTS_MAXIMUM_ALLOWED,
1760 if (!NT_STATUS_IS_OK(result))
1763 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1764 &pol, 5, &domain_name,
1767 if (NT_STATUS_IS_OK(result)) {
1769 fstrcpy(domain->name, domain_name);
1772 sid_copy(&domain->sid, dom_sid);
1777 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1778 domain->name, domain->native_mode ? "" : "NOT "));
1780 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1781 domain->name, domain->active_directory ? "" : "NOT "));
1783 cli_rpc_pipe_close(cli);
1785 talloc_destroy(mem_ctx);
1787 domain->initialized = True;
1790 /**********************************************************************
1791 Set the domain_flags (trust attributes, domain operating modes, etc...
1792 ***********************************************************************/
1794 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1796 /* we always have to contact our primary domain */
1798 if ( domain->primary ) {
1799 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1800 "primary domain\n"));
1801 set_dc_type_and_flags_connect( domain );
1805 /* Use our DC to get the information if possible */
1807 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1808 /* Otherwise, fallback to contacting the
1810 set_dc_type_and_flags_connect( domain );
1818 /**********************************************************************
1819 ***********************************************************************/
1821 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1822 struct dcinfo **ppdc)
1825 struct rpc_pipe_client *netlogon_pipe;
1827 if (lp_client_schannel() == False) {
1831 result = cm_connect_netlogon(domain, &netlogon_pipe);
1832 if (!NT_STATUS_IS_OK(result)) {
1836 /* Return a pointer to the struct dcinfo from the
1839 *ppdc = domain->conn.netlogon_pipe->dc;
1843 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1844 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1846 struct winbindd_cm_conn *conn;
1847 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1849 struct dcinfo *p_dcinfo;
1851 result = init_dc_connection(domain);
1852 if (!NT_STATUS_IS_OK(result)) {
1856 conn = &domain->conn;
1858 if (conn->samr_pipe != NULL) {
1863 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1864 * sign and sealed pipe using the machine account password by
1865 * preference. If we can't - try schannel, if that fails, try
1869 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1870 if ((conn->cli->user_name[0] == '\0') ||
1871 (conn->cli->domain[0] == '\0') ||
1872 (conn_pwd[0] == '\0')) {
1873 DEBUG(10, ("cm_connect_sam: No no user available for "
1874 "domain %s, trying schannel\n", conn->cli->domain));
1878 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1879 authenticated SAMR pipe with sign & seal. */
1881 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1882 PIPE_AUTH_LEVEL_PRIVACY,
1884 conn->cli->user_name,
1887 if (conn->samr_pipe == NULL) {
1888 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1889 "pipe for domain %s using NTLMSSP "
1890 "authenticated pipe: user %s\\%s. Error was "
1891 "%s\n", domain->name, conn->cli->domain,
1892 conn->cli->user_name, nt_errstr(result)));
1896 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1897 "domain %s using NTLMSSP authenticated "
1898 "pipe: user %s\\%s\n", domain->name,
1899 conn->cli->domain, conn->cli->user_name ));
1901 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1902 SEC_RIGHTS_MAXIMUM_ALLOWED,
1903 &conn->sam_connect_handle);
1904 if (NT_STATUS_IS_OK(result)) {
1907 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1908 "failed for domain %s, error was %s. Trying schannel\n",
1909 domain->name, nt_errstr(result) ));
1910 cli_rpc_pipe_close(conn->samr_pipe);
1914 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1916 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1917 /* If this call fails - conn->cli can now be NULL ! */
1918 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1919 "for domain %s, trying anon\n", domain->name));
1922 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1923 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1924 domain->name, p_dcinfo, &result);
1926 if (conn->samr_pipe == NULL) {
1927 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1928 "domain %s using schannel. Error was %s\n",
1929 domain->name, nt_errstr(result) ));
1932 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1933 "schannel.\n", domain->name ));
1935 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1936 SEC_RIGHTS_MAXIMUM_ALLOWED,
1937 &conn->sam_connect_handle);
1938 if (NT_STATUS_IS_OK(result)) {
1941 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1942 "for domain %s, error was %s. Trying anonymous\n",
1943 domain->name, nt_errstr(result) ));
1944 cli_rpc_pipe_close(conn->samr_pipe);
1948 /* Finally fall back to anonymous. */
1949 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1952 if (conn->samr_pipe == NULL) {
1953 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1957 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1958 SEC_RIGHTS_MAXIMUM_ALLOWED,
1959 &conn->sam_connect_handle);
1960 if (!NT_STATUS_IS_OK(result)) {
1961 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1962 "for domain %s Error was %s\n",
1963 domain->name, nt_errstr(result) ));
1968 result = rpccli_samr_open_domain(conn->samr_pipe,
1970 &conn->sam_connect_handle,
1971 SEC_RIGHTS_MAXIMUM_ALLOWED,
1973 &conn->sam_domain_handle);
1977 if (!NT_STATUS_IS_OK(result)) {
1978 invalidate_cm_connection(conn);
1982 *cli = conn->samr_pipe;
1983 *sam_handle = conn->sam_domain_handle;
1987 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1988 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1990 struct winbindd_cm_conn *conn;
1991 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1993 struct dcinfo *p_dcinfo;
1995 result = init_dc_connection(domain);
1996 if (!NT_STATUS_IS_OK(result))
1999 conn = &domain->conn;
2001 if (conn->lsa_pipe != NULL) {
2005 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2006 if ((conn->cli->user_name[0] == '\0') ||
2007 (conn->cli->domain[0] == '\0') ||
2008 (conn_pwd[0] == '\0')) {
2009 DEBUG(10, ("cm_connect_lsa: No no user available for "
2010 "domain %s, trying schannel\n", conn->cli->domain));
2014 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2015 * authenticated LSA pipe with sign & seal. */
2016 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
2017 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2018 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
2020 if (conn->lsa_pipe == NULL) {
2021 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2022 "domain %s using NTLMSSP authenticated pipe: user "
2023 "%s\\%s. Error was %s. Trying schannel.\n",
2024 domain->name, conn->cli->domain,
2025 conn->cli->user_name, nt_errstr(result)));
2029 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2030 "NTLMSSP authenticated pipe: user %s\\%s\n",
2031 domain->name, conn->cli->domain, conn->cli->user_name ));
2033 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2034 SEC_RIGHTS_MAXIMUM_ALLOWED,
2036 if (NT_STATUS_IS_OK(result)) {
2040 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2043 cli_rpc_pipe_close(conn->lsa_pipe);
2047 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2049 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2050 /* If this call fails - conn->cli can now be NULL ! */
2051 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2052 "for domain %s, trying anon\n", domain->name));
2055 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2056 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2057 domain->name, p_dcinfo, &result);
2059 if (conn->lsa_pipe == NULL) {
2060 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2061 "domain %s using schannel. Error was %s\n",
2062 domain->name, nt_errstr(result) ));
2065 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2066 "schannel.\n", domain->name ));
2068 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2069 SEC_RIGHTS_MAXIMUM_ALLOWED,
2071 if (NT_STATUS_IS_OK(result)) {
2075 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2078 cli_rpc_pipe_close(conn->lsa_pipe);
2082 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2084 if (conn->lsa_pipe == NULL) {
2085 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2089 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2090 SEC_RIGHTS_MAXIMUM_ALLOWED,
2093 if (!NT_STATUS_IS_OK(result)) {
2094 invalidate_cm_connection(conn);
2098 *cli = conn->lsa_pipe;
2099 *lsa_policy = conn->lsa_policy;
2103 /****************************************************************************
2104 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2105 session key stored in conn->netlogon_pipe->dc->sess_key.
2106 ****************************************************************************/
2108 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2109 struct rpc_pipe_client **cli)
2111 struct winbindd_cm_conn *conn;
2114 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2116 uint32 sec_chan_type;
2117 const char *account_name;
2118 struct rpc_pipe_client *netlogon_pipe = NULL;
2122 result = init_dc_connection(domain);
2123 if (!NT_STATUS_IS_OK(result)) {
2127 conn = &domain->conn;
2129 if (conn->netlogon_pipe != NULL) {
2130 *cli = conn->netlogon_pipe;
2131 return NT_STATUS_OK;
2134 if (domain->primary && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
2135 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2138 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2140 if (netlogon_pipe == NULL) {
2144 if ( !domain->primary ) {
2145 /* Clear the schannel request bit and drop down */
2146 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2150 if (lp_client_schannel() != False) {
2151 neg_flags |= NETLOGON_NEG_SCHANNEL;
2154 /* if we are a DC and this is a trusted domain, then we need to use our
2155 domain name in the net_req_auth2() request */
2158 && !strequal(domain->name, lp_workgroup())
2159 && lp_allow_trusted_domains() )
2161 account_name = lp_workgroup();
2163 account_name = domain->primary ?
2164 global_myname() : domain->name;
2167 if (account_name == NULL) {
2168 cli_rpc_pipe_close(netlogon_pipe);
2169 return NT_STATUS_NO_MEMORY;
2172 result = rpccli_netlogon_setup_creds(
2174 domain->dcname, /* server name. */
2175 domain->name, /* domain name */
2176 global_myname(), /* client name */
2177 account_name, /* machine account */
2178 mach_pwd, /* machine password */
2179 sec_chan_type, /* from get_trust_pw */
2182 if (!NT_STATUS_IS_OK(result)) {
2183 cli_rpc_pipe_close(netlogon_pipe);
2187 if ((lp_client_schannel() == True) &&
2188 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2189 DEBUG(3, ("Server did not offer schannel\n"));
2190 cli_rpc_pipe_close(netlogon_pipe);
2191 return NT_STATUS_ACCESS_DENIED;
2195 if ((lp_client_schannel() == False) ||
2196 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2199 * NetSamLogonEx only works for schannel
2201 domain->can_do_samlogon_ex = False;
2203 /* We're done - just keep the existing connection to NETLOGON
2205 conn->netlogon_pipe = netlogon_pipe;
2206 *cli = conn->netlogon_pipe;
2207 return NT_STATUS_OK;
2210 /* Using the credentials from the first pipe, open a signed and sealed
2211 second netlogon pipe. The session key is stored in the schannel
2212 part of the new pipe auth struct.
2215 conn->netlogon_pipe =
2216 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2218 PIPE_AUTH_LEVEL_PRIVACY,
2223 /* We can now close the initial netlogon pipe. */
2224 cli_rpc_pipe_close(netlogon_pipe);
2226 if (conn->netlogon_pipe == NULL) {
2227 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2228 "was %s\n", nt_errstr(result)));
2230 /* make sure we return something besides OK */
2231 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2235 * Try NetSamLogonEx for AD domains
2237 domain->can_do_samlogon_ex = domain->active_directory;
2239 *cli = conn->netlogon_pipe;
2240 return NT_STATUS_OK;