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) {
207 mem_ctx = talloc_init("fork_child_dc_connect");
209 DEBUG(0,("talloc_init failed.\n"));
213 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
214 /* Still offline ? Can't find DC's. */
215 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
217 strlen(domain->name)+1, False);
221 /* We got a DC. Send a message to our parent to get it to
222 try and do the same. */
224 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
226 strlen(domain->name)+1, False);
230 /****************************************************************
231 Handler triggered if we're offline to try and detect a DC.
232 ****************************************************************/
234 static void check_domain_online_handler(struct event_context *ctx,
235 struct timed_event *te,
236 const struct timeval *now,
239 struct winbindd_domain *domain =
240 (struct winbindd_domain *)private_data;
242 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
245 if (domain->check_online_event) {
246 TALLOC_FREE(domain->check_online_event);
249 /* Are we still in "startup" mode ? */
251 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
252 /* No longer in "startup" mode. */
253 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
255 domain->startup = False;
258 /* We've been told to stay offline, so stay
261 if (get_global_winbindd_state_offline()) {
262 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
267 /* Fork a child to test if it can contact a DC.
268 If it can then send ourselves a message to
269 cause a reconnect. */
271 fork_child_dc_connect(domain);
274 /****************************************************************
275 If we're still offline setup the timeout check.
276 ****************************************************************/
278 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
280 int wbc = lp_winbind_cache_time();
282 if (domain->startup) {
283 domain->check_online_timeout = 10;
284 } else if (domain->check_online_timeout < wbc) {
285 domain->check_online_timeout = wbc;
289 /****************************************************************
290 Set domain offline and also add handler to put us back online
292 ****************************************************************/
294 void set_domain_offline(struct winbindd_domain *domain)
296 DEBUG(10,("set_domain_offline: called for domain %s\n",
299 if (domain->check_online_event) {
300 TALLOC_FREE(domain->check_online_event);
303 if (domain->internal) {
304 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
309 domain->online = False;
311 /* Offline domains are always initialized. They're
312 re-initialized when they go back online. */
314 domain->initialized = True;
316 /* We only add the timeout handler that checks and
317 allows us to go back online when we've not
318 been told to remain offline. */
320 if (get_global_winbindd_state_offline()) {
321 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
326 /* If we're in statup mode, check again in 10 seconds, not in
327 lp_winbind_cache_time() seconds (which is 5 mins by default). */
329 calc_new_online_timeout_check(domain);
331 domain->check_online_event = event_add_timed(winbind_event_context(), NULL,
332 timeval_current_ofs(domain->check_online_timeout,0),
333 "check_domain_online_handler",
334 check_domain_online_handler,
337 /* The above *has* to succeed for winbindd to work. */
338 if (!domain->check_online_event) {
339 smb_panic("set_domain_offline: failed to add online handler.\n");
342 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
346 /****************************************************************
347 Set domain online - if allowed.
348 ****************************************************************/
350 static void set_domain_online(struct winbindd_domain *domain)
354 DEBUG(10,("set_domain_online: called for domain %s\n",
357 if (domain->internal) {
358 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
363 if (get_global_winbindd_state_offline()) {
364 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
369 /* If we are waiting to get a krb5 ticket, trigger immediately. */
371 set_event_dispatch_time(winbind_event_context(),
372 "krb5_ticket_gain_handler", now);
374 /* Ok, we're out of any startup mode now... */
375 domain->startup = False;
377 if (domain->online == False) {
378 /* We were offline - now we're online. We default to
379 using the MS-RPC backend if we started offline,
380 and if we're going online for the first time we
381 should really re-initialize the backends and the
382 checks to see if we're talking to an AD or NT domain.
385 domain->initialized = False;
387 /* 'reconnect_methods' is the MS-RPC backend. */
388 if (domain->backend == &reconnect_methods) {
389 domain->backend = NULL;
393 /* Ensure we have no online timeout checks. */
394 domain->check_online_timeout = 0;
395 if (domain->check_online_event) {
396 TALLOC_FREE(domain->check_online_event);
399 /* Ensure we ignore any pending child messages. */
400 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
401 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
403 domain->online = True;
406 /****************************************************************
407 Requested to set a domain online.
408 ****************************************************************/
410 void set_domain_online_request(struct winbindd_domain *domain)
414 DEBUG(10,("set_domain_online_request: called for domain %s\n",
417 if (get_global_winbindd_state_offline()) {
418 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
423 /* We've been told it's safe to go online and
424 try and connect to a DC. But I don't believe it
425 because network manager seems to lie.
426 Wait at least 5 seconds. Heuristics suck... */
428 if (!domain->check_online_event) {
429 /* If we've come from being globally offline we
430 don't have a check online event handler set.
431 We need to add one now we're trying to go
434 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
439 TALLOC_FREE(domain->check_online_event);
443 /* Go into "startup" mode again. */
444 domain->startup_time = tev.tv_sec;
445 domain->startup = True;
449 domain->check_online_event = event_add_timed(
450 winbind_event_context(), NULL, tev,
451 "check_domain_online_handler",
452 check_domain_online_handler,
455 /* The above *has* to succeed for winbindd to work. */
456 if (!domain->check_online_event) {
457 smb_panic("set_domain_online_request: failed to add online handler.\n");
461 /****************************************************************
462 Add -ve connection cache entries for domain and realm.
463 ****************************************************************/
465 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
469 add_failed_connection_entry(domain->name, server, result);
470 /* If this was the saf name for the last thing we talked to,
472 saf_delete(domain->name);
473 if (*domain->alt_name) {
474 add_failed_connection_entry(domain->alt_name, server, result);
475 saf_delete(domain->alt_name);
479 /* Choose between anonymous or authenticated connections. We need to use
480 an authenticated connection if DCs have the RestrictAnonymous registry
481 entry set > 0, or the "Additional restrictions for anonymous
482 connections" set in the win2k Local Security Policy.
484 Caller to free() result in domain, username, password
487 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
489 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
490 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
491 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
493 if (*username && **username) {
495 if (!*domain || !**domain)
496 *domain = smb_xstrdup(lp_workgroup());
498 if (!*password || !**password)
499 *password = smb_xstrdup("");
501 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
502 *domain, *username));
505 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
506 *username = smb_xstrdup("");
507 *domain = smb_xstrdup("");
508 *password = smb_xstrdup("");
512 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
513 fstring dcname, struct in_addr *dc_ip)
515 struct winbindd_domain *our_domain = NULL;
516 struct rpc_pipe_client *netlogon_pipe = NULL;
520 unsigned int orig_timeout;
524 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
531 if (domain->primary) {
535 our_domain = find_our_domain();
537 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
541 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
542 if (!NT_STATUS_IS_OK(result)) {
543 talloc_destroy(mem_ctx);
547 /* This call can take a long time - allow the server to time out.
548 35 seconds should do it. */
550 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
552 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
555 /* And restore our original timeout. */
556 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
558 talloc_destroy(mem_ctx);
560 if (!W_ERROR_IS_OK(werr)) {
561 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
566 /* cli_netlogon_getdcname gives us a name with \\ */
577 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
579 if (!resolve_name(dcname, dc_ip, 0x20)) {
586 /************************************************************************
587 Given a fd with a just-connected TCP connection to a DC, open a connection
589 ************************************************************************/
591 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
593 const char *controller,
594 struct cli_state **cli,
597 char *machine_password, *machine_krb5_principal, *machine_account;
598 char *ipc_username, *ipc_domain, *ipc_password;
602 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
604 struct sockaddr peeraddr;
605 socklen_t peeraddr_len;
607 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
609 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
610 controller, domain->name ));
612 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
615 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
616 SAFE_FREE(machine_password);
617 return NT_STATUS_NO_MEMORY;
620 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
622 SAFE_FREE(machine_account);
623 SAFE_FREE(machine_password);
624 return NT_STATUS_NO_MEMORY;
627 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
631 got_mutex = secrets_named_mutex(controller,
632 WINBIND_SERVER_MUTEX_WAIT_TIME);
635 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
637 result = NT_STATUS_POSSIBLE_DEADLOCK;
641 if ((*cli = cli_initialise()) == NULL) {
642 DEBUG(1, ("Could not cli_initialize\n"));
643 result = NT_STATUS_NO_MEMORY;
647 (*cli)->timeout = 10000; /* 10 seconds */
649 fstrcpy((*cli)->desthost, controller);
650 (*cli)->use_kerberos = True;
652 peeraddr_len = sizeof(peeraddr);
654 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
655 (peeraddr_len != sizeof(struct sockaddr_in)) ||
656 (peeraddr_in->sin_family != PF_INET))
658 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
659 result = NT_STATUS_UNSUCCESSFUL;
663 if (ntohs(peeraddr_in->sin_port) == 139) {
664 struct nmb_name calling;
665 struct nmb_name called;
667 make_nmb_name(&calling, global_myname(), 0x0);
668 make_nmb_name(&called, "*SMBSERVER", 0x20);
670 if (!cli_session_request(*cli, &calling, &called)) {
671 DEBUG(8, ("cli_session_request failed for %s\n",
673 result = NT_STATUS_UNSUCCESSFUL;
678 cli_setup_signing_state(*cli, Undefined);
680 if (!cli_negprot(*cli)) {
681 DEBUG(1, ("cli_negprot failed\n"));
682 result = NT_STATUS_UNSUCCESSFUL;
686 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
687 ADS_STATUS ads_status;
689 if (lp_security() == SEC_ADS) {
691 /* Try a krb5 session */
693 (*cli)->use_kerberos = True;
694 DEBUG(5, ("connecting to %s from %s with kerberos principal "
695 "[%s]\n", controller, global_myname(),
696 machine_krb5_principal));
698 ads_status = cli_session_setup_spnego(*cli,
699 machine_krb5_principal,
703 if (!ADS_ERR_OK(ads_status)) {
704 DEBUG(4,("failed kerberos session setup with %s\n",
705 ads_errstr(ads_status)));
708 result = ads_ntstatus(ads_status);
709 if (NT_STATUS_IS_OK(result)) {
710 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
711 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
712 goto session_setup_done;
716 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
717 (*cli)->use_kerberos = False;
719 DEBUG(5, ("connecting to %s from %s with username "
720 "[%s]\\[%s]\n", controller, global_myname(),
721 lp_workgroup(), machine_account));
723 ads_status = cli_session_setup_spnego(*cli,
727 if (!ADS_ERR_OK(ads_status)) {
728 DEBUG(4, ("authenticated session setup failed with %s\n",
729 ads_errstr(ads_status)));
732 result = ads_ntstatus(ads_status);
733 if (NT_STATUS_IS_OK(result)) {
734 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
735 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
736 goto session_setup_done;
740 /* Fall back to non-kerberos session setup */
742 (*cli)->use_kerberos = False;
744 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
745 (strlen(ipc_username) > 0)) {
747 /* Only try authenticated if we have a username */
749 DEBUG(5, ("connecting to %s from %s with username "
750 "[%s]\\[%s]\n", controller, global_myname(),
751 ipc_domain, ipc_username));
753 if (NT_STATUS_IS_OK(cli_session_setup(
755 ipc_password, strlen(ipc_password)+1,
756 ipc_password, strlen(ipc_password)+1,
758 /* Successful logon with given username. */
759 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
760 goto session_setup_done;
762 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
763 ipc_domain, ipc_username ));
767 /* Fall back to anonymous connection, this might fail later */
769 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
771 DEBUG(5, ("Connected anonymously\n"));
772 cli_init_creds(*cli, "", "", "");
773 goto session_setup_done;
776 result = cli_nt_error(*cli);
778 if (NT_STATUS_IS_OK(result))
779 result = NT_STATUS_UNSUCCESSFUL;
781 /* We can't session setup */
787 /* cache the server name for later connections */
789 saf_store( domain->name, (*cli)->desthost );
790 if (domain->alt_name && (*cli)->use_kerberos) {
791 saf_store( domain->alt_name, (*cli)->desthost );
794 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
796 result = cli_nt_error(*cli);
798 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
800 if (NT_STATUS_IS_OK(result))
801 result = NT_STATUS_UNSUCCESSFUL;
806 secrets_named_mutex_release(controller);
810 /* set the domain if empty; needed for schannel connections */
811 if ( !*(*cli)->domain ) {
812 fstrcpy( (*cli)->domain, domain->name );
815 result = NT_STATUS_OK;
819 secrets_named_mutex_release(controller);
822 SAFE_FREE(machine_account);
823 SAFE_FREE(machine_password);
824 SAFE_FREE(machine_krb5_principal);
825 SAFE_FREE(ipc_username);
826 SAFE_FREE(ipc_domain);
827 SAFE_FREE(ipc_password);
829 if (!NT_STATUS_IS_OK(result)) {
830 winbind_add_failed_connection_entry(domain, controller, result);
831 if ((*cli) != NULL) {
840 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
841 const char *dcname, struct in_addr ip,
842 struct dc_name_ip **dcs, int *num)
844 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
845 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
849 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
854 fstrcpy((*dcs)[*num].name, dcname);
855 (*dcs)[*num].ip = ip;
860 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
861 struct in_addr ip, uint16 port,
862 struct sockaddr_in **addrs, int *num)
864 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
866 if (*addrs == NULL) {
871 (*addrs)[*num].sin_family = PF_INET;
872 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
873 (*addrs)[*num].sin_port = htons(port);
879 static void mailslot_name(struct in_addr dc_ip, fstring name)
881 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
884 static BOOL send_getdc_request(struct in_addr dc_ip,
885 const char *domain_name,
890 fstring my_acct_name;
893 mailslot_name(dc_ip, my_mailslot);
895 memset(outbuf, '\0', sizeof(outbuf));
899 SCVAL(p, 0, SAMLOGON);
902 SCVAL(p, 0, 0); /* Count pointer ... */
905 SIVAL(p, 0, 0); /* The sender's token ... */
908 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
909 fstr_sprintf(my_acct_name, "%s$", global_myname());
910 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
912 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
913 p += strlen(my_mailslot)+1;
918 SIVAL(p, 0, sid_size(sid));
921 p = ALIGN4(p, outbuf);
923 sid_linearize(p, sid_size(sid), sid);
931 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
932 outbuf, PTR_DIFF(p, outbuf),
933 global_myname(), 0, domain_name, 0x1c,
937 static BOOL receive_getdc_response(struct in_addr dc_ip,
938 const char *domain_name,
941 struct packet_struct *packet;
944 fstring dcname, user, domain;
947 mailslot_name(dc_ip, my_mailslot);
949 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
951 if (packet == NULL) {
952 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
956 DEBUG(5, ("Received packet for %s\n", my_mailslot));
958 buf = packet->packet.dgram.data;
959 len = packet->packet.dgram.datasize;
962 /* 70 is a completely arbitrary value to make sure
963 the SVAL below does not read uninitialized memory */
964 DEBUG(3, ("GetDC got short response\n"));
968 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
969 p = buf+SVAL(buf, smb_vwv10);
971 if (CVAL(p,0) != SAMLOGON_R) {
972 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
977 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
978 STR_TERMINATE|STR_NOALIGN);
979 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
980 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
981 STR_TERMINATE|STR_NOALIGN);
982 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
983 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
984 STR_TERMINATE|STR_NOALIGN);
985 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
987 if (!strequal(domain, domain_name)) {
988 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
989 domain_name, domain));
994 if (*p == '\\') p += 1;
995 if (*p == '\\') p += 1;
999 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1005 /*******************************************************************
1006 convert an ip to a name
1007 *******************************************************************/
1009 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1011 struct ip_service ip_list;
1017 /* For active directory servers, try to get the ldap server name.
1018 None of these failures should be considered critical for now */
1020 if (lp_security() == SEC_ADS) {
1023 ads = ads_init(domain->alt_name, domain->name, NULL);
1024 ads->auth.flags |= ADS_AUTH_NO_BIND;
1026 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1027 /* We got a cldap packet. */
1028 fstrcpy(name, ads->config.ldap_server_name);
1029 namecache_store(name, 0x20, 1, &ip_list);
1031 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1033 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1034 char *sitename = sitename_fetch(ads->config.realm);
1036 /* We're going to use this KDC for this realm/domain.
1037 If we are using sites, then force the krb5 libs
1040 create_local_private_krb5_conf_for_domain(domain->alt_name,
1045 SAFE_FREE(sitename);
1046 /* Ensure we contact this DC also. */
1047 saf_store( domain->name, name);
1048 saf_store( domain->alt_name, name);
1051 ads_destroy( &ads );
1055 ads_destroy( &ads );
1059 /* try GETDC requests next */
1061 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1064 for (i=0; i<5; i++) {
1065 if (receive_getdc_response(ip, domain->name, name)) {
1066 namecache_store(name, 0x20, 1, &ip_list);
1073 /* try node status request */
1075 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1076 namecache_store(name, 0x20, 1, &ip_list);
1082 /*******************************************************************
1083 Retreive a list of IP address for domain controllers. Fill in
1084 the dcs[] with results.
1085 *******************************************************************/
1087 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1088 struct dc_name_ip **dcs, int *num_dcs)
1092 struct ip_service *ip_list = NULL;
1093 int iplist_size = 0;
1096 enum security_types sec = (enum security_types)lp_security();
1098 is_our_domain = strequal(domain->name, lp_workgroup());
1101 && get_dc_name_via_netlogon(domain, dcname, &ip)
1102 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1104 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1105 dcname, inet_ntoa(ip)));
1109 if (sec == SEC_ADS) {
1110 char *sitename = NULL;
1112 /* We need to make sure we know the local site before
1113 doing any DNS queries, as this will restrict the
1114 get_sorted_dc_list() call below to only fetching
1115 DNS records for the correct site. */
1117 /* Find any DC to get the site record.
1118 We deliberately don't care about the
1121 get_dc_name(domain->name, lp_realm(), dcname, &ip);
1123 sitename = sitename_fetch(lp_realm());
1126 /* Do the site-specific AD dns lookup first. */
1127 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1129 for ( i=0; i<iplist_size; i++ ) {
1130 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1131 ip_list[i].ip, dcs, num_dcs);
1135 SAFE_FREE(sitename);
1139 /* Now we add DCs from the main AD dns lookup. */
1140 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1142 for ( i=0; i<iplist_size; i++ ) {
1143 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1144 ip_list[i].ip, dcs, num_dcs);
1148 /* try standard netbios queries if no ADS */
1150 if (iplist_size==0) {
1151 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1154 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1156 /* now add to the dc array. We'll wait until the last minute
1157 to look up the name of the DC. But we fill in the char* for
1158 the ip now in to make the failed connection cache work */
1160 for ( i=0; i<iplist_size; i++ ) {
1161 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1162 ip_list[i].ip, dcs, num_dcs);
1165 SAFE_FREE( ip_list );
1170 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1171 const struct winbindd_domain *domain,
1172 fstring dcname, struct sockaddr_in *addr, int *fd)
1174 struct dc_name_ip *dcs = NULL;
1177 const char **dcnames = NULL;
1178 int num_dcnames = 0;
1180 struct sockaddr_in *addrs = NULL;
1186 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1189 for (i=0; i<num_dcs; i++) {
1191 if (!add_string_to_array(mem_ctx, dcs[i].name,
1192 &dcnames, &num_dcnames)) {
1195 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1196 &addrs, &num_addrs)) {
1200 if (!add_string_to_array(mem_ctx, dcs[i].name,
1201 &dcnames, &num_dcnames)) {
1204 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1205 &addrs, &num_addrs)) {
1210 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1213 if ((addrs == NULL) || (dcnames == NULL))
1216 /* 5 second timeout. */
1217 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1219 for (i=0; i<num_dcs; i++) {
1220 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1221 "domain %s address %s. Error was %s\n",
1222 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1223 winbind_add_failed_connection_entry(domain,
1224 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1229 *addr = addrs[fd_index];
1231 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1232 /* Ok, we've got a name for the DC */
1233 fstrcpy(dcname, dcnames[fd_index]);
1237 /* Try to figure out the name */
1238 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1242 /* We can not continue without the DC's name */
1243 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1244 NT_STATUS_UNSUCCESSFUL);
1248 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1249 struct winbindd_cm_conn *new_conn)
1251 TALLOC_CTX *mem_ctx;
1253 char *saf_servername = saf_fetch( domain->name );
1256 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1257 SAFE_FREE(saf_servername);
1258 set_domain_offline(domain);
1259 return NT_STATUS_NO_MEMORY;
1262 /* we have to check the server affinity cache here since
1263 later we selecte a DC based on response time and not preference */
1265 /* Check the negative connection cache
1266 before talking to it. It going down may have
1267 triggered the reconnection. */
1269 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1271 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1272 saf_servername, domain->name ));
1274 /* convert an ip address to a name */
1275 if ( is_ipaddress( saf_servername ) ) {
1279 ip = *interpret_addr2( saf_servername );
1280 if (dcip_to_name( domain, ip, saf_name )) {
1281 fstrcpy( domain->dcname, saf_name );
1283 winbind_add_failed_connection_entry(
1284 domain, saf_servername,
1285 NT_STATUS_UNSUCCESSFUL);
1288 fstrcpy( domain->dcname, saf_servername );
1291 SAFE_FREE( saf_servername );
1294 for (retries = 0; retries < 3; retries++) {
1299 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1301 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1302 domain->dcname, domain->name ));
1305 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1306 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1308 struct sockaddr_in *addrs = NULL;
1312 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1313 set_domain_offline(domain);
1314 talloc_destroy(mem_ctx);
1315 return NT_STATUS_NO_MEMORY;
1317 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1318 set_domain_offline(domain);
1319 talloc_destroy(mem_ctx);
1320 return NT_STATUS_NO_MEMORY;
1323 /* 5 second timeout. */
1324 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1330 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1332 /* This is the one place where we will
1333 set the global winbindd offline state
1334 to true, if a "WINBINDD_OFFLINE" entry
1335 is found in the winbindd cache. */
1336 set_global_winbindd_state_offline();
1340 new_conn->cli = NULL;
1342 result = cm_prepare_connection(domain, fd, domain->dcname,
1343 &new_conn->cli, &retry);
1349 if (NT_STATUS_IS_OK(result)) {
1350 if (domain->online == False) {
1351 /* We're changing state from offline to online. */
1352 set_global_winbindd_state_online();
1354 set_domain_online(domain);
1356 /* Ensure we setup the retry handler. */
1357 set_domain_offline(domain);
1360 talloc_destroy(mem_ctx);
1364 /* Close down all open pipes on a connection. */
1366 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1368 /* We're closing down a possibly dead
1369 connection. Don't have impossibly long (10s) timeouts. */
1372 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1375 if (conn->samr_pipe != NULL) {
1376 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1377 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1379 cli_set_timeout(conn->cli, 500);
1382 conn->samr_pipe = NULL;
1385 if (conn->lsa_pipe != NULL) {
1386 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1387 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1389 cli_set_timeout(conn->cli, 500);
1392 conn->lsa_pipe = NULL;
1395 if (conn->netlogon_pipe != NULL) {
1396 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1397 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1399 cli_set_timeout(conn->cli, 500);
1402 conn->netlogon_pipe = NULL;
1406 cli_shutdown(conn->cli);
1412 void close_conns_after_fork(void)
1414 struct winbindd_domain *domain;
1416 for (domain = domain_list(); domain; domain = domain->next) {
1417 if (domain->conn.cli == NULL)
1420 if (domain->conn.cli->fd == -1)
1423 close(domain->conn.cli->fd);
1424 domain->conn.cli->fd = -1;
1428 static BOOL connection_ok(struct winbindd_domain *domain)
1430 if (domain->conn.cli == NULL) {
1431 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1432 "cli!\n", domain->dcname, domain->name));
1436 if (!domain->conn.cli->initialised) {
1437 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1438 "initialised!\n", domain->dcname, domain->name));
1442 if (domain->conn.cli->fd == -1) {
1443 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1444 "never started (fd == -1)\n",
1445 domain->dcname, domain->name));
1449 if (domain->online == False) {
1450 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1457 /* Initialize a new connection up to the RPC BIND.
1458 Bypass online status check so always does network calls. */
1460 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1464 /* Internal connections never use the network. */
1465 if (domain->internal) {
1466 domain->initialized = True;
1467 return NT_STATUS_OK;
1470 if (connection_ok(domain)) {
1471 if (!domain->initialized) {
1472 set_dc_type_and_flags(domain);
1474 return NT_STATUS_OK;
1477 invalidate_cm_connection(&domain->conn);
1479 result = cm_open_connection(domain, &domain->conn);
1481 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1482 set_dc_type_and_flags(domain);
1488 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1490 if (domain->initialized && !domain->online) {
1491 /* We check for online status elsewhere. */
1492 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1495 return init_dc_connection_network(domain);
1498 /******************************************************************************
1499 We can 'sense' certain things about the DC by it's replies to certain
1502 This tells us if this particular remote server is Active Directory, and if it
1504 ******************************************************************************/
1506 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1510 TALLOC_CTX *mem_ctx = NULL;
1511 struct rpc_pipe_client *cli;
1514 char *domain_name = NULL;
1515 char *dns_name = NULL;
1516 char *forest_name = NULL;
1517 DOM_SID *dom_sid = NULL;
1521 if (!connection_ok(domain)) {
1525 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1527 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1531 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1532 "PI_LSARPC_DS on domain %s: (%s)\n",
1533 domain->name, nt_errstr(result)));
1537 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1538 DsRolePrimaryDomainInfoBasic,
1540 cli_rpc_pipe_close(cli);
1542 if (!NT_STATUS_IS_OK(result)) {
1543 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1544 "on domain %s failed: (%s)\n",
1545 domain->name, nt_errstr(result)));
1549 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1550 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1551 domain->native_mode = True;
1553 domain->native_mode = False;
1556 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1559 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1560 "PI_LSARPC on domain %s: (%s)\n",
1561 domain->name, nt_errstr(result)));
1562 cli_rpc_pipe_close(cli);
1566 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1569 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1570 cli_rpc_pipe_close(cli);
1574 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1575 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1577 if (NT_STATUS_IS_OK(result)) {
1578 /* This particular query is exactly what Win2k clients use
1579 to determine that the DC is active directory */
1580 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1582 &dns_name, &forest_name,
1586 if (NT_STATUS_IS_OK(result)) {
1587 domain->active_directory = True;
1590 fstrcpy(domain->name, domain_name);
1593 fstrcpy(domain->alt_name, dns_name);
1596 fstrcpy(domain->forest_name, forest_name);
1599 sid_copy(&domain->sid, dom_sid);
1601 domain->active_directory = False;
1603 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1604 SEC_RIGHTS_MAXIMUM_ALLOWED,
1607 if (!NT_STATUS_IS_OK(result))
1610 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1611 &pol, 5, &domain_name,
1614 if (NT_STATUS_IS_OK(result)) {
1616 fstrcpy(domain->name, domain_name);
1619 sid_copy(&domain->sid, dom_sid);
1624 DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
1625 domain->name, domain->native_mode ? "" : "NOT "));
1627 DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
1628 domain->name, domain->active_directory ? "" : "NOT "));
1630 cli_rpc_pipe_close(cli);
1632 talloc_destroy(mem_ctx);
1634 domain->initialized = True;
1637 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1638 struct dcinfo **ppdc)
1641 struct rpc_pipe_client *netlogon_pipe;
1643 if (lp_client_schannel() == False) {
1647 result = cm_connect_netlogon(domain, &netlogon_pipe);
1648 if (!NT_STATUS_IS_OK(result)) {
1652 /* Return a pointer to the struct dcinfo from the
1655 *ppdc = domain->conn.netlogon_pipe->dc;
1659 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1660 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1662 struct winbindd_cm_conn *conn;
1663 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1665 struct dcinfo *p_dcinfo;
1667 result = init_dc_connection(domain);
1668 if (!NT_STATUS_IS_OK(result)) {
1672 conn = &domain->conn;
1674 if (conn->samr_pipe != NULL) {
1679 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1680 * sign and sealed pipe using the machine account password by
1681 * preference. If we can't - try schannel, if that fails, try
1685 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1686 if ((conn->cli->user_name[0] == '\0') ||
1687 (conn->cli->domain[0] == '\0') ||
1688 (conn_pwd[0] == '\0')) {
1689 DEBUG(10, ("cm_connect_sam: No no user available for "
1690 "domain %s, trying schannel\n", conn->cli->domain));
1694 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1695 authenticated SAMR pipe with sign & seal. */
1697 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1698 PIPE_AUTH_LEVEL_PRIVACY,
1700 conn->cli->user_name,
1703 if (conn->samr_pipe == NULL) {
1704 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1705 "pipe for domain %s using NTLMSSP "
1706 "authenticated pipe: user %s\\%s. Error was "
1707 "%s\n", domain->name, conn->cli->domain,
1708 conn->cli->user_name, nt_errstr(result)));
1712 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1713 "domain %s using NTLMSSP authenticated "
1714 "pipe: user %s\\%s\n", domain->name,
1715 conn->cli->domain, conn->cli->user_name ));
1717 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1718 SEC_RIGHTS_MAXIMUM_ALLOWED,
1719 &conn->sam_connect_handle);
1720 if (NT_STATUS_IS_OK(result)) {
1723 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1724 "failed for domain %s, error was %s. Trying schannel\n",
1725 domain->name, nt_errstr(result) ));
1726 cli_rpc_pipe_close(conn->samr_pipe);
1730 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1732 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1733 /* If this call fails - conn->cli can now be NULL ! */
1734 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1735 "for domain %s, trying anon\n", domain->name));
1738 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1739 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1740 domain->name, p_dcinfo, &result);
1742 if (conn->samr_pipe == NULL) {
1743 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1744 "domain %s using schannel. Error was %s\n",
1745 domain->name, nt_errstr(result) ));
1748 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1749 "schannel.\n", domain->name ));
1751 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1752 SEC_RIGHTS_MAXIMUM_ALLOWED,
1753 &conn->sam_connect_handle);
1754 if (NT_STATUS_IS_OK(result)) {
1757 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1758 "for domain %s, error was %s. Trying anonymous\n",
1759 domain->name, nt_errstr(result) ));
1760 cli_rpc_pipe_close(conn->samr_pipe);
1764 /* Finally fall back to anonymous. */
1765 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1768 if (conn->samr_pipe == NULL) {
1769 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1773 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1774 SEC_RIGHTS_MAXIMUM_ALLOWED,
1775 &conn->sam_connect_handle);
1776 if (!NT_STATUS_IS_OK(result)) {
1777 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1778 "for domain %s Error was %s\n",
1779 domain->name, nt_errstr(result) ));
1784 result = rpccli_samr_open_domain(conn->samr_pipe,
1786 &conn->sam_connect_handle,
1787 SEC_RIGHTS_MAXIMUM_ALLOWED,
1789 &conn->sam_domain_handle);
1793 if (!NT_STATUS_IS_OK(result)) {
1794 invalidate_cm_connection(conn);
1798 *cli = conn->samr_pipe;
1799 *sam_handle = conn->sam_domain_handle;
1803 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1804 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1806 struct winbindd_cm_conn *conn;
1807 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1809 struct dcinfo *p_dcinfo;
1811 result = init_dc_connection(domain);
1812 if (!NT_STATUS_IS_OK(result))
1815 conn = &domain->conn;
1817 if (conn->lsa_pipe != NULL) {
1821 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1822 if ((conn->cli->user_name[0] == '\0') ||
1823 (conn->cli->domain[0] == '\0') ||
1824 (conn_pwd[0] == '\0')) {
1825 DEBUG(10, ("cm_connect_lsa: No no user available for "
1826 "domain %s, trying schannel\n", conn->cli->domain));
1830 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1831 * authenticated LSA pipe with sign & seal. */
1832 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1833 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1834 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1836 if (conn->lsa_pipe == NULL) {
1837 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1838 "domain %s using NTLMSSP authenticated pipe: user "
1839 "%s\\%s. Error was %s. Trying schannel.\n",
1840 domain->name, conn->cli->domain,
1841 conn->cli->user_name, nt_errstr(result)));
1845 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1846 "NTLMSSP authenticated pipe: user %s\\%s\n",
1847 domain->name, conn->cli->domain, conn->cli->user_name ));
1849 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1850 SEC_RIGHTS_MAXIMUM_ALLOWED,
1852 if (NT_STATUS_IS_OK(result)) {
1856 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1859 cli_rpc_pipe_close(conn->lsa_pipe);
1863 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1865 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1866 /* If this call fails - conn->cli can now be NULL ! */
1867 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1868 "for domain %s, trying anon\n", domain->name));
1871 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1872 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1873 domain->name, p_dcinfo, &result);
1875 if (conn->lsa_pipe == NULL) {
1876 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1877 "domain %s using schannel. Error was %s\n",
1878 domain->name, nt_errstr(result) ));
1881 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1882 "schannel.\n", domain->name ));
1884 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1885 SEC_RIGHTS_MAXIMUM_ALLOWED,
1887 if (NT_STATUS_IS_OK(result)) {
1891 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1894 cli_rpc_pipe_close(conn->lsa_pipe);
1898 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1900 if (conn->lsa_pipe == NULL) {
1901 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1905 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1906 SEC_RIGHTS_MAXIMUM_ALLOWED,
1909 if (!NT_STATUS_IS_OK(result)) {
1910 invalidate_cm_connection(conn);
1914 *cli = conn->lsa_pipe;
1915 *lsa_policy = conn->lsa_policy;
1919 /****************************************************************************
1920 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1921 session key stored in conn->netlogon_pipe->dc->sess_key.
1922 ****************************************************************************/
1924 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1925 struct rpc_pipe_client **cli)
1927 struct winbindd_cm_conn *conn;
1930 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1932 uint32 sec_chan_type;
1933 const char *account_name;
1934 struct rpc_pipe_client *netlogon_pipe = NULL;
1938 result = init_dc_connection(domain);
1939 if (!NT_STATUS_IS_OK(result)) {
1943 conn = &domain->conn;
1945 if (conn->netlogon_pipe != NULL) {
1946 *cli = conn->netlogon_pipe;
1947 return NT_STATUS_OK;
1950 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1951 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1954 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1956 if (netlogon_pipe == NULL) {
1960 if (lp_client_schannel() != False) {
1961 neg_flags |= NETLOGON_NEG_SCHANNEL;
1964 /* if we are a DC and this is a trusted domain, then we need to use our
1965 domain name in the net_req_auth2() request */
1968 && !strequal(domain->name, lp_workgroup())
1969 && lp_allow_trusted_domains() )
1971 account_name = lp_workgroup();
1973 account_name = domain->primary ?
1974 global_myname() : domain->name;
1977 if (account_name == NULL) {
1978 cli_rpc_pipe_close(netlogon_pipe);
1979 return NT_STATUS_NO_MEMORY;
1982 result = rpccli_netlogon_setup_creds(
1984 domain->dcname, /* server name. */
1985 domain->name, /* domain name */
1986 global_myname(), /* client name */
1987 account_name, /* machine account */
1988 mach_pwd, /* machine password */
1989 sec_chan_type, /* from get_trust_pw */
1992 if (!NT_STATUS_IS_OK(result)) {
1993 cli_rpc_pipe_close(netlogon_pipe);
1997 if ((lp_client_schannel() == True) &&
1998 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1999 DEBUG(3, ("Server did not offer schannel\n"));
2000 cli_rpc_pipe_close(netlogon_pipe);
2001 return NT_STATUS_ACCESS_DENIED;
2004 if ((lp_client_schannel() == False) ||
2005 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2006 /* We're done - just keep the existing connection to NETLOGON
2008 conn->netlogon_pipe = netlogon_pipe;
2009 *cli = conn->netlogon_pipe;
2010 return NT_STATUS_OK;
2013 /* Using the credentials from the first pipe, open a signed and sealed
2014 second netlogon pipe. The session key is stored in the schannel
2015 part of the new pipe auth struct.
2018 conn->netlogon_pipe =
2019 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2021 PIPE_AUTH_LEVEL_PRIVACY,
2026 /* We can now close the initial netlogon pipe. */
2027 cli_rpc_pipe_close(netlogon_pipe);
2029 if (conn->netlogon_pipe == NULL) {
2030 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2031 "was %s\n", nt_errstr(result)));
2033 /* make sure we return something besides OK */
2034 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2037 *cli = conn->netlogon_pipe;
2038 return NT_STATUS_OK;