r11323: Fix usage of rpccli_netlogon_getdcname. Add some debug messages.
[Samba/nascimento.git] / source3 / nsswitch / winbindd_cm.c
blobe02e219c24aa4ff5e6ff5a75fb394de222853ed3
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 /******************************************************************
69 Disabling schannl on the LSA pipe for now since
70 both Win2K-SP4 SR1 & Win2K3-SP1 fail the open_policy()
71 call (return codes 0xc0020042 and 0xc0020041 respectively).
72 We really need to fix this soon. Had to disable on the
73 SAMR pipe as well for now. --jerry
74 ******************************************************************/
76 /* #define DISABLE_SCHANNEL_WIN2K3_SP1 1 */
79 /* Choose between anonymous or authenticated connections. We need to use
80 an authenticated connection if DCs have the RestrictAnonymous registry
81 entry set > 0, or the "Additional restrictions for anonymous
82 connections" set in the win2k Local Security Policy.
84 Caller to free() result in domain, username, password
87 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
89 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
90 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
91 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
93 if (*username && **username) {
95 if (!*domain || !**domain)
96 *domain = smb_xstrdup(lp_workgroup());
98 if (!*password || !**password)
99 *password = smb_xstrdup("");
101 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
102 *domain, *username));
104 } else {
105 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
106 *username = smb_xstrdup("");
107 *domain = smb_xstrdup("");
108 *password = smb_xstrdup("");
112 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
113 fstring dcname, struct in_addr *dc_ip)
115 struct winbindd_domain *our_domain;
116 struct rpc_pipe_client *netlogon_pipe;
117 NTSTATUS result;
118 TALLOC_CTX *mem_ctx;
119 const char *server_name;
121 fstring tmp;
122 char *p;
124 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
125 * moment.... */
127 if (IS_DC) {
128 return False;
131 if (domain->primary) {
132 return False;
135 our_domain = find_our_domain();
137 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
138 return False;
141 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
142 if (!NT_STATUS_IS_OK(result)) {
143 return False;
146 server_name = talloc_asprintf(mem_ctx, "\\\\%s", our_domain->dcname);
147 if (server_name == NULL) {
148 return False;
151 result = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, server_name,
152 domain->name, tmp);
154 talloc_destroy(mem_ctx);
156 if (!NT_STATUS_IS_OK(result)) {
157 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
158 nt_errstr(result)));
159 return False;
162 /* cli_netlogon_getdcname gives us a name with \\ */
163 p = tmp;
164 if (*p == '\\') {
165 p+=1;
167 if (*p == '\\') {
168 p+=1;
171 fstrcpy(dcname, p);
173 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
175 if (!resolve_name(dcname, dc_ip, 0x20)) {
176 return False;
179 return True;
182 /************************************************************************
183 Given a fd with a just-connected TCP connection to a DC, open a connection
184 to the pipe.
185 ************************************************************************/
187 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
188 const int sockfd,
189 const char *controller,
190 struct cli_state **cli,
191 BOOL *retry)
193 char *machine_password, *machine_krb5_principal, *machine_account;
194 char *ipc_username, *ipc_domain, *ipc_password;
196 BOOL got_mutex;
197 BOOL add_failed_connection = True;
199 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
201 struct sockaddr peeraddr;
202 socklen_t peeraddr_len;
204 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
206 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
207 NULL);
209 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
210 SAFE_FREE(machine_password);
211 return NT_STATUS_NO_MEMORY;
214 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
215 lp_realm()) == -1) {
216 SAFE_FREE(machine_account);
217 SAFE_FREE(machine_password);
218 return NT_STATUS_NO_MEMORY;
221 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
223 *retry = True;
225 got_mutex = secrets_named_mutex(controller,
226 WINBIND_SERVER_MUTEX_WAIT_TIME);
228 if (!got_mutex) {
229 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n",
230 controller));
231 result = NT_STATUS_POSSIBLE_DEADLOCK;
232 goto done;
235 if ((*cli = cli_initialise(NULL)) == NULL) {
236 DEBUG(1, ("Could not cli_initialize\n"));
237 result = NT_STATUS_NO_MEMORY;
238 goto done;
241 (*cli)->timeout = 10000; /* 10 seconds */
242 (*cli)->fd = sockfd;
243 fstrcpy((*cli)->desthost, controller);
244 (*cli)->use_kerberos = True;
246 peeraddr_len = sizeof(peeraddr);
248 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
249 (peeraddr_len != sizeof(struct sockaddr_in)) ||
250 (peeraddr_in->sin_family != PF_INET))
252 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
253 goto done;
256 if (ntohs(peeraddr_in->sin_port) == 139) {
257 struct nmb_name calling;
258 struct nmb_name called;
260 make_nmb_name(&calling, global_myname(), 0x0);
261 make_nmb_name(&called, "*SMBSERVER", 0x20);
263 if (!cli_session_request(*cli, &calling, &called)) {
264 DEBUG(8, ("cli_session_request failed for %s\n",
265 controller));
266 goto done;
270 cli_setup_signing_state(*cli, Undefined);
272 if (!cli_negprot(*cli)) {
273 DEBUG(1, ("cli_negprot failed\n"));
274 cli_shutdown(*cli);
275 goto done;
279 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
280 ADS_STATUS ads_status;
282 if (lp_security() == SEC_ADS) {
284 /* Try a krb5 session */
286 (*cli)->use_kerberos = True;
287 DEBUG(5, ("connecting to %s from %s with kerberos principal "
288 "[%s]\n", controller, global_myname(),
289 machine_krb5_principal));
291 ads_status = cli_session_setup_spnego(*cli,
292 machine_krb5_principal,
293 machine_password,
294 lp_workgroup());
296 if (!ADS_ERR_OK(ads_status)) {
297 DEBUG(4,("failed kerberos session setup with %s\n",
298 ads_errstr(ads_status)));
301 result = ads_ntstatus(ads_status);
302 if (NT_STATUS_IS_OK(result)) {
303 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
304 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
305 goto session_setup_done;
309 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
310 (*cli)->use_kerberos = False;
312 DEBUG(5, ("connecting to %s from %s with username "
313 "[%s]\\[%s]\n", controller, global_myname(),
314 machine_account, machine_password));
316 ads_status = cli_session_setup_spnego(*cli,
317 machine_account,
318 machine_password,
319 lp_workgroup());
320 if (!ADS_ERR_OK(ads_status)) {
321 DEBUG(4, ("authenticated session setup failed with %s\n",
322 ads_errstr(ads_status)));
325 result = ads_ntstatus(ads_status);
326 if (NT_STATUS_IS_OK(result)) {
327 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
328 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
329 goto session_setup_done;
333 /* Fall back to non-kerberos session setup */
335 (*cli)->use_kerberos = False;
337 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
338 (strlen(ipc_username) > 0)) {
340 /* Only try authenticated if we have a username */
342 DEBUG(5, ("connecting to %s from %s with username "
343 "[%s]\\[%s]\n", controller, global_myname(),
344 ipc_domain, ipc_username));
346 if (cli_session_setup(*cli, ipc_username,
347 ipc_password, strlen(ipc_password)+1,
348 ipc_password, strlen(ipc_password)+1,
349 ipc_domain)) {
350 /* Successful logon with given username. */
351 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
352 goto session_setup_done;
353 } else {
354 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
355 ipc_domain, ipc_username ));
359 /* Fall back to anonymous connection, this might fail later */
361 if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
362 DEBUG(5, ("Connected anonymously\n"));
363 cli_init_creds(*cli, "", "", "");
364 goto session_setup_done;
367 result = cli_nt_error(*cli);
369 if (NT_STATUS_IS_OK(result))
370 result = NT_STATUS_UNSUCCESSFUL;
372 /* We can't session setup */
374 goto done;
376 session_setup_done:
378 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
380 result = cli_nt_error(*cli);
382 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
384 if (NT_STATUS_IS_OK(result))
385 result = NT_STATUS_UNSUCCESSFUL;
387 cli_shutdown(*cli);
388 goto done;
391 secrets_named_mutex_release(controller);
392 got_mutex = False;
393 *retry = False;
395 /* set the domain if empty; needed for schannel connections */
396 if ( !*(*cli)->domain ) {
397 fstrcpy( (*cli)->domain, domain->name );
400 result = NT_STATUS_OK;
401 add_failed_connection = False;
403 done:
404 if (got_mutex) {
405 secrets_named_mutex_release(controller);
408 SAFE_FREE(machine_account);
409 SAFE_FREE(machine_password);
410 SAFE_FREE(machine_krb5_principal);
411 SAFE_FREE(ipc_username);
412 SAFE_FREE(ipc_domain);
413 SAFE_FREE(ipc_password);
415 if (add_failed_connection) {
416 add_failed_connection_entry(domain->name, controller, result);
419 return result;
422 struct dc_name_ip {
423 fstring name;
424 struct in_addr ip;
427 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
428 const char *dcname, struct in_addr ip,
429 struct dc_name_ip **dcs, int *num)
431 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
432 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
433 return False;
436 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
438 if (*dcs == NULL)
439 return False;
441 fstrcpy((*dcs)[*num].name, dcname);
442 (*dcs)[*num].ip = ip;
443 *num += 1;
444 return True;
447 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
448 struct in_addr ip, uint16 port,
449 struct sockaddr_in **addrs, int *num)
451 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
453 if (*addrs == NULL)
454 return False;
456 (*addrs)[*num].sin_family = PF_INET;
457 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
458 (*addrs)[*num].sin_port = htons(port);
460 *num += 1;
461 return True;
464 static void mailslot_name(struct in_addr dc_ip, fstring name)
466 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
469 static BOOL send_getdc_request(struct in_addr dc_ip,
470 const char *domain_name,
471 const DOM_SID *sid)
473 pstring outbuf;
474 char *p;
475 fstring my_acct_name;
476 fstring my_mailslot;
478 mailslot_name(dc_ip, my_mailslot);
480 memset(outbuf, '\0', sizeof(outbuf));
482 p = outbuf;
484 SCVAL(p, 0, SAMLOGON);
485 p++;
487 SCVAL(p, 0, 0); /* Count pointer ... */
488 p++;
490 SIVAL(p, 0, 0); /* The sender's token ... */
491 p += 2;
493 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
494 fstr_sprintf(my_acct_name, "%s$", global_myname());
495 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
497 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
498 p += strlen(my_mailslot)+1;
500 SIVAL(p, 0, 0x80);
501 p+=4;
503 SIVAL(p, 0, sid_size(sid));
504 p+=4;
506 p = ALIGN4(p, outbuf);
508 sid_linearize(p, sid_size(sid), sid);
509 p += sid_size(sid);
511 SIVAL(p, 0, 1);
512 SSVAL(p, 4, 0xffff);
513 SSVAL(p, 6, 0xffff);
514 p+=8;
516 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
517 outbuf, PTR_DIFF(p, outbuf),
518 global_myname(), 0, domain_name, 0x1c,
519 dc_ip);
522 static BOOL receive_getdc_response(struct in_addr dc_ip,
523 const char *domain_name,
524 fstring dc_name)
526 struct packet_struct *packet;
527 fstring my_mailslot;
528 char *buf, *p;
529 fstring dcname, user, domain;
530 int len;
532 mailslot_name(dc_ip, my_mailslot);
534 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
536 if (packet == NULL) {
537 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
538 return False;
541 DEBUG(5, ("Received packet for %s\n", my_mailslot));
543 buf = packet->packet.dgram.data;
544 len = packet->packet.dgram.datasize;
546 if (len < 70) {
547 /* 70 is a completely arbitrary value to make sure
548 the SVAL below does not read uninitialized memory */
549 DEBUG(3, ("GetDC got short response\n"));
550 return False;
553 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
554 p = buf+SVAL(buf, smb_vwv10);
556 if (CVAL(p,0) != SAMLOGON_R) {
557 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
558 return False;
561 p+=2;
562 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
563 STR_TERMINATE|STR_NOALIGN);
564 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
565 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
566 STR_TERMINATE|STR_NOALIGN);
567 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
568 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
569 STR_TERMINATE|STR_NOALIGN);
570 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
572 if (!strequal(domain, domain_name)) {
573 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
574 domain_name, domain));
575 return False;
578 p = dcname;
579 if (*p == '\\') p += 1;
580 if (*p == '\\') p += 1;
582 fstrcpy(dc_name, p);
584 DEBUG(10, ("GetDC gave name %s for domain %s\n",
585 dc_name, domain));
587 return True;
590 /*******************************************************************
591 convert an ip to a name
592 *******************************************************************/
594 static void dcip_to_name( const char *domainname, const char *realm,
595 const DOM_SID *sid, struct in_addr ip, fstring name )
598 /* try GETDC requests first */
600 if (send_getdc_request(ip, domainname, sid)) {
601 int i;
602 smb_msleep(100);
603 for (i=0; i<5; i++) {
604 if (receive_getdc_response(ip, domainname, name))
605 return;
606 smb_msleep(500);
610 /* try node status request */
612 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
613 return;
615 /* backup in case the netbios stuff fails */
617 fstrcpy( name, inet_ntoa(ip) );
619 #ifdef WITH_ADS
620 /* for active directory servers, try to get the ldap server name.
621 None of these failure should be considered critical for now */
623 if ( lp_security() == SEC_ADS )
625 ADS_STRUCT *ads;
626 ADS_STATUS status;
628 ads = ads_init( realm, domainname, NULL );
629 ads->auth.flags |= ADS_AUTH_NO_BIND;
631 if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) ) {
632 ads_destroy( &ads );
633 return;
636 status = ads_server_info(ads);
637 if ( !ADS_ERR_OK(status) ) {
638 ads_destroy( &ads );
639 return;
642 fstrcpy(name, ads->config.ldap_server_name);
644 ads_destroy( &ads );
646 #endif
648 return;
651 /*******************************************************************
652 Retreive a list of IP address for domain controllers. Fill in
653 the dcs[] with results.
654 *******************************************************************/
656 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
657 struct dc_name_ip **dcs, int *num_dcs)
659 fstring dcname;
660 struct in_addr ip;
661 struct ip_service *ip_list = NULL;
662 int iplist_size = 0;
663 int i;
664 BOOL is_our_domain;
667 is_our_domain = strequal(domain->name, lp_workgroup());
669 if ( !is_our_domain
670 && get_dc_name_via_netlogon(domain, dcname, &ip)
671 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
673 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
674 dcname, inet_ntoa(ip)));
675 return True;
678 if ( is_our_domain
679 && must_use_pdc(domain->name)
680 && get_pdc_ip(domain->name, &ip))
682 if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs))
683 return True;
686 /* try standard netbios queries first */
688 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
690 /* check for security = ads and use DNS if we can */
692 if ( iplist_size==0 && lp_security() == SEC_ADS )
693 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
695 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
697 /* now add to the dc array. We'll wait until the last minute
698 to look up the name of the DC. But we fill in the char* for
699 the ip now in to make the failed connection cache work */
701 for ( i=0; i<iplist_size; i++ ) {
702 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
703 ip_list[i].ip, dcs, num_dcs);
706 SAFE_FREE( ip_list );
708 return True;
711 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
712 const struct winbindd_domain *domain,
713 fstring dcname, struct sockaddr_in *addr, int *fd)
715 struct dc_name_ip *dcs = NULL;
716 int num_dcs = 0;
718 const char **dcnames = NULL;
719 int num_dcnames = 0;
721 struct sockaddr_in *addrs = NULL;
722 int num_addrs = 0;
724 int i, fd_index;
726 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
727 return False;
729 for (i=0; i<num_dcs; i++) {
731 add_string_to_array(mem_ctx, dcs[i].name,
732 &dcnames, &num_dcnames);
733 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
734 &addrs, &num_addrs);
736 add_string_to_array(mem_ctx, dcs[i].name,
737 &dcnames, &num_dcnames);
738 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
739 &addrs, &num_addrs);
742 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
743 return False;
745 if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) )
747 for (i=0; i<num_dcs; i++) {
748 add_failed_connection_entry(domain->name,
749 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
751 return False;
754 *addr = addrs[fd_index];
756 /* if we have no name on the server or just an IP address for
757 the name, now try to get the name */
759 if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
760 dcip_to_name( domain->name, domain->alt_name, &domain->sid, addr->sin_addr, dcname );
761 else
762 fstrcpy(dcname, dcnames[fd_index]);
764 return True;
767 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
768 struct winbindd_cm_conn *new_conn)
770 TALLOC_CTX *mem_ctx;
771 NTSTATUS result;
773 int retries;
775 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
776 return NT_STATUS_NO_MEMORY;
778 for (retries = 0; retries < 3; retries++) {
780 int fd = -1;
781 BOOL retry = False;
783 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
785 if ((strlen(domain->dcname) > 0) &&
786 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
787 domain->dcname))) {
788 int dummy;
789 if (!open_any_socket_out(&domain->dcaddr, 1, 10000,
790 &dummy, &fd)) {
791 fd = -1;
795 if ((fd == -1) &&
796 !find_new_dc(mem_ctx, domain, domain->dcname,
797 &domain->dcaddr, &fd))
798 break;
800 new_conn->cli = NULL;
802 result = cm_prepare_connection(domain, fd, domain->dcname,
803 &new_conn->cli, &retry);
805 if (!retry)
806 break;
809 talloc_destroy(mem_ctx);
810 return result;
813 /* Return true if a connection is still alive */
815 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
817 if (conn->samr_pipe != NULL) {
818 cli_rpc_pipe_close(conn->samr_pipe);
819 conn->samr_pipe = NULL;
822 if (conn->lsa_pipe != NULL) {
823 cli_rpc_pipe_close(conn->lsa_pipe);
824 conn->lsa_pipe = NULL;
827 if (conn->netlogon_pipe != NULL) {
828 cli_rpc_pipe_close(conn->netlogon_pipe);
829 conn->netlogon_pipe = NULL;
832 if (conn->cli) {
833 cli_shutdown(conn->cli);
836 conn->cli = NULL;
839 void close_conns_after_fork(void)
841 struct winbindd_domain *domain;
843 for (domain = domain_list(); domain; domain = domain->next) {
844 if (domain->conn.cli == NULL)
845 continue;
847 if (domain->conn.cli->fd == -1)
848 continue;
850 close(domain->conn.cli->fd);
851 domain->conn.cli->fd = -1;
855 static BOOL connection_ok(struct winbindd_domain *domain)
857 if (domain->conn.cli == NULL) {
858 DEBUG(8, ("Connection to %s for domain %s has NULL "
859 "cli!\n", domain->dcname, domain->name));
860 return False;
863 if (!domain->conn.cli->initialised) {
864 DEBUG(3, ("Connection to %s for domain %s was never "
865 "initialised!\n", domain->dcname, domain->name));
866 return False;
869 if (domain->conn.cli->fd == -1) {
870 DEBUG(3, ("Connection to %s for domain %s has died or was "
871 "never started (fd == -1)\n",
872 domain->dcname, domain->name));
873 return False;
876 return True;
879 /* Initialize a new connection up to the RPC BIND. */
881 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
883 if (connection_ok(domain))
884 return NT_STATUS_OK;
886 invalidate_cm_connection(&domain->conn);
888 return cm_open_connection(domain, &domain->conn);
891 /**********************************************************************************
892 We can 'sense' certain things about the DC by it's replies to certain questions.
894 This tells us if this particular remote server is Active Directory, and if it is
895 native mode.
896 **********************************************************************************/
898 void set_dc_type_and_flags( struct winbindd_domain *domain )
900 NTSTATUS result;
901 DS_DOMINFO_CTR ctr;
902 TALLOC_CTX *mem_ctx = NULL;
903 struct rpc_pipe_client *cli;
904 POLICY_HND pol;
906 char *domain_name = NULL;
907 char *dns_name = NULL;
908 DOM_SID *dom_sid = NULL;
910 ZERO_STRUCT( ctr );
912 domain->native_mode = False;
913 domain->active_directory = False;
915 if (domain->internal) {
916 domain->initialized = True;
917 return;
920 result = init_dc_connection(domain);
921 if (!NT_STATUS_IS_OK(result)) {
922 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
923 "to %s: (%s)\n", domain->name, nt_errstr(result)));
924 domain->initialized = True;
925 return;
928 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS, &result);
930 if (cli == NULL) {
931 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
932 "PI_LSARPC_DS on domain %s: (%s)\n",
933 domain->name, nt_errstr(result)));
934 domain->initialized = True;
935 return;
938 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
939 DsRolePrimaryDomainInfoBasic,
940 &ctr);
941 cli_rpc_pipe_close(cli);
943 if (!NT_STATUS_IS_OK(result)) {
944 domain->initialized = True;
945 return;
948 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
949 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
950 domain->native_mode = True;
952 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
954 if (cli == NULL) {
955 domain->initialized = True;
956 return;
959 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
960 domain->name);
961 if (!mem_ctx) {
962 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
963 cli_rpc_pipe_close(cli);
964 return;
967 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
968 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
970 if (NT_STATUS_IS_OK(result)) {
971 /* This particular query is exactly what Win2k clients use
972 to determine that the DC is active directory */
973 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
974 12, &domain_name,
975 &dns_name, NULL,
976 NULL, &dom_sid);
979 if (NT_STATUS_IS_OK(result)) {
980 if (domain_name)
981 fstrcpy(domain->name, domain_name);
983 if (dns_name)
984 fstrcpy(domain->alt_name, dns_name);
986 if (dom_sid)
987 sid_copy(&domain->sid, dom_sid);
989 domain->active_directory = True;
990 } else {
992 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
993 SEC_RIGHTS_MAXIMUM_ALLOWED,
994 &pol);
996 if (!NT_STATUS_IS_OK(result))
997 goto done;
999 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1000 &pol, 5, &domain_name,
1001 &dom_sid);
1003 if (NT_STATUS_IS_OK(result)) {
1004 if (domain_name)
1005 fstrcpy(domain->name, domain_name);
1007 if (dom_sid)
1008 sid_copy(&domain->sid, dom_sid);
1011 done:
1013 cli_rpc_pipe_close(cli);
1015 talloc_destroy(mem_ctx);
1017 domain->initialized = True;
1019 return;
1022 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
1023 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain, struct dcinfo **ppdc)
1025 NTSTATUS result;
1026 struct rpc_pipe_client *netlogon_pipe;
1028 if (lp_client_schannel() == False) {
1029 return False;
1032 result = cm_connect_netlogon(domain, &netlogon_pipe);
1033 if (!NT_STATUS_IS_OK(result)) {
1034 return False;
1037 /* Return a pointer to the struct dcinfo from the
1038 netlogon pipe. */
1040 *ppdc = domain->conn.netlogon_pipe->dc;
1041 return True;
1043 #endif
1045 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1046 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1048 struct winbindd_cm_conn *conn;
1049 NTSTATUS result;
1051 result = init_dc_connection(domain);
1052 if (!NT_STATUS_IS_OK(result)) {
1053 return result;
1056 conn = &domain->conn;
1058 if (conn->samr_pipe == NULL) {
1060 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO
1061 * authenticated sign and sealed pipe using the machine
1062 * account password by preference. If we can't - try schannel,
1063 * if that fails, try anonymous.
1066 fstring conn_pwd;
1067 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1068 if (conn->cli->user_name[0] && conn->cli->domain[0] &&
1069 conn_pwd[0]) {
1070 /* We have an authenticated connection. Use
1071 a NTLMSSP SPNEGO authenticated SAMR pipe with
1072 sign & seal. */
1073 conn->samr_pipe =
1074 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
1075 PI_SAMR,
1076 PIPE_AUTH_LEVEL_PRIVACY,
1077 conn->cli->domain,
1078 conn->cli->user_name,
1079 conn_pwd,
1080 &result);
1081 if (conn->samr_pipe == NULL) {
1082 DEBUG(10,("cm_connect_sam: failed to connect "
1083 "to SAMR pipe for domain %s using "
1084 "NTLMSSP authenticated pipe: user "
1085 "%s\\%s. Error was %s\n",
1086 domain->name, conn->cli->domain,
1087 conn->cli->user_name,
1088 nt_errstr(result)));
1089 } else {
1090 DEBUG(10,("cm_connect_sam: connected to SAMR "
1091 "pipe for domain %s using NTLMSSP "
1092 "authenticated pipe: user %s\\%s\n",
1093 domain->name, conn->cli->domain,
1094 conn->cli->user_name ));
1098 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
1099 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1100 if (conn->samr_pipe == NULL) {
1101 struct dcinfo *p_dcinfo;
1103 if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1104 conn->samr_pipe =
1105 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1106 PI_SAMR,
1107 PIPE_AUTH_LEVEL_PRIVACY,
1108 domain->name,
1109 p_dcinfo,
1110 &result);
1112 if (conn->samr_pipe == NULL) {
1113 DEBUG(10,("cm_connect_sam: failed to connect "
1114 "to SAMR pipe for domain %s using "
1115 "schannel authenticated. Error "
1116 "was %s\n", domain->name,
1117 nt_errstr(result) ));
1118 } else {
1119 DEBUG(10,("cm_connect_sam: connected to SAMR "
1120 "pipe for domain %s using schannel.\n",
1121 domain->name ));
1124 #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */
1126 /* Finally fall back to anonymous. */
1127 if (conn->samr_pipe == NULL) {
1128 conn->samr_pipe =
1129 cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR, &result);
1132 if (conn->samr_pipe == NULL) {
1133 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1134 goto done;
1137 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1138 SEC_RIGHTS_MAXIMUM_ALLOWED,
1139 &conn->sam_connect_handle);
1140 if (!NT_STATUS_IS_OK(result)) {
1141 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1142 "for domain %s Error was %s\n",
1143 domain->name, nt_errstr(result) ));
1144 goto done;
1147 result = rpccli_samr_open_domain(conn->samr_pipe,
1148 mem_ctx,
1149 &conn->sam_connect_handle,
1150 SEC_RIGHTS_MAXIMUM_ALLOWED,
1151 &domain->sid,
1152 &conn->sam_domain_handle);
1155 done:
1157 if (!NT_STATUS_IS_OK(result)) {
1158 invalidate_cm_connection(conn);
1159 return result;
1162 *cli = conn->samr_pipe;
1163 *sam_handle = conn->sam_domain_handle;
1164 return result;
1167 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1168 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1170 struct winbindd_cm_conn *conn;
1171 NTSTATUS result;
1173 result = init_dc_connection(domain);
1174 if (!NT_STATUS_IS_OK(result))
1175 return result;
1177 conn = &domain->conn;
1179 if (conn->lsa_pipe == NULL) {
1180 fstring conn_pwd;
1181 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1182 if (conn->cli->user_name[0] && conn->cli->domain[0] &&
1183 conn_pwd[0]) {
1184 /* We have an authenticated connection. Use
1185 a NTLMSSP SPNEGO authenticated LSA pipe with
1186 sign & seal. */
1187 conn->lsa_pipe =
1188 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
1189 PI_LSARPC,
1190 PIPE_AUTH_LEVEL_PRIVACY,
1191 conn->cli->domain,
1192 conn->cli->user_name,
1193 conn_pwd,
1194 &result);
1195 if (conn->lsa_pipe == NULL) {
1196 DEBUG(10,("cm_connect_lsa: failed to connect "
1197 "to LSA pipe for domain %s using "
1198 "NTLMSSP authenticated pipe: user "
1199 "%s\\%s. Error was %s\n",
1200 domain->name, conn->cli->domain,
1201 conn->cli->user_name,
1202 nt_errstr(result)));
1203 } else {
1204 DEBUG(10,("cm_connect_lsa: connected to LSA "
1205 "pipe for domain %s using NTLMSSP "
1206 "authenticated pipe: user %s\\%s\n",
1207 domain->name, conn->cli->domain,
1208 conn->cli->user_name ));
1212 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
1213 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1214 if (conn->lsa_pipe == NULL) {
1215 struct dcinfo *p_dcinfo;
1217 if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1218 conn->lsa_pipe =
1219 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1220 PI_LSARPC,
1221 PIPE_AUTH_LEVEL_PRIVACY,
1222 domain->name,
1223 p_dcinfo,
1224 &result);
1226 if (conn->lsa_pipe == NULL) {
1227 DEBUG(10,("cm_connect_lsa: failed to connect "
1228 "to LSA pipe for domain %s using "
1229 "schannel authenticated. Error "
1230 "was %s\n", domain->name,
1231 nt_errstr(result) ));
1232 } else {
1233 DEBUG(10,("cm_connect_lsa: connected to LSA "
1234 "pipe for domain %s using schannel.\n",
1235 domain->name ));
1238 #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */
1240 /* Finally fall back to anonymous. */
1241 if (conn->lsa_pipe == NULL) {
1242 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli,
1243 PI_LSARPC,
1244 &result);
1247 if (conn->lsa_pipe == NULL) {
1248 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1249 goto done;
1252 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1253 SEC_RIGHTS_MAXIMUM_ALLOWED,
1254 &conn->lsa_policy);
1257 done:
1258 if (!NT_STATUS_IS_OK(result)) {
1259 invalidate_cm_connection(conn);
1260 return NT_STATUS_UNSUCCESSFUL;
1263 *cli = conn->lsa_pipe;
1264 *lsa_policy = conn->lsa_policy;
1265 return result;
1268 /****************************************************************************
1269 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1270 session key stored in conn->netlogon_pipe->dc->sess_key.
1271 ****************************************************************************/
1273 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct rpc_pipe_client **cli)
1275 struct winbindd_cm_conn *conn;
1276 NTSTATUS result;
1278 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1279 uint8 mach_pwd[16];
1280 uint32 sec_chan_type;
1281 const char *account_name;
1282 struct rpc_pipe_client *netlogon_pipe;
1284 result = init_dc_connection(domain);
1285 if (!NT_STATUS_IS_OK(result)) {
1286 return result;
1289 conn = &domain->conn;
1291 if (conn->netlogon_pipe != NULL) {
1292 *cli = conn->netlogon_pipe;
1293 return NT_STATUS_OK;
1296 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1297 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1300 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, &result);
1301 if (netlogon_pipe == NULL) {
1302 return result;
1305 if (lp_client_schannel() != False) {
1306 neg_flags |= NETLOGON_NEG_SCHANNEL;
1309 /* if we are a DC and this is a trusted domain, then we need to use our
1310 domain name in the net_req_auth2() request */
1312 if ( IS_DC
1313 && !strequal(domain->name, lp_workgroup())
1314 && lp_allow_trusted_domains() )
1316 account_name = lp_workgroup();
1317 } else {
1318 account_name = domain->primary ? global_myname() : domain->name;
1321 if (account_name == NULL) {
1322 cli_rpc_pipe_close(netlogon_pipe);
1323 return NT_STATUS_NO_MEMORY;
1326 result = rpccli_netlogon_setup_creds(netlogon_pipe,
1327 domain->dcname, /* server name. */
1328 domain->name, /* domain name */
1329 account_name, /* machine account */
1330 mach_pwd, /* machine password */
1331 sec_chan_type, /* from get_trust_pw */
1332 &neg_flags);
1334 if (!NT_STATUS_IS_OK(result)) {
1335 cli_rpc_pipe_close(netlogon_pipe);
1336 return result;
1339 if ((lp_client_schannel() == True) &&
1340 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1341 DEBUG(3, ("Server did not offer schannel\n"));
1342 cli_rpc_pipe_close(netlogon_pipe);
1343 return NT_STATUS_ACCESS_DENIED;
1346 if ((lp_client_schannel() == False) ||
1347 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1348 /* We're done - just keep the existing connection to NETLOGON open */
1349 conn->netlogon_pipe = netlogon_pipe;
1350 *cli = conn->netlogon_pipe;
1351 return NT_STATUS_OK;
1354 /* Using the credentials from the first pipe, open a signed and sealed
1355 second netlogon pipe. The session key is stored in the schannel
1356 part of the new pipe auth struct.
1359 conn->netlogon_pipe = cli_rpc_pipe_open_schannel_with_key(conn->cli,
1360 PI_NETLOGON,
1361 PIPE_AUTH_LEVEL_PRIVACY,
1362 domain->name,
1363 netlogon_pipe->dc,
1364 &result);
1366 /* We can now close the initial netlogon pipe. */
1367 cli_rpc_pipe_close(netlogon_pipe);
1369 if (conn->netlogon_pipe == NULL) {
1370 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error was %s\n",
1371 nt_errstr(result)));
1372 return result;
1375 *cli = conn->netlogon_pipe;
1376 return NT_STATUS_OK;