r14823: committing changes for 3.0.22
[Samba.git] / source / nsswitch / winbindd_cm.c
blobacca6fcb9387184bfca9de77562cf783a1f94a8d
1 /*
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
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
34 selection etc
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
46 implementation. -tpot
51 TODO:
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
57 various sam handles.
61 #include "includes.h"
62 #include "winbindd.h"
64 #undef DBGC_CLASS
65 #define DBGC_CLASS DBGC_WINBIND
68 /* Choose between anonymous or authenticated connections. We need to use
69 an authenticated connection if DCs have the RestrictAnonymous registry
70 entry set > 0, or the "Additional restrictions for anonymous
71 connections" set in the win2k Local Security Policy.
73 Caller to free() result in domain, username, password
76 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
78 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
79 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
80 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
82 if (*username && **username) {
84 if (!*domain || !**domain)
85 *domain = smb_xstrdup(lp_workgroup());
87 if (!*password || !**password)
88 *password = smb_xstrdup("");
90 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
91 *domain, *username));
93 } else {
94 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
95 *username = smb_xstrdup("");
96 *domain = smb_xstrdup("");
97 *password = smb_xstrdup("");
101 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
102 fstring dcname, struct in_addr *dc_ip)
104 struct winbindd_domain *our_domain = NULL;
105 struct rpc_pipe_client *netlogon_pipe = NULL;
106 NTSTATUS result;
107 TALLOC_CTX *mem_ctx;
109 fstring tmp;
110 char *p;
112 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
113 * moment.... */
115 if (IS_DC) {
116 return False;
119 if (domain->primary) {
120 return False;
123 our_domain = find_our_domain();
125 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
126 return False;
129 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
130 if (!NT_STATUS_IS_OK(result)) {
131 return False;
134 result = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
135 domain->name, tmp);
137 talloc_destroy(mem_ctx);
139 if (!NT_STATUS_IS_OK(result)) {
140 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
141 nt_errstr(result)));
142 return False;
145 /* cli_netlogon_getdcname gives us a name with \\ */
146 p = tmp;
147 if (*p == '\\') {
148 p+=1;
150 if (*p == '\\') {
151 p+=1;
154 fstrcpy(dcname, p);
156 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
158 if (!resolve_name(dcname, dc_ip, 0x20)) {
159 return False;
162 return True;
165 /************************************************************************
166 Given a fd with a just-connected TCP connection to a DC, open a connection
167 to the pipe.
168 ************************************************************************/
170 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
171 const int sockfd,
172 const char *controller,
173 struct cli_state **cli,
174 BOOL *retry)
176 char *machine_password, *machine_krb5_principal, *machine_account;
177 char *ipc_username, *ipc_domain, *ipc_password;
179 BOOL got_mutex;
180 BOOL add_failed_connection = True;
182 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
184 struct sockaddr peeraddr;
185 socklen_t peeraddr_len;
187 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
189 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
190 NULL);
192 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
193 SAFE_FREE(machine_password);
194 return NT_STATUS_NO_MEMORY;
197 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
198 lp_realm()) == -1) {
199 SAFE_FREE(machine_account);
200 SAFE_FREE(machine_password);
201 return NT_STATUS_NO_MEMORY;
204 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
206 *retry = True;
208 got_mutex = secrets_named_mutex(controller,
209 WINBIND_SERVER_MUTEX_WAIT_TIME);
211 if (!got_mutex) {
212 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
213 controller));
214 result = NT_STATUS_POSSIBLE_DEADLOCK;
215 goto done;
218 if ((*cli = cli_initialise(NULL)) == NULL) {
219 DEBUG(1, ("Could not cli_initialize\n"));
220 result = NT_STATUS_NO_MEMORY;
221 goto done;
224 (*cli)->timeout = 10000; /* 10 seconds */
225 (*cli)->fd = sockfd;
226 fstrcpy((*cli)->desthost, controller);
227 (*cli)->use_kerberos = True;
229 peeraddr_len = sizeof(peeraddr);
231 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
232 (peeraddr_len != sizeof(struct sockaddr_in)) ||
233 (peeraddr_in->sin_family != PF_INET))
235 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
236 goto done;
239 if (ntohs(peeraddr_in->sin_port) == 139) {
240 struct nmb_name calling;
241 struct nmb_name called;
243 make_nmb_name(&calling, global_myname(), 0x0);
244 make_nmb_name(&called, "*SMBSERVER", 0x20);
246 if (!cli_session_request(*cli, &calling, &called)) {
247 DEBUG(8, ("cli_session_request failed for %s\n",
248 controller));
249 goto done;
253 cli_setup_signing_state(*cli, Undefined);
255 if (!cli_negprot(*cli)) {
256 DEBUG(1, ("cli_negprot failed\n"));
257 cli_shutdown(*cli);
258 goto done;
262 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
263 ADS_STATUS ads_status;
265 if (lp_security() == SEC_ADS) {
267 /* Try a krb5 session */
269 (*cli)->use_kerberos = True;
270 DEBUG(5, ("connecting to %s from %s with kerberos principal "
271 "[%s]\n", controller, global_myname(),
272 machine_krb5_principal));
274 ads_status = cli_session_setup_spnego(*cli,
275 machine_krb5_principal,
276 machine_password,
277 lp_workgroup());
279 if (!ADS_ERR_OK(ads_status)) {
280 DEBUG(4,("failed kerberos session setup with %s\n",
281 ads_errstr(ads_status)));
284 result = ads_ntstatus(ads_status);
285 if (NT_STATUS_IS_OK(result)) {
286 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
287 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
288 goto session_setup_done;
292 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
293 (*cli)->use_kerberos = False;
295 DEBUG(5, ("connecting to %s from %s with username "
296 "[%s]\\[%s]\n", controller, global_myname(),
297 lp_workgroup(), machine_account));
299 ads_status = cli_session_setup_spnego(*cli,
300 machine_account,
301 machine_password,
302 lp_workgroup());
303 if (!ADS_ERR_OK(ads_status)) {
304 DEBUG(4, ("authenticated session setup failed with %s\n",
305 ads_errstr(ads_status)));
308 result = ads_ntstatus(ads_status);
309 if (NT_STATUS_IS_OK(result)) {
310 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
311 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
312 goto session_setup_done;
316 /* Fall back to non-kerberos session setup */
318 (*cli)->use_kerberos = False;
320 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
321 (strlen(ipc_username) > 0)) {
323 /* Only try authenticated if we have a username */
325 DEBUG(5, ("connecting to %s from %s with username "
326 "[%s]\\[%s]\n", controller, global_myname(),
327 ipc_domain, ipc_username));
329 if (cli_session_setup(*cli, ipc_username,
330 ipc_password, strlen(ipc_password)+1,
331 ipc_password, strlen(ipc_password)+1,
332 ipc_domain)) {
333 /* Successful logon with given username. */
334 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
335 goto session_setup_done;
336 } else {
337 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
338 ipc_domain, ipc_username ));
342 /* Fall back to anonymous connection, this might fail later */
344 if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
345 DEBUG(5, ("Connected anonymously\n"));
346 cli_init_creds(*cli, "", "", "");
347 goto session_setup_done;
350 result = cli_nt_error(*cli);
352 if (NT_STATUS_IS_OK(result))
353 result = NT_STATUS_UNSUCCESSFUL;
355 /* We can't session setup */
357 goto done;
359 session_setup_done:
361 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
363 result = cli_nt_error(*cli);
365 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
367 if (NT_STATUS_IS_OK(result))
368 result = NT_STATUS_UNSUCCESSFUL;
370 cli_shutdown(*cli);
371 goto done;
374 secrets_named_mutex_release(controller);
375 got_mutex = False;
376 *retry = False;
378 /* set the domain if empty; needed for schannel connections */
379 if ( !*(*cli)->domain ) {
380 fstrcpy( (*cli)->domain, domain->name );
383 result = NT_STATUS_OK;
384 add_failed_connection = False;
386 done:
387 if (got_mutex) {
388 secrets_named_mutex_release(controller);
391 SAFE_FREE(machine_account);
392 SAFE_FREE(machine_password);
393 SAFE_FREE(machine_krb5_principal);
394 SAFE_FREE(ipc_username);
395 SAFE_FREE(ipc_domain);
396 SAFE_FREE(ipc_password);
398 if (add_failed_connection) {
399 add_failed_connection_entry(domain->name, controller, result);
402 return result;
405 struct dc_name_ip {
406 fstring name;
407 struct in_addr ip;
410 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
411 const char *dcname, struct in_addr ip,
412 struct dc_name_ip **dcs, int *num)
414 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
415 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
416 return False;
419 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
421 if (*dcs == NULL)
422 return False;
424 fstrcpy((*dcs)[*num].name, dcname);
425 (*dcs)[*num].ip = ip;
426 *num += 1;
427 return True;
430 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
431 struct in_addr ip, uint16 port,
432 struct sockaddr_in **addrs, int *num)
434 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
436 if (*addrs == NULL)
437 return False;
439 (*addrs)[*num].sin_family = PF_INET;
440 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
441 (*addrs)[*num].sin_port = htons(port);
443 *num += 1;
444 return True;
447 static void mailslot_name(struct in_addr dc_ip, fstring name)
449 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
452 static BOOL send_getdc_request(struct in_addr dc_ip,
453 const char *domain_name,
454 const DOM_SID *sid)
456 pstring outbuf;
457 char *p;
458 fstring my_acct_name;
459 fstring my_mailslot;
461 mailslot_name(dc_ip, my_mailslot);
463 memset(outbuf, '\0', sizeof(outbuf));
465 p = outbuf;
467 SCVAL(p, 0, SAMLOGON);
468 p++;
470 SCVAL(p, 0, 0); /* Count pointer ... */
471 p++;
473 SIVAL(p, 0, 0); /* The sender's token ... */
474 p += 2;
476 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
477 fstr_sprintf(my_acct_name, "%s$", global_myname());
478 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
480 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
481 p += strlen(my_mailslot)+1;
483 SIVAL(p, 0, 0x80);
484 p+=4;
486 SIVAL(p, 0, sid_size(sid));
487 p+=4;
489 p = ALIGN4(p, outbuf);
491 sid_linearize(p, sid_size(sid), sid);
492 p += sid_size(sid);
494 SIVAL(p, 0, 1);
495 SSVAL(p, 4, 0xffff);
496 SSVAL(p, 6, 0xffff);
497 p+=8;
499 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
500 outbuf, PTR_DIFF(p, outbuf),
501 global_myname(), 0, domain_name, 0x1c,
502 dc_ip);
505 static BOOL receive_getdc_response(struct in_addr dc_ip,
506 const char *domain_name,
507 fstring dc_name)
509 struct packet_struct *packet;
510 fstring my_mailslot;
511 char *buf, *p;
512 fstring dcname, user, domain;
513 int len;
515 mailslot_name(dc_ip, my_mailslot);
517 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
519 if (packet == NULL) {
520 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
521 return False;
524 DEBUG(5, ("Received packet for %s\n", my_mailslot));
526 buf = packet->packet.dgram.data;
527 len = packet->packet.dgram.datasize;
529 if (len < 70) {
530 /* 70 is a completely arbitrary value to make sure
531 the SVAL below does not read uninitialized memory */
532 DEBUG(3, ("GetDC got short response\n"));
533 return False;
536 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
537 p = buf+SVAL(buf, smb_vwv10);
539 if (CVAL(p,0) != SAMLOGON_R) {
540 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
541 return False;
544 p+=2;
545 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
546 STR_TERMINATE|STR_NOALIGN);
547 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
548 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
549 STR_TERMINATE|STR_NOALIGN);
550 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
551 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
552 STR_TERMINATE|STR_NOALIGN);
553 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
555 if (!strequal(domain, domain_name)) {
556 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
557 domain_name, domain));
558 return False;
561 p = dcname;
562 if (*p == '\\') p += 1;
563 if (*p == '\\') p += 1;
565 fstrcpy(dc_name, p);
567 DEBUG(10, ("GetDC gave name %s for domain %s\n",
568 dc_name, domain));
570 return True;
573 /*******************************************************************
574 convert an ip to a name
575 *******************************************************************/
577 static void dcip_to_name( const char *domainname, const char *realm,
578 const DOM_SID *sid, struct in_addr ip, fstring name )
581 /* try GETDC requests first */
583 if (send_getdc_request(ip, domainname, sid)) {
584 int i;
585 smb_msleep(100);
586 for (i=0; i<5; i++) {
587 if (receive_getdc_response(ip, domainname, name))
588 return;
589 smb_msleep(500);
593 /* try node status request */
595 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
596 return;
598 /* backup in case the netbios stuff fails */
600 fstrcpy( name, inet_ntoa(ip) );
602 #ifdef WITH_ADS
603 /* for active directory servers, try to get the ldap server name.
604 None of these failure should be considered critical for now */
606 if ( lp_security() == SEC_ADS )
608 ADS_STRUCT *ads;
609 ADS_STATUS status;
611 ads = ads_init( realm, domainname, NULL );
612 ads->auth.flags |= ADS_AUTH_NO_BIND;
614 if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) ) {
615 ads_destroy( &ads );
616 return;
619 status = ads_server_info(ads);
620 if ( !ADS_ERR_OK(status) ) {
621 ads_destroy( &ads );
622 return;
625 fstrcpy(name, ads->config.ldap_server_name);
627 ads_destroy( &ads );
629 #endif
631 return;
634 /*******************************************************************
635 Retreive a list of IP address for domain controllers. Fill in
636 the dcs[] with results.
637 *******************************************************************/
639 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
640 struct dc_name_ip **dcs, int *num_dcs)
642 fstring dcname;
643 struct in_addr ip;
644 struct ip_service *ip_list = NULL;
645 int iplist_size = 0;
646 int i;
647 BOOL is_our_domain;
650 is_our_domain = strequal(domain->name, lp_workgroup());
652 if ( !is_our_domain
653 && get_dc_name_via_netlogon(domain, dcname, &ip)
654 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
656 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
657 dcname, inet_ntoa(ip)));
658 return True;
661 if ( is_our_domain
662 && must_use_pdc(domain->name)
663 && get_pdc_ip(domain->name, &ip))
665 if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs))
666 return True;
669 /* try standard netbios queries first */
671 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
673 /* check for security = ads and use DNS if we can */
675 if ( iplist_size==0 && lp_security() == SEC_ADS )
676 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
678 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
680 /* now add to the dc array. We'll wait until the last minute
681 to look up the name of the DC. But we fill in the char* for
682 the ip now in to make the failed connection cache work */
684 for ( i=0; i<iplist_size; i++ ) {
685 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
686 ip_list[i].ip, dcs, num_dcs);
689 SAFE_FREE( ip_list );
691 return True;
694 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
695 const struct winbindd_domain *domain,
696 fstring dcname, struct sockaddr_in *addr, int *fd)
698 struct dc_name_ip *dcs = NULL;
699 int num_dcs = 0;
701 const char **dcnames = NULL;
702 int num_dcnames = 0;
704 struct sockaddr_in *addrs = NULL;
705 int num_addrs = 0;
707 int i, fd_index;
709 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
710 return False;
712 for (i=0; i<num_dcs; i++) {
714 add_string_to_array(mem_ctx, dcs[i].name,
715 &dcnames, &num_dcnames);
716 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
717 &addrs, &num_addrs);
719 add_string_to_array(mem_ctx, dcs[i].name,
720 &dcnames, &num_dcnames);
721 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
722 &addrs, &num_addrs);
725 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
726 return False;
728 if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) )
730 for (i=0; i<num_dcs; i++) {
731 add_failed_connection_entry(domain->name,
732 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
734 return False;
737 *addr = addrs[fd_index];
739 /* if we have no name on the server or just an IP address for
740 the name, now try to get the name */
742 if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
743 dcip_to_name( domain->name, domain->alt_name, &domain->sid, addr->sin_addr, dcname );
744 else
745 fstrcpy(dcname, dcnames[fd_index]);
747 return True;
750 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
751 struct winbindd_cm_conn *new_conn)
753 TALLOC_CTX *mem_ctx;
754 NTSTATUS result;
756 int retries;
758 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
759 return NT_STATUS_NO_MEMORY;
761 for (retries = 0; retries < 3; retries++) {
763 int fd = -1;
764 BOOL retry = False;
766 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
768 if ((strlen(domain->dcname) > 0) &&
769 NT_STATUS_IS_OK(check_negative_conn_cache(
770 domain->name, domain->dcname)) &&
771 (resolve_name(domain->dcname, &domain->dcaddr.sin_addr,
772 0x20))) {
773 int dummy;
774 struct sockaddr_in addrs[2];
775 addrs[0] = domain->dcaddr;
776 addrs[0].sin_port = htons(445);
777 addrs[1] = domain->dcaddr;
778 addrs[1].sin_port = htons(139);
779 if (!open_any_socket_out(addrs, 2, 10000,
780 &dummy, &fd)) {
781 fd = -1;
785 if ((fd == -1) &&
786 !find_new_dc(mem_ctx, domain, domain->dcname,
787 &domain->dcaddr, &fd))
788 break;
790 new_conn->cli = NULL;
792 result = cm_prepare_connection(domain, fd, domain->dcname,
793 &new_conn->cli, &retry);
795 if (!retry)
796 break;
799 talloc_destroy(mem_ctx);
800 return result;
803 /* Return true if a connection is still alive */
805 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
807 if (conn->samr_pipe != NULL) {
808 cli_rpc_pipe_close(conn->samr_pipe);
809 conn->samr_pipe = NULL;
812 if (conn->lsa_pipe != NULL) {
813 cli_rpc_pipe_close(conn->lsa_pipe);
814 conn->lsa_pipe = NULL;
817 if (conn->netlogon_pipe != NULL) {
818 cli_rpc_pipe_close(conn->netlogon_pipe);
819 conn->netlogon_pipe = NULL;
822 if (conn->cli) {
823 cli_shutdown(conn->cli);
826 conn->cli = NULL;
829 void close_conns_after_fork(void)
831 struct winbindd_domain *domain;
833 for (domain = domain_list(); domain; domain = domain->next) {
834 if (domain->conn.cli == NULL)
835 continue;
837 if (domain->conn.cli->fd == -1)
838 continue;
840 close(domain->conn.cli->fd);
841 domain->conn.cli->fd = -1;
845 static BOOL connection_ok(struct winbindd_domain *domain)
847 if (domain->conn.cli == NULL) {
848 DEBUG(8, ("Connection to %s for domain %s has NULL "
849 "cli!\n", domain->dcname, domain->name));
850 return False;
853 if (!domain->conn.cli->initialised) {
854 DEBUG(3, ("Connection to %s for domain %s was never "
855 "initialised!\n", domain->dcname, domain->name));
856 return False;
859 if (domain->conn.cli->fd == -1) {
860 DEBUG(3, ("Connection to %s for domain %s has died or was "
861 "never started (fd == -1)\n",
862 domain->dcname, domain->name));
863 return False;
866 return True;
869 /* Initialize a new connection up to the RPC BIND. */
871 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
873 if (connection_ok(domain))
874 return NT_STATUS_OK;
876 invalidate_cm_connection(&domain->conn);
878 return cm_open_connection(domain, &domain->conn);
881 /******************************************************************************
882 We can 'sense' certain things about the DC by it's replies to certain
883 questions.
885 This tells us if this particular remote server is Active Directory, and if it
886 is native mode.
887 ******************************************************************************/
889 void set_dc_type_and_flags( struct winbindd_domain *domain )
891 NTSTATUS result;
892 DS_DOMINFO_CTR ctr;
893 TALLOC_CTX *mem_ctx = NULL;
894 struct rpc_pipe_client *cli;
895 POLICY_HND pol;
897 char *domain_name = NULL;
898 char *dns_name = NULL;
899 DOM_SID *dom_sid = NULL;
901 ZERO_STRUCT( ctr );
903 domain->native_mode = False;
904 domain->active_directory = False;
906 if (domain->internal) {
907 domain->initialized = True;
908 return;
911 result = init_dc_connection(domain);
912 if (!NT_STATUS_IS_OK(result)) {
913 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
914 "to %s: (%s)\n", domain->name, nt_errstr(result)));
915 domain->initialized = True;
916 return;
919 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
920 &result);
922 if (cli == NULL) {
923 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
924 "PI_LSARPC_DS on domain %s: (%s)\n",
925 domain->name, nt_errstr(result)));
926 domain->initialized = True;
927 return;
930 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
931 DsRolePrimaryDomainInfoBasic,
932 &ctr);
933 cli_rpc_pipe_close(cli);
935 if (!NT_STATUS_IS_OK(result)) {
936 domain->initialized = True;
937 return;
940 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
941 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
942 domain->native_mode = True;
944 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
946 if (cli == NULL) {
947 domain->initialized = True;
948 return;
951 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
952 domain->name);
953 if (!mem_ctx) {
954 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
955 cli_rpc_pipe_close(cli);
956 return;
959 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
960 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
962 if (NT_STATUS_IS_OK(result)) {
963 /* This particular query is exactly what Win2k clients use
964 to determine that the DC is active directory */
965 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
966 12, &domain_name,
967 &dns_name, NULL,
968 NULL, &dom_sid);
971 if (NT_STATUS_IS_OK(result)) {
972 if (domain_name)
973 fstrcpy(domain->name, domain_name);
975 if (dns_name)
976 fstrcpy(domain->alt_name, dns_name);
978 if (dom_sid)
979 sid_copy(&domain->sid, dom_sid);
981 domain->active_directory = True;
982 } else {
984 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
985 SEC_RIGHTS_MAXIMUM_ALLOWED,
986 &pol);
988 if (!NT_STATUS_IS_OK(result))
989 goto done;
991 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
992 &pol, 5, &domain_name,
993 &dom_sid);
995 if (NT_STATUS_IS_OK(result)) {
996 if (domain_name)
997 fstrcpy(domain->name, domain_name);
999 if (dom_sid)
1000 sid_copy(&domain->sid, dom_sid);
1003 done:
1005 cli_rpc_pipe_close(cli);
1007 talloc_destroy(mem_ctx);
1009 domain->initialized = True;
1011 return;
1014 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1015 struct dcinfo **ppdc)
1017 NTSTATUS result;
1018 struct rpc_pipe_client *netlogon_pipe;
1020 if (lp_client_schannel() == False) {
1021 return False;
1024 result = cm_connect_netlogon(domain, &netlogon_pipe);
1025 if (!NT_STATUS_IS_OK(result)) {
1026 return False;
1029 /* Return a pointer to the struct dcinfo from the
1030 netlogon pipe. */
1032 *ppdc = domain->conn.netlogon_pipe->dc;
1033 return True;
1036 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1037 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1039 struct winbindd_cm_conn *conn;
1040 NTSTATUS result;
1041 fstring conn_pwd;
1042 struct dcinfo *p_dcinfo;
1044 result = init_dc_connection(domain);
1045 if (!NT_STATUS_IS_OK(result)) {
1046 return result;
1049 conn = &domain->conn;
1051 if (conn->samr_pipe != NULL) {
1052 goto done;
1056 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1057 * sign and sealed pipe using the machine account password by
1058 * preference. If we can't - try schannel, if that fails, try
1059 * anonymous.
1062 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1063 if ((conn->cli->user_name[0] == '\0') ||
1064 (conn->cli->domain[0] == '\0') ||
1065 (conn_pwd[0] == '\0')) {
1066 DEBUG(10, ("cm_connect_sam: No no user available for "
1067 "domain %s, trying schannel\n", conn->cli->domain));
1068 goto schannel;
1071 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1072 authenticated SAMR pipe with sign & seal. */
1073 conn->samr_pipe =
1074 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1075 PIPE_AUTH_LEVEL_PRIVACY,
1076 conn->cli->domain,
1077 conn->cli->user_name,
1078 conn_pwd, &result);
1080 if (conn->samr_pipe == NULL) {
1081 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1082 "pipe for domain %s using NTLMSSP "
1083 "authenticated pipe: user %s\\%s. Error was "
1084 "%s\n", domain->name, conn->cli->domain,
1085 conn->cli->user_name, nt_errstr(result)));
1086 goto schannel;
1089 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1090 "domain %s using NTLMSSP authenticated "
1091 "pipe: user %s\\%s\n", domain->name,
1092 conn->cli->domain, conn->cli->user_name ));
1094 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1095 SEC_RIGHTS_MAXIMUM_ALLOWED,
1096 &conn->sam_connect_handle);
1097 if (NT_STATUS_IS_OK(result)) {
1098 goto open_domain;
1100 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1101 "failed for domain %s, error was %s. Trying schannel\n",
1102 domain->name, nt_errstr(result) ));
1103 cli_rpc_pipe_close(conn->samr_pipe);
1105 schannel:
1107 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1109 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1110 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1111 "for domain %s, trying anon\n", conn->cli->domain));
1112 goto anonymous;
1114 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1115 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1116 domain->name, p_dcinfo, &result);
1118 if (conn->samr_pipe == NULL) {
1119 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1120 "domain %s using schannel. Error was %s\n",
1121 domain->name, nt_errstr(result) ));
1122 goto anonymous;
1124 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1125 "schannel.\n", domain->name ));
1127 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1128 SEC_RIGHTS_MAXIMUM_ALLOWED,
1129 &conn->sam_connect_handle);
1130 if (NT_STATUS_IS_OK(result)) {
1131 goto open_domain;
1133 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1134 "for domain %s, error was %s. Trying anonymous\n",
1135 domain->name, nt_errstr(result) ));
1136 cli_rpc_pipe_close(conn->samr_pipe);
1138 anonymous:
1140 /* Finally fall back to anonymous. */
1141 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1142 &result);
1144 if (conn->samr_pipe == NULL) {
1145 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1146 goto done;
1149 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1150 SEC_RIGHTS_MAXIMUM_ALLOWED,
1151 &conn->sam_connect_handle);
1152 if (!NT_STATUS_IS_OK(result)) {
1153 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1154 "for domain %s Error was %s\n",
1155 domain->name, nt_errstr(result) ));
1156 goto done;
1159 open_domain:
1160 result = rpccli_samr_open_domain(conn->samr_pipe,
1161 mem_ctx,
1162 &conn->sam_connect_handle,
1163 SEC_RIGHTS_MAXIMUM_ALLOWED,
1164 &domain->sid,
1165 &conn->sam_domain_handle);
1167 done:
1169 if (!NT_STATUS_IS_OK(result)) {
1170 invalidate_cm_connection(conn);
1171 return result;
1174 *cli = conn->samr_pipe;
1175 *sam_handle = conn->sam_domain_handle;
1176 return result;
1179 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1180 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1182 struct winbindd_cm_conn *conn;
1183 NTSTATUS result;
1184 fstring conn_pwd;
1185 struct dcinfo *p_dcinfo;
1187 result = init_dc_connection(domain);
1188 if (!NT_STATUS_IS_OK(result))
1189 return result;
1191 conn = &domain->conn;
1193 if (conn->lsa_pipe != NULL) {
1194 goto done;
1197 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1198 if ((conn->cli->user_name[0] == '\0') ||
1199 (conn->cli->domain[0] == '\0') ||
1200 (conn_pwd[0] == '\0')) {
1201 DEBUG(10, ("cm_connect_lsa: No no user available for "
1202 "domain %s, trying schannel\n", conn->cli->domain));
1203 goto schannel;
1206 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1207 * authenticated LSA pipe with sign & seal. */
1208 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1209 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1210 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1212 if (conn->lsa_pipe == NULL) {
1213 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1214 "domain %s using NTLMSSP authenticated pipe: user "
1215 "%s\\%s. Error was %s. Trying schannel.\n",
1216 domain->name, conn->cli->domain,
1217 conn->cli->user_name, nt_errstr(result)));
1218 goto schannel;
1221 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1222 "NTLMSSP authenticated pipe: user %s\\%s\n",
1223 domain->name, conn->cli->domain, conn->cli->user_name ));
1225 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1226 SEC_RIGHTS_MAXIMUM_ALLOWED,
1227 &conn->lsa_policy);
1228 if (NT_STATUS_IS_OK(result)) {
1229 goto done;
1232 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1233 "schannel\n"));
1235 cli_rpc_pipe_close(conn->lsa_pipe);
1237 schannel:
1239 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1241 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1242 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1243 "for domain %s, trying anon\n", conn->cli->domain));
1244 goto anonymous;
1246 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1247 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1248 domain->name, p_dcinfo, &result);
1250 if (conn->lsa_pipe == NULL) {
1251 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1252 "domain %s using schannel. Error was %s\n",
1253 domain->name, nt_errstr(result) ));
1254 goto anonymous;
1256 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1257 "schannel.\n", domain->name ));
1259 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1260 SEC_RIGHTS_MAXIMUM_ALLOWED,
1261 &conn->lsa_policy);
1262 if (NT_STATUS_IS_OK(result)) {
1263 goto done;
1266 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1267 "anonymous\n"));
1269 cli_rpc_pipe_close(conn->lsa_pipe);
1271 anonymous:
1273 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1274 &result);
1275 if (conn->lsa_pipe == NULL) {
1276 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1277 goto done;
1280 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1281 SEC_RIGHTS_MAXIMUM_ALLOWED,
1282 &conn->lsa_policy);
1283 done:
1284 if (!NT_STATUS_IS_OK(result)) {
1285 invalidate_cm_connection(conn);
1286 return NT_STATUS_UNSUCCESSFUL;
1289 *cli = conn->lsa_pipe;
1290 *lsa_policy = conn->lsa_policy;
1291 return result;
1294 /****************************************************************************
1295 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1296 session key stored in conn->netlogon_pipe->dc->sess_key.
1297 ****************************************************************************/
1299 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1300 struct rpc_pipe_client **cli)
1302 struct winbindd_cm_conn *conn;
1303 NTSTATUS result;
1305 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1306 uint8 mach_pwd[16];
1307 uint32 sec_chan_type;
1308 const char *account_name;
1309 struct rpc_pipe_client *netlogon_pipe = NULL;
1311 *cli = NULL;
1313 result = init_dc_connection(domain);
1314 if (!NT_STATUS_IS_OK(result)) {
1315 return result;
1318 conn = &domain->conn;
1320 if (conn->netlogon_pipe != NULL) {
1321 *cli = conn->netlogon_pipe;
1322 return NT_STATUS_OK;
1325 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1326 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1329 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1330 &result);
1331 if (netlogon_pipe == NULL) {
1332 return result;
1335 if (lp_client_schannel() != False) {
1336 neg_flags |= NETLOGON_NEG_SCHANNEL;
1339 /* if we are a DC and this is a trusted domain, then we need to use our
1340 domain name in the net_req_auth2() request */
1342 if ( IS_DC
1343 && !strequal(domain->name, lp_workgroup())
1344 && lp_allow_trusted_domains() )
1346 account_name = lp_workgroup();
1347 } else {
1348 account_name = domain->primary ?
1349 global_myname() : domain->name;
1352 if (account_name == NULL) {
1353 cli_rpc_pipe_close(netlogon_pipe);
1354 return NT_STATUS_NO_MEMORY;
1357 result = rpccli_netlogon_setup_creds(
1358 netlogon_pipe,
1359 domain->dcname, /* server name. */
1360 domain->name, /* domain name */
1361 global_myname(), /* client name */
1362 account_name, /* machine account */
1363 mach_pwd, /* machine password */
1364 sec_chan_type, /* from get_trust_pw */
1365 &neg_flags);
1367 if (!NT_STATUS_IS_OK(result)) {
1368 cli_rpc_pipe_close(netlogon_pipe);
1369 return result;
1372 if ((lp_client_schannel() == True) &&
1373 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1374 DEBUG(3, ("Server did not offer schannel\n"));
1375 cli_rpc_pipe_close(netlogon_pipe);
1376 return NT_STATUS_ACCESS_DENIED;
1379 if ((lp_client_schannel() == False) ||
1380 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1381 /* We're done - just keep the existing connection to NETLOGON
1382 * open */
1383 conn->netlogon_pipe = netlogon_pipe;
1384 *cli = conn->netlogon_pipe;
1385 return NT_STATUS_OK;
1388 /* Using the credentials from the first pipe, open a signed and sealed
1389 second netlogon pipe. The session key is stored in the schannel
1390 part of the new pipe auth struct.
1393 conn->netlogon_pipe =
1394 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1395 PI_NETLOGON,
1396 PIPE_AUTH_LEVEL_PRIVACY,
1397 domain->name,
1398 netlogon_pipe->dc,
1399 &result);
1401 /* We can now close the initial netlogon pipe. */
1402 cli_rpc_pipe_close(netlogon_pipe);
1404 if (conn->netlogon_pipe == NULL) {
1405 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1406 "was %s\n", nt_errstr(result)));
1407 return result;
1410 *cli = conn->netlogon_pipe;
1411 return NT_STATUS_OK;