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(int msg_type, struct process_id src, void *buf, size_t len)
87 struct winbindd_domain *domain;
88 const char *domainname = (const char *)buf;
90 if (buf == NULL || len == 0) {
94 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
96 for (domain = domain_list(); domain; domain = domain->next) {
97 if (domain->internal) {
101 if (strequal(domain->name, domainname)) {
102 if (domain->online) {
103 /* We're already online, ignore. */
104 DEBUG(5,("msg_fail_to_go_online: domain %s "
105 "already online.\n", domainname));
109 /* Reschedule the online check. */
110 set_domain_offline(domain);
116 /****************************************************************
117 Actually cause a reconnect from a message.
118 ****************************************************************/
120 static void msg_try_to_go_online(int msg_type, struct process_id src, void *buf, size_t len)
122 struct winbindd_domain *domain;
123 const char *domainname = (const char *)buf;
125 if (buf == NULL || len == 0) {
129 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
131 for (domain = domain_list(); domain; domain = domain->next) {
132 if (domain->internal) {
136 if (strequal(domain->name, domainname)) {
138 if (domain->online) {
139 /* We're already online, ignore. */
140 DEBUG(5,("msg_try_to_go_online: domain %s "
141 "already online.\n", domainname));
145 /* This call takes care of setting the online
146 flag to true if we connected, or re-adding
147 the offline handler if false. Bypasses online
148 check so always does network calls. */
150 init_dc_connection_network(domain);
156 /****************************************************************
157 Fork a child to try and contact a DC. Do this as contacting a
158 DC requires blocking lookups and we don't want to block our
160 ****************************************************************/
162 static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
164 struct dc_name_ip *dcs = NULL;
166 TALLOC_CTX *mem_ctx = NULL;
168 pid_t parent_pid = sys_getpid();
175 child_pid = sys_fork();
177 if (child_pid == -1) {
178 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
183 if (child_pid != 0) {
185 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,msg_try_to_go_online);
186 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,msg_failed_to_go_online);
193 /* Leave messages blocked - we will never process one. */
195 /* tdb needs special fork handling */
196 if (tdb_reopen_all(1) == -1) {
197 DEBUG(0,("tdb_reopen_all failed.\n"));
201 close_conns_after_fork();
203 if (!override_logfile) {
205 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
206 lp_set_logfile(logfile);
210 mem_ctx = talloc_init("fork_child_dc_connect");
212 DEBUG(0,("talloc_init failed.\n"));
216 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
217 /* Still offline ? Can't find DC's. */
218 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
220 strlen(domain->name)+1, False);
224 /* We got a DC. Send a message to our parent to get it to
225 try and do the same. */
227 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
229 strlen(domain->name)+1, False);
233 /****************************************************************
234 Handler triggered if we're offline to try and detect a DC.
235 ****************************************************************/
237 static void check_domain_online_handler(struct event_context *ctx,
238 struct timed_event *te,
239 const struct timeval *now,
242 struct winbindd_domain *domain =
243 (struct winbindd_domain *)private_data;
245 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
248 if (domain->check_online_event) {
249 TALLOC_FREE(domain->check_online_event);
252 /* Are we still in "startup" mode ? */
254 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
255 /* No longer in "startup" mode. */
256 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
258 domain->startup = False;
261 /* We've been told to stay offline, so stay
264 if (get_global_winbindd_state_offline()) {
265 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
270 /* Fork a child to test if it can contact a DC.
271 If it can then send ourselves a message to
272 cause a reconnect. */
274 fork_child_dc_connect(domain);
277 /****************************************************************
278 If we're still offline setup the timeout check.
279 ****************************************************************/
281 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
283 int wbc = lp_winbind_cache_time();
285 if (domain->startup) {
286 domain->check_online_timeout = 10;
287 } else if (domain->check_online_timeout < wbc) {
288 domain->check_online_timeout = wbc;
292 /****************************************************************
293 Set domain offline and also add handler to put us back online
295 ****************************************************************/
297 void set_domain_offline(struct winbindd_domain *domain)
299 DEBUG(10,("set_domain_offline: called for domain %s\n",
302 if (domain->check_online_event) {
303 TALLOC_FREE(domain->check_online_event);
306 if (domain->internal) {
307 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
312 domain->online = False;
314 /* Offline domains are always initialized. They're
315 re-initialized when they go back online. */
317 domain->initialized = True;
319 /* We only add the timeout handler that checks and
320 allows us to go back online when we've not
321 been told to remain offline. */
323 if (get_global_winbindd_state_offline()) {
324 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
329 /* If we're in statup mode, check again in 10 seconds, not in
330 lp_winbind_cache_time() seconds (which is 5 mins by default). */
332 calc_new_online_timeout_check(domain);
334 domain->check_online_event = event_add_timed(winbind_event_context(),
336 timeval_current_ofs(domain->check_online_timeout,0),
337 "check_domain_online_handler",
338 check_domain_online_handler,
341 /* The above *has* to succeed for winbindd to work. */
342 if (!domain->check_online_event) {
343 smb_panic("set_domain_offline: failed to add online handler.\n");
346 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
350 /****************************************************************
351 Set domain online - if allowed.
352 ****************************************************************/
354 static void set_domain_online(struct winbindd_domain *domain)
358 DEBUG(10,("set_domain_online: called for domain %s\n",
361 if (domain->internal) {
362 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
367 if (get_global_winbindd_state_offline()) {
368 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
373 /* If we are waiting to get a krb5 ticket, trigger immediately. */
375 set_event_dispatch_time(winbind_event_context(),
376 "krb5_ticket_gain_handler", now);
378 /* Ok, we're out of any startup mode now... */
379 domain->startup = False;
381 if (domain->online == False) {
382 /* We were offline - now we're online. We default to
383 using the MS-RPC backend if we started offline,
384 and if we're going online for the first time we
385 should really re-initialize the backends and the
386 checks to see if we're talking to an AD or NT domain.
389 domain->initialized = False;
391 /* 'reconnect_methods' is the MS-RPC backend. */
392 if (domain->backend == &reconnect_methods) {
393 domain->backend = NULL;
397 /* Ensure we have no online timeout checks. */
398 domain->check_online_timeout = 0;
399 if (domain->check_online_event) {
400 TALLOC_FREE(domain->check_online_event);
403 /* Ensure we ignore any pending child messages. */
404 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
405 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
407 domain->online = True;
410 /****************************************************************
411 Requested to set a domain online.
412 ****************************************************************/
414 void set_domain_online_request(struct winbindd_domain *domain)
418 DEBUG(10,("set_domain_online_request: called for domain %s\n",
421 if (get_global_winbindd_state_offline()) {
422 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
427 /* We've been told it's safe to go online and
428 try and connect to a DC. But I don't believe it
429 because network manager seems to lie.
430 Wait at least 5 seconds. Heuristics suck... */
432 if (!domain->check_online_event) {
433 /* If we've come from being globally offline we
434 don't have a check online event handler set.
435 We need to add one now we're trying to go
438 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
441 domain->check_online_event = event_add_timed(winbind_event_context(),
443 timeval_current_ofs(5, 0),
444 "check_domain_online_handler",
445 check_domain_online_handler,
448 /* The above *has* to succeed for winbindd to work. */
449 if (!domain->check_online_event) {
450 smb_panic("set_domain_online_request: failed to add online handler.\n");
456 /* Go into "startup" mode again. */
457 domain->startup_time = tev.tv_sec;
458 domain->startup = True;
462 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
465 /****************************************************************
466 Add -ve connection cache entries for domain and realm.
467 ****************************************************************/
469 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
473 add_failed_connection_entry(domain->name, server, result);
474 /* If this was the saf name for the last thing we talked to,
476 saf_delete(domain->name);
477 if (*domain->alt_name) {
478 add_failed_connection_entry(domain->alt_name, server, result);
479 saf_delete(domain->alt_name);
483 /* Choose between anonymous or authenticated connections. We need to use
484 an authenticated connection if DCs have the RestrictAnonymous registry
485 entry set > 0, or the "Additional restrictions for anonymous
486 connections" set in the win2k Local Security Policy.
488 Caller to free() result in domain, username, password
491 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
493 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
494 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
495 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
497 if (*username && **username) {
499 if (!*domain || !**domain)
500 *domain = smb_xstrdup(lp_workgroup());
502 if (!*password || !**password)
503 *password = smb_xstrdup("");
505 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
506 *domain, *username));
509 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
510 *username = smb_xstrdup("");
511 *domain = smb_xstrdup("");
512 *password = smb_xstrdup("");
516 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
517 fstring dcname, struct in_addr *dc_ip)
519 struct winbindd_domain *our_domain = NULL;
520 struct rpc_pipe_client *netlogon_pipe = NULL;
524 unsigned int orig_timeout;
528 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
535 if (domain->primary) {
539 our_domain = find_our_domain();
541 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
545 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
546 if (!NT_STATUS_IS_OK(result)) {
547 talloc_destroy(mem_ctx);
551 /* This call can take a long time - allow the server to time out.
552 35 seconds should do it. */
554 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
556 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
559 /* And restore our original timeout. */
560 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
562 talloc_destroy(mem_ctx);
564 if (!W_ERROR_IS_OK(werr)) {
565 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
570 /* cli_netlogon_getdcname gives us a name with \\ */
581 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
583 if (!resolve_name(dcname, dc_ip, 0x20)) {
590 /************************************************************************
591 Given a fd with a just-connected TCP connection to a DC, open a connection
593 ************************************************************************/
595 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
597 const char *controller,
598 struct cli_state **cli,
601 char *machine_password, *machine_krb5_principal, *machine_account;
602 char *ipc_username, *ipc_domain, *ipc_password;
606 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
608 struct sockaddr peeraddr;
609 socklen_t peeraddr_len;
611 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
613 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
614 controller, domain->name ));
616 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
619 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
620 SAFE_FREE(machine_password);
621 return NT_STATUS_NO_MEMORY;
624 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
626 SAFE_FREE(machine_account);
627 SAFE_FREE(machine_password);
628 return NT_STATUS_NO_MEMORY;
631 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
635 got_mutex = secrets_named_mutex(controller,
636 WINBIND_SERVER_MUTEX_WAIT_TIME);
639 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
641 result = NT_STATUS_POSSIBLE_DEADLOCK;
645 if ((*cli = cli_initialise()) == NULL) {
646 DEBUG(1, ("Could not cli_initialize\n"));
647 result = NT_STATUS_NO_MEMORY;
651 (*cli)->timeout = 10000; /* 10 seconds */
653 fstrcpy((*cli)->desthost, controller);
654 (*cli)->use_kerberos = True;
656 peeraddr_len = sizeof(peeraddr);
658 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
659 (peeraddr_len != sizeof(struct sockaddr_in)) ||
660 (peeraddr_in->sin_family != PF_INET))
662 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
663 result = NT_STATUS_UNSUCCESSFUL;
667 if (ntohs(peeraddr_in->sin_port) == 139) {
668 struct nmb_name calling;
669 struct nmb_name called;
671 make_nmb_name(&calling, global_myname(), 0x0);
672 make_nmb_name(&called, "*SMBSERVER", 0x20);
674 if (!cli_session_request(*cli, &calling, &called)) {
675 DEBUG(8, ("cli_session_request failed for %s\n",
677 result = NT_STATUS_UNSUCCESSFUL;
682 cli_setup_signing_state(*cli, Undefined);
684 if (!cli_negprot(*cli)) {
685 DEBUG(1, ("cli_negprot failed\n"));
686 result = NT_STATUS_UNSUCCESSFUL;
690 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
691 ADS_STATUS ads_status;
693 if (lp_security() == SEC_ADS) {
695 /* Try a krb5 session */
697 (*cli)->use_kerberos = True;
698 DEBUG(5, ("connecting to %s from %s with kerberos principal "
699 "[%s]\n", controller, global_myname(),
700 machine_krb5_principal));
702 ads_status = cli_session_setup_spnego(*cli,
703 machine_krb5_principal,
707 if (!ADS_ERR_OK(ads_status)) {
708 DEBUG(4,("failed kerberos session setup with %s\n",
709 ads_errstr(ads_status)));
712 result = ads_ntstatus(ads_status);
713 if (NT_STATUS_IS_OK(result)) {
714 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
715 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
716 goto session_setup_done;
720 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
721 (*cli)->use_kerberos = False;
723 DEBUG(5, ("connecting to %s from %s with username "
724 "[%s]\\[%s]\n", controller, global_myname(),
725 lp_workgroup(), machine_account));
727 ads_status = cli_session_setup_spnego(*cli,
731 if (!ADS_ERR_OK(ads_status)) {
732 DEBUG(4, ("authenticated session setup failed with %s\n",
733 ads_errstr(ads_status)));
736 result = ads_ntstatus(ads_status);
737 if (NT_STATUS_IS_OK(result)) {
738 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
739 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
740 goto session_setup_done;
744 /* Fall back to non-kerberos session setup */
746 (*cli)->use_kerberos = False;
748 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
749 (strlen(ipc_username) > 0)) {
751 /* Only try authenticated if we have a username */
753 DEBUG(5, ("connecting to %s from %s with username "
754 "[%s]\\[%s]\n", controller, global_myname(),
755 ipc_domain, ipc_username));
757 if (NT_STATUS_IS_OK(cli_session_setup(
759 ipc_password, strlen(ipc_password)+1,
760 ipc_password, strlen(ipc_password)+1,
762 /* Successful logon with given username. */
763 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
764 goto session_setup_done;
766 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
767 ipc_domain, ipc_username ));
771 /* Fall back to anonymous connection, this might fail later */
773 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
775 DEBUG(5, ("Connected anonymously\n"));
776 cli_init_creds(*cli, "", "", "");
777 goto session_setup_done;
780 result = cli_nt_error(*cli);
782 if (NT_STATUS_IS_OK(result))
783 result = NT_STATUS_UNSUCCESSFUL;
785 /* We can't session setup */
791 /* cache the server name for later connections */
793 saf_store( domain->name, (*cli)->desthost );
794 if (domain->alt_name && (*cli)->use_kerberos) {
795 saf_store( domain->alt_name, (*cli)->desthost );
798 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
800 result = cli_nt_error(*cli);
802 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
804 if (NT_STATUS_IS_OK(result))
805 result = NT_STATUS_UNSUCCESSFUL;
810 secrets_named_mutex_release(controller);
814 /* set the domain if empty; needed for schannel connections */
815 if ( !*(*cli)->domain ) {
816 fstrcpy( (*cli)->domain, domain->name );
819 result = NT_STATUS_OK;
823 secrets_named_mutex_release(controller);
826 SAFE_FREE(machine_account);
827 SAFE_FREE(machine_password);
828 SAFE_FREE(machine_krb5_principal);
829 SAFE_FREE(ipc_username);
830 SAFE_FREE(ipc_domain);
831 SAFE_FREE(ipc_password);
833 if (!NT_STATUS_IS_OK(result)) {
834 winbind_add_failed_connection_entry(domain, controller, result);
835 if ((*cli) != NULL) {
844 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
845 const char *dcname, struct in_addr ip,
846 struct dc_name_ip **dcs, int *num)
848 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
849 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
853 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
858 fstrcpy((*dcs)[*num].name, dcname);
859 (*dcs)[*num].ip = ip;
864 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
865 struct in_addr ip, uint16 port,
866 struct sockaddr_in **addrs, int *num)
868 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
870 if (*addrs == NULL) {
875 (*addrs)[*num].sin_family = PF_INET;
876 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
877 (*addrs)[*num].sin_port = htons(port);
883 static void mailslot_name(struct in_addr dc_ip, fstring name)
885 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
888 static BOOL send_getdc_request(struct in_addr dc_ip,
889 const char *domain_name,
894 fstring my_acct_name;
897 mailslot_name(dc_ip, my_mailslot);
899 memset(outbuf, '\0', sizeof(outbuf));
903 SCVAL(p, 0, SAMLOGON);
906 SCVAL(p, 0, 0); /* Count pointer ... */
909 SIVAL(p, 0, 0); /* The sender's token ... */
912 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
913 fstr_sprintf(my_acct_name, "%s$", global_myname());
914 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
916 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
917 p += strlen(my_mailslot)+1;
922 SIVAL(p, 0, sid_size(sid));
925 p = ALIGN4(p, outbuf);
927 sid_linearize(p, sid_size(sid), sid);
935 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
936 outbuf, PTR_DIFF(p, outbuf),
937 global_myname(), 0, domain_name, 0x1c,
941 static BOOL receive_getdc_response(struct in_addr dc_ip,
942 const char *domain_name,
945 struct packet_struct *packet;
948 fstring dcname, user, domain;
951 mailslot_name(dc_ip, my_mailslot);
953 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
955 if (packet == NULL) {
956 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
960 DEBUG(5, ("Received packet for %s\n", my_mailslot));
962 buf = packet->packet.dgram.data;
963 len = packet->packet.dgram.datasize;
966 /* 70 is a completely arbitrary value to make sure
967 the SVAL below does not read uninitialized memory */
968 DEBUG(3, ("GetDC got short response\n"));
972 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
973 p = buf+SVAL(buf, smb_vwv10);
975 if (CVAL(p,0) != SAMLOGON_R) {
976 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
981 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
982 STR_TERMINATE|STR_NOALIGN);
983 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
984 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
985 STR_TERMINATE|STR_NOALIGN);
986 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
987 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
988 STR_TERMINATE|STR_NOALIGN);
989 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
991 if (!strequal(domain, domain_name)) {
992 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
993 domain_name, domain));
998 if (*p == '\\') p += 1;
999 if (*p == '\\') p += 1;
1001 fstrcpy(dc_name, p);
1003 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1009 /*******************************************************************
1010 convert an ip to a name
1011 *******************************************************************/
1013 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1015 struct ip_service ip_list;
1021 /* For active directory servers, try to get the ldap server name.
1022 None of these failures should be considered critical for now */
1024 if (lp_security() == SEC_ADS) {
1027 ads = ads_init(domain->alt_name, domain->name, NULL);
1028 ads->auth.flags |= ADS_AUTH_NO_BIND;
1030 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1031 /* We got a cldap packet. */
1032 fstrcpy(name, ads->config.ldap_server_name);
1033 namecache_store(name, 0x20, 1, &ip_list);
1035 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1037 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1038 char *sitename = sitename_fetch(ads->config.realm);
1040 /* We're going to use this KDC for this realm/domain.
1041 If we are using sites, then force the krb5 libs
1044 create_local_private_krb5_conf_for_domain(domain->alt_name,
1049 SAFE_FREE(sitename);
1050 /* Ensure we contact this DC also. */
1051 saf_store( domain->name, name);
1052 saf_store( domain->alt_name, name);
1055 ads_destroy( &ads );
1059 ads_destroy( &ads );
1063 /* try GETDC requests next */
1065 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1068 for (i=0; i<5; i++) {
1069 if (receive_getdc_response(ip, domain->name, name)) {
1070 namecache_store(name, 0x20, 1, &ip_list);
1077 /* try node status request */
1079 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1080 namecache_store(name, 0x20, 1, &ip_list);
1086 /*******************************************************************
1087 Retreive a list of IP address for domain controllers. Fill in
1088 the dcs[] with results.
1089 *******************************************************************/
1091 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1092 struct dc_name_ip **dcs, int *num_dcs)
1096 struct ip_service *ip_list = NULL;
1097 int iplist_size = 0;
1100 enum security_types sec = (enum security_types)lp_security();
1102 is_our_domain = strequal(domain->name, lp_workgroup());
1105 && get_dc_name_via_netlogon(domain, dcname, &ip)
1106 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1108 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1109 dcname, inet_ntoa(ip)));
1113 if (sec == SEC_ADS) {
1114 char *sitename = NULL;
1116 /* We need to make sure we know the local site before
1117 doing any DNS queries, as this will restrict the
1118 get_sorted_dc_list() call below to only fetching
1119 DNS records for the correct site. */
1121 /* Find any DC to get the site record.
1122 We deliberately don't care about the
1125 get_dc_name(domain->name, lp_realm(), dcname, &ip);
1127 sitename = sitename_fetch(lp_realm());
1130 /* Do the site-specific AD dns lookup first. */
1131 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1133 for ( i=0; i<iplist_size; i++ ) {
1134 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1135 ip_list[i].ip, dcs, num_dcs);
1139 SAFE_FREE(sitename);
1143 /* Now we add DCs from the main AD dns lookup. */
1144 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1146 for ( i=0; i<iplist_size; i++ ) {
1147 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1148 ip_list[i].ip, dcs, num_dcs);
1152 /* try standard netbios queries if no ADS */
1154 if (iplist_size==0) {
1155 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1158 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1160 /* now add to the dc array. We'll wait until the last minute
1161 to look up the name of the DC. But we fill in the char* for
1162 the ip now in to make the failed connection cache work */
1164 for ( i=0; i<iplist_size; i++ ) {
1165 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1166 ip_list[i].ip, dcs, num_dcs);
1169 SAFE_FREE( ip_list );
1174 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1175 const struct winbindd_domain *domain,
1176 fstring dcname, struct sockaddr_in *addr, int *fd)
1178 struct dc_name_ip *dcs = NULL;
1181 const char **dcnames = NULL;
1182 int num_dcnames = 0;
1184 struct sockaddr_in *addrs = NULL;
1190 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1193 for (i=0; i<num_dcs; i++) {
1195 if (!add_string_to_array(mem_ctx, dcs[i].name,
1196 &dcnames, &num_dcnames)) {
1199 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1200 &addrs, &num_addrs)) {
1204 if (!add_string_to_array(mem_ctx, dcs[i].name,
1205 &dcnames, &num_dcnames)) {
1208 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1209 &addrs, &num_addrs)) {
1214 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1217 if ((addrs == NULL) || (dcnames == NULL))
1220 /* 5 second timeout. */
1221 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1223 for (i=0; i<num_dcs; i++) {
1224 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1225 "domain %s address %s. Error was %s\n",
1226 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1227 winbind_add_failed_connection_entry(domain,
1228 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1233 *addr = addrs[fd_index];
1235 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1236 /* Ok, we've got a name for the DC */
1237 fstrcpy(dcname, dcnames[fd_index]);
1241 /* Try to figure out the name */
1242 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1246 /* We can not continue without the DC's name */
1247 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1248 NT_STATUS_UNSUCCESSFUL);
1252 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1253 struct winbindd_cm_conn *new_conn)
1255 TALLOC_CTX *mem_ctx;
1257 char *saf_servername = saf_fetch( domain->name );
1260 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1261 SAFE_FREE(saf_servername);
1262 set_domain_offline(domain);
1263 return NT_STATUS_NO_MEMORY;
1266 /* we have to check the server affinity cache here since
1267 later we selecte a DC based on response time and not preference */
1269 /* Check the negative connection cache
1270 before talking to it. It going down may have
1271 triggered the reconnection. */
1273 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1275 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1276 saf_servername, domain->name ));
1278 /* convert an ip address to a name */
1279 if ( is_ipaddress( saf_servername ) ) {
1283 ip = *interpret_addr2( saf_servername );
1284 if (dcip_to_name( domain, ip, saf_name )) {
1285 fstrcpy( domain->dcname, saf_name );
1287 winbind_add_failed_connection_entry(
1288 domain, saf_servername,
1289 NT_STATUS_UNSUCCESSFUL);
1292 fstrcpy( domain->dcname, saf_servername );
1295 SAFE_FREE( saf_servername );
1298 for (retries = 0; retries < 3; retries++) {
1303 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1305 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1306 domain->dcname, domain->name ));
1309 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1310 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1312 struct sockaddr_in *addrs = NULL;
1316 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1317 set_domain_offline(domain);
1318 talloc_destroy(mem_ctx);
1319 return NT_STATUS_NO_MEMORY;
1321 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1322 set_domain_offline(domain);
1323 talloc_destroy(mem_ctx);
1324 return NT_STATUS_NO_MEMORY;
1327 /* 5 second timeout. */
1328 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1334 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1336 /* This is the one place where we will
1337 set the global winbindd offline state
1338 to true, if a "WINBINDD_OFFLINE" entry
1339 is found in the winbindd cache. */
1340 set_global_winbindd_state_offline();
1344 new_conn->cli = NULL;
1346 result = cm_prepare_connection(domain, fd, domain->dcname,
1347 &new_conn->cli, &retry);
1353 if (NT_STATUS_IS_OK(result)) {
1354 if (domain->online == False) {
1355 /* We're changing state from offline to online. */
1356 set_global_winbindd_state_online();
1358 set_domain_online(domain);
1360 /* Ensure we setup the retry handler. */
1361 set_domain_offline(domain);
1364 talloc_destroy(mem_ctx);
1368 /* Close down all open pipes on a connection. */
1370 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1372 /* We're closing down a possibly dead
1373 connection. Don't have impossibly long (10s) timeouts. */
1376 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1379 if (conn->samr_pipe != NULL) {
1380 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1381 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1383 cli_set_timeout(conn->cli, 500);
1386 conn->samr_pipe = NULL;
1389 if (conn->lsa_pipe != NULL) {
1390 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1391 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1393 cli_set_timeout(conn->cli, 500);
1396 conn->lsa_pipe = NULL;
1399 if (conn->netlogon_pipe != NULL) {
1400 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1401 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1403 cli_set_timeout(conn->cli, 500);
1406 conn->netlogon_pipe = NULL;
1410 cli_shutdown(conn->cli);
1416 void close_conns_after_fork(void)
1418 struct winbindd_domain *domain;
1420 for (domain = domain_list(); domain; domain = domain->next) {
1421 if (domain->conn.cli == NULL)
1424 if (domain->conn.cli->fd == -1)
1427 close(domain->conn.cli->fd);
1428 domain->conn.cli->fd = -1;
1432 static BOOL connection_ok(struct winbindd_domain *domain)
1434 if (domain->conn.cli == NULL) {
1435 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1436 "cli!\n", domain->dcname, domain->name));
1440 if (!domain->conn.cli->initialised) {
1441 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1442 "initialised!\n", domain->dcname, domain->name));
1446 if (domain->conn.cli->fd == -1) {
1447 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1448 "never started (fd == -1)\n",
1449 domain->dcname, domain->name));
1453 if (domain->online == False) {
1454 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1461 /* Initialize a new connection up to the RPC BIND.
1462 Bypass online status check so always does network calls. */
1464 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1468 /* Internal connections never use the network. */
1469 if (domain->internal) {
1470 domain->initialized = True;
1471 return NT_STATUS_OK;
1474 if (connection_ok(domain)) {
1475 if (!domain->initialized) {
1476 set_dc_type_and_flags(domain);
1478 return NT_STATUS_OK;
1481 invalidate_cm_connection(&domain->conn);
1483 result = cm_open_connection(domain, &domain->conn);
1485 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1486 set_dc_type_and_flags(domain);
1492 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1494 if (domain->initialized && !domain->online) {
1495 /* We check for online status elsewhere. */
1496 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1499 return init_dc_connection_network(domain);
1502 /******************************************************************************
1503 We can 'sense' certain things about the DC by it's replies to certain
1506 This tells us if this particular remote server is Active Directory, and if it
1508 ******************************************************************************/
1510 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1514 TALLOC_CTX *mem_ctx = NULL;
1515 struct rpc_pipe_client *cli;
1518 char *domain_name = NULL;
1519 char *dns_name = NULL;
1520 char *forest_name = NULL;
1521 DOM_SID *dom_sid = NULL;
1525 if (!connection_ok(domain)) {
1529 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1531 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1535 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1536 "PI_LSARPC_DS on domain %s: (%s)\n",
1537 domain->name, nt_errstr(result)));
1541 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1542 DsRolePrimaryDomainInfoBasic,
1544 cli_rpc_pipe_close(cli);
1546 if (!NT_STATUS_IS_OK(result)) {
1547 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1548 "on domain %s failed: (%s)\n",
1549 domain->name, nt_errstr(result)));
1553 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1554 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1555 domain->native_mode = True;
1557 domain->native_mode = False;
1560 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1563 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1564 "PI_LSARPC on domain %s: (%s)\n",
1565 domain->name, nt_errstr(result)));
1566 cli_rpc_pipe_close(cli);
1570 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1573 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1574 cli_rpc_pipe_close(cli);
1578 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1579 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1581 if (NT_STATUS_IS_OK(result)) {
1582 /* This particular query is exactly what Win2k clients use
1583 to determine that the DC is active directory */
1584 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1586 &dns_name, &forest_name,
1590 if (NT_STATUS_IS_OK(result)) {
1591 domain->active_directory = True;
1594 fstrcpy(domain->name, domain_name);
1597 fstrcpy(domain->alt_name, dns_name);
1600 fstrcpy(domain->forest_name, forest_name);
1603 sid_copy(&domain->sid, dom_sid);
1605 domain->active_directory = False;
1607 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1608 SEC_RIGHTS_MAXIMUM_ALLOWED,
1611 if (!NT_STATUS_IS_OK(result))
1614 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1615 &pol, 5, &domain_name,
1618 if (NT_STATUS_IS_OK(result)) {
1620 fstrcpy(domain->name, domain_name);
1623 sid_copy(&domain->sid, dom_sid);
1628 DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
1629 domain->name, domain->native_mode ? "" : "NOT "));
1631 DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
1632 domain->name, domain->active_directory ? "" : "NOT "));
1634 cli_rpc_pipe_close(cli);
1636 talloc_destroy(mem_ctx);
1638 domain->initialized = True;
1641 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1642 struct dcinfo **ppdc)
1645 struct rpc_pipe_client *netlogon_pipe;
1647 if (lp_client_schannel() == False) {
1651 result = cm_connect_netlogon(domain, &netlogon_pipe);
1652 if (!NT_STATUS_IS_OK(result)) {
1656 /* Return a pointer to the struct dcinfo from the
1659 *ppdc = domain->conn.netlogon_pipe->dc;
1663 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1664 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1666 struct winbindd_cm_conn *conn;
1667 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1669 struct dcinfo *p_dcinfo;
1671 result = init_dc_connection(domain);
1672 if (!NT_STATUS_IS_OK(result)) {
1676 conn = &domain->conn;
1678 if (conn->samr_pipe != NULL) {
1683 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1684 * sign and sealed pipe using the machine account password by
1685 * preference. If we can't - try schannel, if that fails, try
1689 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1690 if ((conn->cli->user_name[0] == '\0') ||
1691 (conn->cli->domain[0] == '\0') ||
1692 (conn_pwd[0] == '\0')) {
1693 DEBUG(10, ("cm_connect_sam: No no user available for "
1694 "domain %s, trying schannel\n", conn->cli->domain));
1698 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1699 authenticated SAMR pipe with sign & seal. */
1701 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1702 PIPE_AUTH_LEVEL_PRIVACY,
1704 conn->cli->user_name,
1707 if (conn->samr_pipe == NULL) {
1708 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1709 "pipe for domain %s using NTLMSSP "
1710 "authenticated pipe: user %s\\%s. Error was "
1711 "%s\n", domain->name, conn->cli->domain,
1712 conn->cli->user_name, nt_errstr(result)));
1716 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1717 "domain %s using NTLMSSP authenticated "
1718 "pipe: user %s\\%s\n", domain->name,
1719 conn->cli->domain, conn->cli->user_name ));
1721 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1722 SEC_RIGHTS_MAXIMUM_ALLOWED,
1723 &conn->sam_connect_handle);
1724 if (NT_STATUS_IS_OK(result)) {
1727 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1728 "failed for domain %s, error was %s. Trying schannel\n",
1729 domain->name, nt_errstr(result) ));
1730 cli_rpc_pipe_close(conn->samr_pipe);
1734 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1736 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1737 /* If this call fails - conn->cli can now be NULL ! */
1738 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1739 "for domain %s, trying anon\n", domain->name));
1742 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1743 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1744 domain->name, p_dcinfo, &result);
1746 if (conn->samr_pipe == NULL) {
1747 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1748 "domain %s using schannel. Error was %s\n",
1749 domain->name, nt_errstr(result) ));
1752 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1753 "schannel.\n", domain->name ));
1755 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1756 SEC_RIGHTS_MAXIMUM_ALLOWED,
1757 &conn->sam_connect_handle);
1758 if (NT_STATUS_IS_OK(result)) {
1761 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1762 "for domain %s, error was %s. Trying anonymous\n",
1763 domain->name, nt_errstr(result) ));
1764 cli_rpc_pipe_close(conn->samr_pipe);
1768 /* Finally fall back to anonymous. */
1769 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1772 if (conn->samr_pipe == NULL) {
1773 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1777 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1778 SEC_RIGHTS_MAXIMUM_ALLOWED,
1779 &conn->sam_connect_handle);
1780 if (!NT_STATUS_IS_OK(result)) {
1781 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1782 "for domain %s Error was %s\n",
1783 domain->name, nt_errstr(result) ));
1788 result = rpccli_samr_open_domain(conn->samr_pipe,
1790 &conn->sam_connect_handle,
1791 SEC_RIGHTS_MAXIMUM_ALLOWED,
1793 &conn->sam_domain_handle);
1797 if (!NT_STATUS_IS_OK(result)) {
1798 invalidate_cm_connection(conn);
1802 *cli = conn->samr_pipe;
1803 *sam_handle = conn->sam_domain_handle;
1807 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1808 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1810 struct winbindd_cm_conn *conn;
1811 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1813 struct dcinfo *p_dcinfo;
1815 result = init_dc_connection(domain);
1816 if (!NT_STATUS_IS_OK(result))
1819 conn = &domain->conn;
1821 if (conn->lsa_pipe != NULL) {
1825 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1826 if ((conn->cli->user_name[0] == '\0') ||
1827 (conn->cli->domain[0] == '\0') ||
1828 (conn_pwd[0] == '\0')) {
1829 DEBUG(10, ("cm_connect_lsa: No no user available for "
1830 "domain %s, trying schannel\n", conn->cli->domain));
1834 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1835 * authenticated LSA pipe with sign & seal. */
1836 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1837 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1838 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1840 if (conn->lsa_pipe == NULL) {
1841 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1842 "domain %s using NTLMSSP authenticated pipe: user "
1843 "%s\\%s. Error was %s. Trying schannel.\n",
1844 domain->name, conn->cli->domain,
1845 conn->cli->user_name, nt_errstr(result)));
1849 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1850 "NTLMSSP authenticated pipe: user %s\\%s\n",
1851 domain->name, conn->cli->domain, conn->cli->user_name ));
1853 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1854 SEC_RIGHTS_MAXIMUM_ALLOWED,
1856 if (NT_STATUS_IS_OK(result)) {
1860 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1863 cli_rpc_pipe_close(conn->lsa_pipe);
1867 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1869 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1870 /* If this call fails - conn->cli can now be NULL ! */
1871 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1872 "for domain %s, trying anon\n", domain->name));
1875 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1876 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1877 domain->name, p_dcinfo, &result);
1879 if (conn->lsa_pipe == NULL) {
1880 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1881 "domain %s using schannel. Error was %s\n",
1882 domain->name, nt_errstr(result) ));
1885 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1886 "schannel.\n", domain->name ));
1888 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1889 SEC_RIGHTS_MAXIMUM_ALLOWED,
1891 if (NT_STATUS_IS_OK(result)) {
1895 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1898 cli_rpc_pipe_close(conn->lsa_pipe);
1902 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1904 if (conn->lsa_pipe == NULL) {
1905 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1909 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1910 SEC_RIGHTS_MAXIMUM_ALLOWED,
1913 if (!NT_STATUS_IS_OK(result)) {
1914 invalidate_cm_connection(conn);
1918 *cli = conn->lsa_pipe;
1919 *lsa_policy = conn->lsa_policy;
1923 /****************************************************************************
1924 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1925 session key stored in conn->netlogon_pipe->dc->sess_key.
1926 ****************************************************************************/
1928 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1929 struct rpc_pipe_client **cli)
1931 struct winbindd_cm_conn *conn;
1934 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1936 uint32 sec_chan_type;
1937 const char *account_name;
1938 struct rpc_pipe_client *netlogon_pipe = NULL;
1942 result = init_dc_connection(domain);
1943 if (!NT_STATUS_IS_OK(result)) {
1947 conn = &domain->conn;
1949 if (conn->netlogon_pipe != NULL) {
1950 *cli = conn->netlogon_pipe;
1951 return NT_STATUS_OK;
1954 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1955 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1958 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1960 if (netlogon_pipe == NULL) {
1964 if (lp_client_schannel() != False) {
1965 neg_flags |= NETLOGON_NEG_SCHANNEL;
1968 /* if we are a DC and this is a trusted domain, then we need to use our
1969 domain name in the net_req_auth2() request */
1972 && !strequal(domain->name, lp_workgroup())
1973 && lp_allow_trusted_domains() )
1975 account_name = lp_workgroup();
1977 account_name = domain->primary ?
1978 global_myname() : domain->name;
1981 if (account_name == NULL) {
1982 cli_rpc_pipe_close(netlogon_pipe);
1983 return NT_STATUS_NO_MEMORY;
1986 result = rpccli_netlogon_setup_creds(
1988 domain->dcname, /* server name. */
1989 domain->name, /* domain name */
1990 global_myname(), /* client name */
1991 account_name, /* machine account */
1992 mach_pwd, /* machine password */
1993 sec_chan_type, /* from get_trust_pw */
1996 if (!NT_STATUS_IS_OK(result)) {
1997 cli_rpc_pipe_close(netlogon_pipe);
2001 if ((lp_client_schannel() == True) &&
2002 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2003 DEBUG(3, ("Server did not offer schannel\n"));
2004 cli_rpc_pipe_close(netlogon_pipe);
2005 return NT_STATUS_ACCESS_DENIED;
2008 if ((lp_client_schannel() == False) ||
2009 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2010 /* We're done - just keep the existing connection to NETLOGON
2012 conn->netlogon_pipe = netlogon_pipe;
2013 *cli = conn->netlogon_pipe;
2014 return NT_STATUS_OK;
2017 /* Using the credentials from the first pipe, open a signed and sealed
2018 second netlogon pipe. The session key is stored in the schannel
2019 part of the new pipe auth struct.
2022 conn->netlogon_pipe =
2023 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2025 PIPE_AUTH_LEVEL_PRIVACY,
2030 /* We can now close the initial netlogon pipe. */
2031 cli_rpc_pipe_close(netlogon_pipe);
2033 if (conn->netlogon_pipe == NULL) {
2034 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2035 "was %s\n", nt_errstr(result)));
2037 /* make sure we return something besides OK */
2038 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2041 *cli = conn->netlogon_pipe;
2042 return NT_STATUS_OK;