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 2 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, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 We need to manage connections to domain controllers without having to
29 mess up the main winbindd code with other issues. The aim of the
30 connection manager is to:
32 - make connections to domain controllers and cache them
33 - re-establish connections when networks or servers go down
34 - centralise the policy on connection timeouts, domain controller
36 - manage re-entrancy for when winbindd becomes able to handle
37 multiple outstanding rpc requests
39 Why not have connection management as part of the rpc layer like tng?
40 Good question. This code may morph into libsmb/rpc_cache.c or something
41 like that but at the moment it's simply staying as part of winbind. I
42 think the TNG architecture of forcing every user of the rpc layer to use
43 the connection caching system is a bad idea. It should be an optional
44 method of using the routines.
46 The TNG design is quite good but I disagree with some aspects of the
54 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
55 moved down into another function.
57 - Take care when destroying cli_structs as they can be shared between
66 #define DBGC_CLASS DBGC_WINBIND
73 extern struct winbindd_methods reconnect_methods;
74 extern BOOL override_logfile;
76 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
77 static void set_dc_type_and_flags( struct winbindd_domain *domain );
78 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
79 struct dc_name_ip **dcs, int *num_dcs);
81 /****************************************************************
82 Child failed to find DC's. Reschedule check.
83 ****************************************************************/
85 static void msg_failed_to_go_online(struct messaging_context *msg,
88 struct server_id server_id,
91 struct winbindd_domain *domain;
92 const char *domainname = (const char *)data->data;
94 if (data->data == NULL || data->length == 0) {
98 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
100 for (domain = domain_list(); domain; domain = domain->next) {
101 if (domain->internal) {
105 if (strequal(domain->name, domainname)) {
106 if (domain->online) {
107 /* We're already online, ignore. */
108 DEBUG(5,("msg_fail_to_go_online: domain %s "
109 "already online.\n", domainname));
113 /* Reschedule the online check. */
114 set_domain_offline(domain);
120 /****************************************************************
121 Actually cause a reconnect from a message.
122 ****************************************************************/
124 static void msg_try_to_go_online(struct messaging_context *msg,
127 struct server_id server_id,
130 struct winbindd_domain *domain;
131 const char *domainname = (const char *)data->data;
133 if (data->data == NULL || data->length == 0) {
137 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
139 for (domain = domain_list(); domain; domain = domain->next) {
140 if (domain->internal) {
144 if (strequal(domain->name, domainname)) {
146 if (domain->online) {
147 /* We're already online, ignore. */
148 DEBUG(5,("msg_try_to_go_online: domain %s "
149 "already online.\n", domainname));
153 /* This call takes care of setting the online
154 flag to true if we connected, or re-adding
155 the offline handler if false. Bypasses online
156 check so always does network calls. */
158 init_dc_connection_network(domain);
164 /****************************************************************
165 Fork a child to try and contact a DC. Do this as contacting a
166 DC requires blocking lookups and we don't want to block our
168 ****************************************************************/
170 static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
172 struct dc_name_ip *dcs = NULL;
174 TALLOC_CTX *mem_ctx = NULL;
176 pid_t parent_pid = sys_getpid();
181 child_pid = sys_fork();
183 if (child_pid == -1) {
184 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
188 if (child_pid != 0) {
190 messaging_register(winbind_messaging_context(), NULL,
191 MSG_WINBIND_TRY_TO_GO_ONLINE,
192 msg_try_to_go_online);
193 messaging_register(winbind_messaging_context(), NULL,
194 MSG_WINBIND_FAILED_TO_GO_ONLINE,
195 msg_failed_to_go_online);
201 /* Leave messages blocked - we will never process one. */
203 /* tdb needs special fork handling */
204 if (tdb_reopen_all(1) == -1) {
205 DEBUG(0,("tdb_reopen_all failed.\n"));
209 close_conns_after_fork();
211 if (!override_logfile) {
213 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
214 lp_set_logfile(logfile);
218 mem_ctx = talloc_init("fork_child_dc_connect");
220 DEBUG(0,("talloc_init failed.\n"));
224 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
225 /* Still offline ? Can't find DC's. */
226 messaging_send_buf(winbind_messaging_context(),
227 pid_to_procid(parent_pid),
228 MSG_WINBIND_FAILED_TO_GO_ONLINE,
229 (uint8 *)domain->name,
230 strlen(domain->name)+1);
234 /* We got a DC. Send a message to our parent to get it to
235 try and do the same. */
237 messaging_send_buf(winbind_messaging_context(),
238 pid_to_procid(parent_pid),
239 MSG_WINBIND_TRY_TO_GO_ONLINE,
240 (uint8 *)domain->name,
241 strlen(domain->name)+1);
245 /****************************************************************
246 Handler triggered if we're offline to try and detect a DC.
247 ****************************************************************/
249 static void check_domain_online_handler(struct event_context *ctx,
250 struct timed_event *te,
251 const struct timeval *now,
254 struct winbindd_domain *domain =
255 (struct winbindd_domain *)private_data;
257 DEBUG(10,("check_domain_online_handler: called for domain "
258 "%s (online = %s)\n", domain->name,
259 domain->online ? "True" : "False" ));
261 if (domain->check_online_event) {
262 TALLOC_FREE(domain->check_online_event);
265 /* Are we still in "startup" mode ? */
267 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
268 /* No longer in "startup" mode. */
269 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
271 domain->startup = False;
274 /* We've been told to stay offline, so stay
277 if (get_global_winbindd_state_offline()) {
278 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
283 /* Fork a child to test if it can contact a DC.
284 If it can then send ourselves a message to
285 cause a reconnect. */
287 fork_child_dc_connect(domain);
290 /****************************************************************
291 If we're still offline setup the timeout check.
292 ****************************************************************/
294 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
296 int wbc = lp_winbind_cache_time();
298 if (domain->startup) {
299 domain->check_online_timeout = 10;
300 } else if (domain->check_online_timeout < wbc) {
301 domain->check_online_timeout = wbc;
305 /****************************************************************
306 Set domain offline and also add handler to put us back online
308 ****************************************************************/
310 void set_domain_offline(struct winbindd_domain *domain)
312 DEBUG(10,("set_domain_offline: called for domain %s\n",
315 if (domain->check_online_event) {
316 TALLOC_FREE(domain->check_online_event);
319 if (domain->internal) {
320 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
325 domain->online = False;
327 /* Offline domains are always initialized. They're
328 re-initialized when they go back online. */
330 domain->initialized = True;
332 /* We only add the timeout handler that checks and
333 allows us to go back online when we've not
334 been told to remain offline. */
336 if (get_global_winbindd_state_offline()) {
337 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
342 /* If we're in statup mode, check again in 10 seconds, not in
343 lp_winbind_cache_time() seconds (which is 5 mins by default). */
345 calc_new_online_timeout_check(domain);
347 domain->check_online_event = event_add_timed(winbind_event_context(),
349 timeval_current_ofs(domain->check_online_timeout,0),
350 "check_domain_online_handler",
351 check_domain_online_handler,
354 /* The above *has* to succeed for winbindd to work. */
355 if (!domain->check_online_event) {
356 smb_panic("set_domain_offline: failed to add online handler");
359 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
362 /* Send an offline message to the idmap child when our
363 primary domain goes offline */
365 if ( domain->primary ) {
366 struct winbindd_child *idmap = idmap_child();
368 if ( idmap->pid != 0 ) {
369 messaging_send_buf(winbind_messaging_context(),
370 pid_to_procid(idmap->pid),
372 (uint8 *)domain->name,
373 strlen(domain->name)+1);
380 /****************************************************************
381 Set domain online - if allowed.
382 ****************************************************************/
384 static void set_domain_online(struct winbindd_domain *domain)
388 DEBUG(10,("set_domain_online: called for domain %s\n",
391 if (domain->internal) {
392 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
397 if (get_global_winbindd_state_offline()) {
398 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
403 /* If we are waiting to get a krb5 ticket, trigger immediately. */
405 set_event_dispatch_time(winbind_event_context(),
406 "krb5_ticket_gain_handler", now);
408 /* Ok, we're out of any startup mode now... */
409 domain->startup = False;
411 if (domain->online == False) {
412 /* We were offline - now we're online. We default to
413 using the MS-RPC backend if we started offline,
414 and if we're going online for the first time we
415 should really re-initialize the backends and the
416 checks to see if we're talking to an AD or NT domain.
419 domain->initialized = False;
421 /* 'reconnect_methods' is the MS-RPC backend. */
422 if (domain->backend == &reconnect_methods) {
423 domain->backend = NULL;
427 /* Ensure we have no online timeout checks. */
428 domain->check_online_timeout = 0;
429 if (domain->check_online_event) {
430 TALLOC_FREE(domain->check_online_event);
433 /* Ensure we ignore any pending child messages. */
434 messaging_deregister(winbind_messaging_context(),
435 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
436 messaging_deregister(winbind_messaging_context(),
437 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
439 domain->online = True;
441 /* Send an online message to the idmap child when our
442 primary domain comes online */
444 if ( domain->primary ) {
445 struct winbindd_child *idmap = idmap_child();
447 if ( idmap->pid != 0 ) {
448 messaging_send_buf(winbind_messaging_context(),
449 pid_to_procid(idmap->pid),
451 (uint8 *)domain->name,
452 strlen(domain->name)+1);
459 /****************************************************************
460 Requested to set a domain online.
461 ****************************************************************/
463 void set_domain_online_request(struct winbindd_domain *domain)
467 DEBUG(10,("set_domain_online_request: called for domain %s\n",
470 if (get_global_winbindd_state_offline()) {
471 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
476 /* We've been told it's safe to go online and
477 try and connect to a DC. But I don't believe it
478 because network manager seems to lie.
479 Wait at least 5 seconds. Heuristics suck... */
481 if (!domain->check_online_event) {
482 /* If we've come from being globally offline we
483 don't have a check online event handler set.
484 We need to add one now we're trying to go
487 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
490 domain->check_online_event = event_add_timed(winbind_event_context(),
492 timeval_current_ofs(5, 0),
493 "check_domain_online_handler",
494 check_domain_online_handler,
497 /* The above *has* to succeed for winbindd to work. */
498 if (!domain->check_online_event) {
499 smb_panic("set_domain_online_request: failed to add online handler");
505 /* Go into "startup" mode again. */
506 domain->startup_time = tev.tv_sec;
507 domain->startup = True;
511 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
514 /****************************************************************
515 Add -ve connection cache entries for domain and realm.
516 ****************************************************************/
518 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
522 add_failed_connection_entry(domain->name, server, result);
523 /* If this was the saf name for the last thing we talked to,
525 saf_delete(domain->name);
526 if (*domain->alt_name) {
527 add_failed_connection_entry(domain->alt_name, server, result);
528 saf_delete(domain->alt_name);
532 /* Choose between anonymous or authenticated connections. We need to use
533 an authenticated connection if DCs have the RestrictAnonymous registry
534 entry set > 0, or the "Additional restrictions for anonymous
535 connections" set in the win2k Local Security Policy.
537 Caller to free() result in domain, username, password
540 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
542 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
543 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
544 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
546 if (*username && **username) {
548 if (!*domain || !**domain)
549 *domain = smb_xstrdup(lp_workgroup());
551 if (!*password || !**password)
552 *password = smb_xstrdup("");
554 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
555 *domain, *username));
558 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
559 *username = smb_xstrdup("");
560 *domain = smb_xstrdup("");
561 *password = smb_xstrdup("");
565 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
566 fstring dcname, struct in_addr *dc_ip)
568 struct winbindd_domain *our_domain = NULL;
569 struct rpc_pipe_client *netlogon_pipe = NULL;
573 unsigned int orig_timeout;
577 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
584 if (domain->primary) {
588 our_domain = find_our_domain();
590 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
594 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
595 if (!NT_STATUS_IS_OK(result)) {
596 talloc_destroy(mem_ctx);
600 /* This call can take a long time - allow the server to time out.
601 35 seconds should do it. */
603 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
605 werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
608 /* And restore our original timeout. */
609 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
611 talloc_destroy(mem_ctx);
613 if (!W_ERROR_IS_OK(werr)) {
614 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
619 /* cli_netlogon_getanydcname gives us a name with \\ */
630 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
632 if (!resolve_name(dcname, dc_ip, 0x20)) {
639 /************************************************************************
640 Given a fd with a just-connected TCP connection to a DC, open a connection
642 ************************************************************************/
644 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
646 const char *controller,
647 struct cli_state **cli,
650 char *machine_password, *machine_krb5_principal, *machine_account;
651 char *ipc_username, *ipc_domain, *ipc_password;
655 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
657 struct sockaddr peeraddr;
658 socklen_t peeraddr_len;
660 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
662 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
663 controller, domain->name ));
665 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
668 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
669 SAFE_FREE(machine_password);
670 return NT_STATUS_NO_MEMORY;
673 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
675 SAFE_FREE(machine_account);
676 SAFE_FREE(machine_password);
677 return NT_STATUS_NO_MEMORY;
680 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
684 got_mutex = secrets_named_mutex(controller,
685 WINBIND_SERVER_MUTEX_WAIT_TIME);
688 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
690 result = NT_STATUS_POSSIBLE_DEADLOCK;
694 if ((*cli = cli_initialise()) == NULL) {
695 DEBUG(1, ("Could not cli_initialize\n"));
696 result = NT_STATUS_NO_MEMORY;
700 (*cli)->timeout = 10000; /* 10 seconds */
702 fstrcpy((*cli)->desthost, controller);
703 (*cli)->use_kerberos = True;
705 peeraddr_len = sizeof(peeraddr);
707 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
708 (peeraddr_len != sizeof(struct sockaddr_in)) ||
709 (peeraddr_in->sin_family != PF_INET))
711 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
712 result = NT_STATUS_UNSUCCESSFUL;
716 if (ntohs(peeraddr_in->sin_port) == 139) {
717 struct nmb_name calling;
718 struct nmb_name called;
720 make_nmb_name(&calling, global_myname(), 0x0);
721 make_nmb_name(&called, "*SMBSERVER", 0x20);
723 if (!cli_session_request(*cli, &calling, &called)) {
724 DEBUG(8, ("cli_session_request failed for %s\n",
726 result = NT_STATUS_UNSUCCESSFUL;
731 cli_setup_signing_state(*cli, Undefined);
733 if (!cli_negprot(*cli)) {
734 DEBUG(1, ("cli_negprot failed\n"));
735 result = NT_STATUS_UNSUCCESSFUL;
739 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
740 ADS_STATUS ads_status;
742 if (lp_security() == SEC_ADS) {
744 /* Try a krb5 session */
746 (*cli)->use_kerberos = True;
747 DEBUG(5, ("connecting to %s from %s with kerberos principal "
748 "[%s]\n", controller, global_myname(),
749 machine_krb5_principal));
751 ads_status = cli_session_setup_spnego(*cli,
752 machine_krb5_principal,
756 if (!ADS_ERR_OK(ads_status)) {
757 DEBUG(4,("failed kerberos session setup with %s\n",
758 ads_errstr(ads_status)));
761 result = ads_ntstatus(ads_status);
762 if (NT_STATUS_IS_OK(result)) {
763 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
764 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
765 goto session_setup_done;
769 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
770 (*cli)->use_kerberos = False;
772 DEBUG(5, ("connecting to %s from %s with username "
773 "[%s]\\[%s]\n", controller, global_myname(),
774 lp_workgroup(), machine_account));
776 ads_status = cli_session_setup_spnego(*cli,
780 if (!ADS_ERR_OK(ads_status)) {
781 DEBUG(4, ("authenticated session setup failed with %s\n",
782 ads_errstr(ads_status)));
785 result = ads_ntstatus(ads_status);
786 if (NT_STATUS_IS_OK(result)) {
787 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
788 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
789 goto session_setup_done;
793 /* Fall back to non-kerberos session setup */
795 (*cli)->use_kerberos = False;
797 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
798 (strlen(ipc_username) > 0)) {
800 /* Only try authenticated if we have a username */
802 DEBUG(5, ("connecting to %s from %s with username "
803 "[%s]\\[%s]\n", controller, global_myname(),
804 ipc_domain, ipc_username));
806 if (NT_STATUS_IS_OK(cli_session_setup(
808 ipc_password, strlen(ipc_password)+1,
809 ipc_password, strlen(ipc_password)+1,
811 /* Successful logon with given username. */
812 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
813 goto session_setup_done;
815 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
816 ipc_domain, ipc_username ));
820 /* Fall back to anonymous connection, this might fail later */
822 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
824 DEBUG(5, ("Connected anonymously\n"));
825 cli_init_creds(*cli, "", "", "");
826 goto session_setup_done;
829 result = cli_nt_error(*cli);
831 if (NT_STATUS_IS_OK(result))
832 result = NT_STATUS_UNSUCCESSFUL;
834 /* We can't session setup */
840 /* cache the server name for later connections */
842 saf_store( domain->name, (*cli)->desthost );
843 if (domain->alt_name && (*cli)->use_kerberos) {
844 saf_store( domain->alt_name, (*cli)->desthost );
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 SAFE_FREE(sitename);
1100 /* Ensure we contact this DC also. */
1101 saf_store( domain->name, name);
1102 saf_store( domain->alt_name, name);
1105 ads_destroy( &ads );
1109 ads_destroy( &ads );
1113 /* try GETDC requests next */
1115 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1118 for (i=0; i<5; i++) {
1119 if (receive_getdc_response(ip, domain->name, name)) {
1120 namecache_store(name, 0x20, 1, &ip_list);
1127 /* try node status request */
1129 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1130 namecache_store(name, 0x20, 1, &ip_list);
1136 /*******************************************************************
1137 Retreive a list of IP address for domain controllers. Fill in
1138 the dcs[] with results.
1139 *******************************************************************/
1141 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1142 struct dc_name_ip **dcs, int *num_dcs)
1146 struct ip_service *ip_list = NULL;
1147 int iplist_size = 0;
1150 enum security_types sec = (enum security_types)lp_security();
1152 is_our_domain = strequal(domain->name, lp_workgroup());
1155 && get_dc_name_via_netlogon(domain, dcname, &ip)
1156 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1158 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1159 dcname, inet_ntoa(ip)));
1163 if (sec == SEC_ADS) {
1164 char *sitename = NULL;
1166 /* We need to make sure we know the local site before
1167 doing any DNS queries, as this will restrict the
1168 get_sorted_dc_list() call below to only fetching
1169 DNS records for the correct site. */
1171 /* Find any DC to get the site record.
1172 We deliberately don't care about the
1175 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1177 sitename = sitename_fetch(domain->alt_name);
1180 /* Do the site-specific AD dns lookup first. */
1181 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1183 for ( i=0; i<iplist_size; i++ ) {
1184 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1185 ip_list[i].ip, dcs, num_dcs);
1189 SAFE_FREE(sitename);
1193 /* Now we add DCs from the main AD dns lookup. */
1194 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1196 for ( i=0; i<iplist_size; i++ ) {
1197 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1198 ip_list[i].ip, dcs, num_dcs);
1202 /* try standard netbios queries if no ADS */
1204 if (iplist_size==0) {
1205 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1208 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1210 /* now add to the dc array. We'll wait until the last minute
1211 to look up the name of the DC. But we fill in the char* for
1212 the ip now in to make the failed connection cache work */
1214 for ( i=0; i<iplist_size; i++ ) {
1215 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1216 ip_list[i].ip, dcs, num_dcs);
1219 SAFE_FREE( ip_list );
1224 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1225 const struct winbindd_domain *domain,
1226 fstring dcname, struct sockaddr_in *addr, int *fd)
1228 struct dc_name_ip *dcs = NULL;
1231 const char **dcnames = NULL;
1232 int num_dcnames = 0;
1234 struct sockaddr_in *addrs = NULL;
1240 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1243 for (i=0; i<num_dcs; i++) {
1245 if (!add_string_to_array(mem_ctx, dcs[i].name,
1246 &dcnames, &num_dcnames)) {
1249 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1250 &addrs, &num_addrs)) {
1254 if (!add_string_to_array(mem_ctx, dcs[i].name,
1255 &dcnames, &num_dcnames)) {
1258 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1259 &addrs, &num_addrs)) {
1264 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1267 if ((addrs == NULL) || (dcnames == NULL))
1270 /* 5 second timeout. */
1271 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1273 for (i=0; i<num_dcs; i++) {
1274 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1275 "domain %s address %s. Error was %s\n",
1276 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1277 winbind_add_failed_connection_entry(domain,
1278 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1283 *addr = addrs[fd_index];
1285 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1286 /* Ok, we've got a name for the DC */
1287 fstrcpy(dcname, dcnames[fd_index]);
1291 /* Try to figure out the name */
1292 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1296 /* We can not continue without the DC's name */
1297 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1298 NT_STATUS_UNSUCCESSFUL);
1302 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1303 struct winbindd_cm_conn *new_conn)
1305 TALLOC_CTX *mem_ctx;
1307 char *saf_servername = saf_fetch( domain->name );
1310 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1311 SAFE_FREE(saf_servername);
1312 set_domain_offline(domain);
1313 return NT_STATUS_NO_MEMORY;
1316 /* we have to check the server affinity cache here since
1317 later we selecte a DC based on response time and not preference */
1319 /* Check the negative connection cache
1320 before talking to it. It going down may have
1321 triggered the reconnection. */
1323 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1325 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1326 saf_servername, domain->name ));
1328 /* convert an ip address to a name */
1329 if ( is_ipaddress( saf_servername ) ) {
1333 ip = *interpret_addr2( saf_servername );
1334 if (dcip_to_name( domain, ip, saf_name )) {
1335 fstrcpy( domain->dcname, saf_name );
1337 winbind_add_failed_connection_entry(
1338 domain, saf_servername,
1339 NT_STATUS_UNSUCCESSFUL);
1342 fstrcpy( domain->dcname, saf_servername );
1345 SAFE_FREE( saf_servername );
1348 for (retries = 0; retries < 3; retries++) {
1353 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1355 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1356 domain->dcname, domain->name ));
1359 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1360 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1362 struct sockaddr_in *addrs = NULL;
1366 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1367 set_domain_offline(domain);
1368 talloc_destroy(mem_ctx);
1369 return NT_STATUS_NO_MEMORY;
1371 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1372 set_domain_offline(domain);
1373 talloc_destroy(mem_ctx);
1374 return NT_STATUS_NO_MEMORY;
1377 /* 5 second timeout. */
1378 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1384 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1386 /* This is the one place where we will
1387 set the global winbindd offline state
1388 to true, if a "WINBINDD_OFFLINE" entry
1389 is found in the winbindd cache. */
1390 set_global_winbindd_state_offline();
1394 new_conn->cli = NULL;
1396 result = cm_prepare_connection(domain, fd, domain->dcname,
1397 &new_conn->cli, &retry);
1403 if (NT_STATUS_IS_OK(result)) {
1404 if (domain->online == False) {
1405 /* We're changing state from offline to online. */
1406 set_global_winbindd_state_online();
1408 set_domain_online(domain);
1410 /* Ensure we setup the retry handler. */
1411 set_domain_offline(domain);
1414 talloc_destroy(mem_ctx);
1418 /* Close down all open pipes on a connection. */
1420 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1422 /* We're closing down a possibly dead
1423 connection. Don't have impossibly long (10s) timeouts. */
1426 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1429 if (conn->samr_pipe != NULL) {
1430 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1431 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1433 cli_set_timeout(conn->cli, 500);
1436 conn->samr_pipe = NULL;
1439 if (conn->lsa_pipe != NULL) {
1440 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1441 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1443 cli_set_timeout(conn->cli, 500);
1446 conn->lsa_pipe = NULL;
1449 if (conn->netlogon_pipe != NULL) {
1450 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1451 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1453 cli_set_timeout(conn->cli, 500);
1456 conn->netlogon_pipe = NULL;
1460 cli_shutdown(conn->cli);
1466 void close_conns_after_fork(void)
1468 struct winbindd_domain *domain;
1470 for (domain = domain_list(); domain; domain = domain->next) {
1471 if (domain->conn.cli == NULL)
1474 if (domain->conn.cli->fd == -1)
1477 close(domain->conn.cli->fd);
1478 domain->conn.cli->fd = -1;
1482 static BOOL connection_ok(struct winbindd_domain *domain)
1484 if (domain->conn.cli == NULL) {
1485 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1486 "cli!\n", domain->dcname, domain->name));
1490 if (!domain->conn.cli->initialised) {
1491 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1492 "initialised!\n", domain->dcname, domain->name));
1496 if (domain->conn.cli->fd == -1) {
1497 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1498 "never started (fd == -1)\n",
1499 domain->dcname, domain->name));
1503 if (domain->online == False) {
1504 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1511 /* Initialize a new connection up to the RPC BIND.
1512 Bypass online status check so always does network calls. */
1514 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1518 /* Internal connections never use the network. */
1519 if (domain->internal) {
1520 domain->initialized = True;
1521 return NT_STATUS_OK;
1524 if (connection_ok(domain)) {
1525 if (!domain->initialized) {
1526 set_dc_type_and_flags(domain);
1528 return NT_STATUS_OK;
1531 invalidate_cm_connection(&domain->conn);
1533 result = cm_open_connection(domain, &domain->conn);
1535 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1536 set_dc_type_and_flags(domain);
1542 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1544 if (domain->initialized && !domain->online) {
1545 /* We check for online status elsewhere. */
1546 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1549 return init_dc_connection_network(domain);
1552 /******************************************************************************
1553 Set the trust flags (direction and forest location) for a domain
1554 ******************************************************************************/
1556 static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1558 struct winbindd_domain *our_domain;
1559 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1560 struct ds_domain_trust *domains = NULL;
1563 uint32 flags = (DS_DOMAIN_IN_FOREST |
1564 DS_DOMAIN_DIRECT_OUTBOUND |
1565 DS_DOMAIN_DIRECT_INBOUND);
1566 struct rpc_pipe_client *cli;
1567 TALLOC_CTX *mem_ctx = NULL;
1569 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1571 /* Our primary domain doesn't need to worry about trust flags.
1572 Force it to go through the network setup */
1573 if ( domain->primary ) {
1577 our_domain = find_our_domain();
1579 if ( !connection_ok(our_domain) ) {
1580 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1584 /* This won't work unless our domain is AD */
1586 if ( !our_domain->active_directory ) {
1590 /* Use DsEnumerateDomainTrusts to get us the trust direction
1593 result = cm_connect_netlogon(our_domain, &cli);
1595 if (!NT_STATUS_IS_OK(result)) {
1596 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1597 "a connection to %s for PIPE_NETLOGON (%s)\n",
1598 domain->name, nt_errstr(result)));
1602 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1603 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1607 result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
1610 (unsigned int *)&count);
1612 /* Now find the domain name and get the flags */
1614 for ( i=0; i<count; i++ ) {
1615 if ( strequal( domain->name, domains[i].netbios_domain ) ) {
1616 domain->domain_flags = domains[i].flags;
1617 domain->domain_type = domains[i].trust_type;
1618 domain->domain_trust_attribs = domains[i].trust_attributes;
1620 if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
1621 domain->active_directory = True;
1623 /* This flag is only set if the domain is *our*
1624 primary domain and the primary domain is in
1627 domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
1629 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1630 "native mode.\n", domain->name,
1631 domain->native_mode ? "" : "NOT "));
1633 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1634 "running active directory.\n", domain->name,
1635 domain->active_directory ? "" : "NOT "));
1638 domain->initialized = True;
1640 if ( !winbindd_can_contact_domain( domain) )
1641 domain->internal = True;
1647 talloc_destroy( mem_ctx );
1649 return domain->initialized;
1652 /******************************************************************************
1653 We can 'sense' certain things about the DC by it's replies to certain
1656 This tells us if this particular remote server is Active Directory, and if it
1658 ******************************************************************************/
1660 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1664 TALLOC_CTX *mem_ctx = NULL;
1665 struct rpc_pipe_client *cli;
1668 char *domain_name = NULL;
1669 char *dns_name = NULL;
1670 char *forest_name = NULL;
1671 DOM_SID *dom_sid = NULL;
1675 if (!connection_ok(domain)) {
1679 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1681 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1685 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1686 "PI_LSARPC_DS on domain %s: (%s)\n",
1687 domain->name, nt_errstr(result)));
1689 /* if this is just a non-AD domain we need to continue
1690 * identifying so that we can in the end return with
1691 * domain->initialized = True - gd */
1696 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1697 DsRolePrimaryDomainInfoBasic,
1699 cli_rpc_pipe_close(cli);
1701 if (!NT_STATUS_IS_OK(result)) {
1702 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1703 "on domain %s failed: (%s)\n",
1704 domain->name, nt_errstr(result)));
1708 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1709 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1710 domain->native_mode = True;
1712 domain->native_mode = False;
1716 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1719 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1720 "PI_LSARPC on domain %s: (%s)\n",
1721 domain->name, nt_errstr(result)));
1722 cli_rpc_pipe_close(cli);
1726 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1729 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1730 cli_rpc_pipe_close(cli);
1734 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1735 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1737 if (NT_STATUS_IS_OK(result)) {
1738 /* This particular query is exactly what Win2k clients use
1739 to determine that the DC is active directory */
1740 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1742 &dns_name, &forest_name,
1746 if (NT_STATUS_IS_OK(result)) {
1747 domain->active_directory = True;
1750 fstrcpy(domain->name, domain_name);
1753 fstrcpy(domain->alt_name, dns_name);
1756 fstrcpy(domain->forest_name, forest_name);
1759 sid_copy(&domain->sid, dom_sid);
1761 domain->active_directory = False;
1763 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1764 SEC_RIGHTS_MAXIMUM_ALLOWED,
1767 if (!NT_STATUS_IS_OK(result))
1770 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1771 &pol, 5, &domain_name,
1774 if (NT_STATUS_IS_OK(result)) {
1776 fstrcpy(domain->name, domain_name);
1779 sid_copy(&domain->sid, dom_sid);
1784 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1785 domain->name, domain->native_mode ? "" : "NOT "));
1787 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1788 domain->name, domain->active_directory ? "" : "NOT "));
1790 cli_rpc_pipe_close(cli);
1792 talloc_destroy(mem_ctx);
1794 domain->initialized = True;
1797 /**********************************************************************
1798 Set the domain_flags (trust attributes, domain operating modes, etc...
1799 ***********************************************************************/
1801 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1803 /* we always have to contact our primary domain */
1805 if ( domain->primary ) {
1806 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1807 "primary domain\n"));
1808 set_dc_type_and_flags_connect( domain );
1812 /* Use our DC to get the information if possible */
1814 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1815 /* Otherwise, fallback to contacting the
1817 set_dc_type_and_flags_connect( domain );
1825 /**********************************************************************
1826 ***********************************************************************/
1828 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1829 struct dcinfo **ppdc)
1832 struct rpc_pipe_client *netlogon_pipe;
1834 if (lp_client_schannel() == False) {
1838 result = cm_connect_netlogon(domain, &netlogon_pipe);
1839 if (!NT_STATUS_IS_OK(result)) {
1843 /* Return a pointer to the struct dcinfo from the
1846 *ppdc = domain->conn.netlogon_pipe->dc;
1850 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1851 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1853 struct winbindd_cm_conn *conn;
1854 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1856 struct dcinfo *p_dcinfo;
1858 result = init_dc_connection(domain);
1859 if (!NT_STATUS_IS_OK(result)) {
1863 conn = &domain->conn;
1865 if (conn->samr_pipe != NULL) {
1870 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1871 * sign and sealed pipe using the machine account password by
1872 * preference. If we can't - try schannel, if that fails, try
1876 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1877 if ((conn->cli->user_name[0] == '\0') ||
1878 (conn->cli->domain[0] == '\0') ||
1879 (conn_pwd[0] == '\0')) {
1880 DEBUG(10, ("cm_connect_sam: No no user available for "
1881 "domain %s, trying schannel\n", conn->cli->domain));
1885 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1886 authenticated SAMR pipe with sign & seal. */
1888 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1889 PIPE_AUTH_LEVEL_PRIVACY,
1891 conn->cli->user_name,
1894 if (conn->samr_pipe == NULL) {
1895 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1896 "pipe for domain %s using NTLMSSP "
1897 "authenticated pipe: user %s\\%s. Error was "
1898 "%s\n", domain->name, conn->cli->domain,
1899 conn->cli->user_name, nt_errstr(result)));
1903 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1904 "domain %s using NTLMSSP authenticated "
1905 "pipe: user %s\\%s\n", domain->name,
1906 conn->cli->domain, conn->cli->user_name ));
1908 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1909 SEC_RIGHTS_MAXIMUM_ALLOWED,
1910 &conn->sam_connect_handle);
1911 if (NT_STATUS_IS_OK(result)) {
1914 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1915 "failed for domain %s, error was %s. Trying schannel\n",
1916 domain->name, nt_errstr(result) ));
1917 cli_rpc_pipe_close(conn->samr_pipe);
1921 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1923 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1924 /* If this call fails - conn->cli can now be NULL ! */
1925 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1926 "for domain %s, trying anon\n", domain->name));
1929 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1930 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1931 domain->name, p_dcinfo, &result);
1933 if (conn->samr_pipe == NULL) {
1934 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1935 "domain %s using schannel. Error was %s\n",
1936 domain->name, nt_errstr(result) ));
1939 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1940 "schannel.\n", domain->name ));
1942 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1943 SEC_RIGHTS_MAXIMUM_ALLOWED,
1944 &conn->sam_connect_handle);
1945 if (NT_STATUS_IS_OK(result)) {
1948 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1949 "for domain %s, error was %s. Trying anonymous\n",
1950 domain->name, nt_errstr(result) ));
1951 cli_rpc_pipe_close(conn->samr_pipe);
1955 /* Finally fall back to anonymous. */
1956 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1959 if (conn->samr_pipe == NULL) {
1960 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1964 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1965 SEC_RIGHTS_MAXIMUM_ALLOWED,
1966 &conn->sam_connect_handle);
1967 if (!NT_STATUS_IS_OK(result)) {
1968 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1969 "for domain %s Error was %s\n",
1970 domain->name, nt_errstr(result) ));
1975 result = rpccli_samr_open_domain(conn->samr_pipe,
1977 &conn->sam_connect_handle,
1978 SEC_RIGHTS_MAXIMUM_ALLOWED,
1980 &conn->sam_domain_handle);
1984 if (!NT_STATUS_IS_OK(result)) {
1985 invalidate_cm_connection(conn);
1989 *cli = conn->samr_pipe;
1990 *sam_handle = conn->sam_domain_handle;
1994 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1995 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1997 struct winbindd_cm_conn *conn;
1998 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2000 struct dcinfo *p_dcinfo;
2002 result = init_dc_connection(domain);
2003 if (!NT_STATUS_IS_OK(result))
2006 conn = &domain->conn;
2008 if (conn->lsa_pipe != NULL) {
2012 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2013 if ((conn->cli->user_name[0] == '\0') ||
2014 (conn->cli->domain[0] == '\0') ||
2015 (conn_pwd[0] == '\0')) {
2016 DEBUG(10, ("cm_connect_lsa: No no user available for "
2017 "domain %s, trying schannel\n", conn->cli->domain));
2021 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2022 * authenticated LSA pipe with sign & seal. */
2023 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
2024 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2025 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
2027 if (conn->lsa_pipe == NULL) {
2028 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2029 "domain %s using NTLMSSP authenticated pipe: user "
2030 "%s\\%s. Error was %s. Trying schannel.\n",
2031 domain->name, conn->cli->domain,
2032 conn->cli->user_name, nt_errstr(result)));
2036 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2037 "NTLMSSP authenticated pipe: user %s\\%s\n",
2038 domain->name, conn->cli->domain, conn->cli->user_name ));
2040 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2041 SEC_RIGHTS_MAXIMUM_ALLOWED,
2043 if (NT_STATUS_IS_OK(result)) {
2047 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2050 cli_rpc_pipe_close(conn->lsa_pipe);
2054 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2056 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2057 /* If this call fails - conn->cli can now be NULL ! */
2058 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2059 "for domain %s, trying anon\n", domain->name));
2062 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2063 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2064 domain->name, p_dcinfo, &result);
2066 if (conn->lsa_pipe == NULL) {
2067 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2068 "domain %s using schannel. Error was %s\n",
2069 domain->name, nt_errstr(result) ));
2072 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2073 "schannel.\n", domain->name ));
2075 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2076 SEC_RIGHTS_MAXIMUM_ALLOWED,
2078 if (NT_STATUS_IS_OK(result)) {
2082 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2085 cli_rpc_pipe_close(conn->lsa_pipe);
2089 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2091 if (conn->lsa_pipe == NULL) {
2092 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2096 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2097 SEC_RIGHTS_MAXIMUM_ALLOWED,
2100 if (!NT_STATUS_IS_OK(result)) {
2101 invalidate_cm_connection(conn);
2105 *cli = conn->lsa_pipe;
2106 *lsa_policy = conn->lsa_policy;
2110 /****************************************************************************
2111 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2112 session key stored in conn->netlogon_pipe->dc->sess_key.
2113 ****************************************************************************/
2115 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2116 struct rpc_pipe_client **cli)
2118 struct winbindd_cm_conn *conn;
2121 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2123 uint32 sec_chan_type;
2124 const char *account_name;
2125 struct rpc_pipe_client *netlogon_pipe = NULL;
2129 result = init_dc_connection(domain);
2130 if (!NT_STATUS_IS_OK(result)) {
2134 conn = &domain->conn;
2136 if (conn->netlogon_pipe != NULL) {
2137 *cli = conn->netlogon_pipe;
2138 return NT_STATUS_OK;
2141 if (domain->primary && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
2142 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2145 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2147 if (netlogon_pipe == NULL) {
2151 if ( !domain->primary ) {
2152 /* Clear the schannel request bit and drop down */
2153 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2157 if (lp_client_schannel() != False) {
2158 neg_flags |= NETLOGON_NEG_SCHANNEL;
2161 /* if we are a DC and this is a trusted domain, then we need to use our
2162 domain name in the net_req_auth2() request */
2165 && !strequal(domain->name, lp_workgroup())
2166 && lp_allow_trusted_domains() )
2168 account_name = lp_workgroup();
2170 account_name = domain->primary ?
2171 global_myname() : domain->name;
2174 if (account_name == NULL) {
2175 cli_rpc_pipe_close(netlogon_pipe);
2176 return NT_STATUS_NO_MEMORY;
2179 result = rpccli_netlogon_setup_creds(
2181 domain->dcname, /* server name. */
2182 domain->name, /* domain name */
2183 global_myname(), /* client name */
2184 account_name, /* machine account */
2185 mach_pwd, /* machine password */
2186 sec_chan_type, /* from get_trust_pw */
2189 if (!NT_STATUS_IS_OK(result)) {
2190 cli_rpc_pipe_close(netlogon_pipe);
2194 if ((lp_client_schannel() == True) &&
2195 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2196 DEBUG(3, ("Server did not offer schannel\n"));
2197 cli_rpc_pipe_close(netlogon_pipe);
2198 return NT_STATUS_ACCESS_DENIED;
2202 if ((lp_client_schannel() == False) ||
2203 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2206 * NetSamLogonEx only works for schannel
2208 domain->can_do_samlogon_ex = False;
2210 /* We're done - just keep the existing connection to NETLOGON
2212 conn->netlogon_pipe = netlogon_pipe;
2213 *cli = conn->netlogon_pipe;
2214 return NT_STATUS_OK;
2217 /* Using the credentials from the first pipe, open a signed and sealed
2218 second netlogon pipe. The session key is stored in the schannel
2219 part of the new pipe auth struct.
2222 conn->netlogon_pipe =
2223 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2225 PIPE_AUTH_LEVEL_PRIVACY,
2230 /* We can now close the initial netlogon pipe. */
2231 cli_rpc_pipe_close(netlogon_pipe);
2233 if (conn->netlogon_pipe == NULL) {
2234 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2235 "was %s\n", nt_errstr(result)));
2237 /* make sure we return something besides OK */
2238 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2242 * Try NetSamLogonEx for AD domains
2244 domain->can_do_samlogon_ex = domain->active_directory;
2246 *cli = conn->netlogon_pipe;
2247 return NT_STATUS_OK;