r11328: Actually verify that the bind on a pipe succeeded with a samr_connect or
[Samba.git] / source / nsswitch / winbindd_cm.c
blob4e11206c9ca3f3673b3e0af98a0f2900682db8c1
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;
105 struct rpc_pipe_client *netlogon_pipe;
106 NTSTATUS result;
107 TALLOC_CTX *mem_ctx;
108 const char *server_name;
110 fstring tmp;
111 char *p;
113 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
114 * moment.... */
116 if (IS_DC) {
117 return False;
120 if (domain->primary) {
121 return False;
124 our_domain = find_our_domain();
126 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
127 return False;
130 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
131 if (!NT_STATUS_IS_OK(result)) {
132 return False;
135 server_name = talloc_asprintf(mem_ctx, "\\\\%s", our_domain->dcname);
136 if (server_name == NULL) {
137 return False;
140 result = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, server_name,
141 domain->name, tmp);
143 talloc_destroy(mem_ctx);
145 if (!NT_STATUS_IS_OK(result)) {
146 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
147 nt_errstr(result)));
148 return False;
151 /* cli_netlogon_getdcname gives us a name with \\ */
152 p = tmp;
153 if (*p == '\\') {
154 p+=1;
156 if (*p == '\\') {
157 p+=1;
160 fstrcpy(dcname, p);
162 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
164 if (!resolve_name(dcname, dc_ip, 0x20)) {
165 return False;
168 return True;
171 /************************************************************************
172 Given a fd with a just-connected TCP connection to a DC, open a connection
173 to the pipe.
174 ************************************************************************/
176 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
177 const int sockfd,
178 const char *controller,
179 struct cli_state **cli,
180 BOOL *retry)
182 char *machine_password, *machine_krb5_principal, *machine_account;
183 char *ipc_username, *ipc_domain, *ipc_password;
185 BOOL got_mutex;
186 BOOL add_failed_connection = True;
188 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
190 struct sockaddr peeraddr;
191 socklen_t peeraddr_len;
193 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
195 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
196 NULL);
198 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
199 SAFE_FREE(machine_password);
200 return NT_STATUS_NO_MEMORY;
203 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
204 lp_realm()) == -1) {
205 SAFE_FREE(machine_account);
206 SAFE_FREE(machine_password);
207 return NT_STATUS_NO_MEMORY;
210 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
212 *retry = True;
214 got_mutex = secrets_named_mutex(controller,
215 WINBIND_SERVER_MUTEX_WAIT_TIME);
217 if (!got_mutex) {
218 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n",
219 controller));
220 result = NT_STATUS_POSSIBLE_DEADLOCK;
221 goto done;
224 if ((*cli = cli_initialise(NULL)) == NULL) {
225 DEBUG(1, ("Could not cli_initialize\n"));
226 result = NT_STATUS_NO_MEMORY;
227 goto done;
230 (*cli)->timeout = 10000; /* 10 seconds */
231 (*cli)->fd = sockfd;
232 fstrcpy((*cli)->desthost, controller);
233 (*cli)->use_kerberos = True;
235 peeraddr_len = sizeof(peeraddr);
237 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
238 (peeraddr_len != sizeof(struct sockaddr_in)) ||
239 (peeraddr_in->sin_family != PF_INET))
241 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
242 goto done;
245 if (ntohs(peeraddr_in->sin_port) == 139) {
246 struct nmb_name calling;
247 struct nmb_name called;
249 make_nmb_name(&calling, global_myname(), 0x0);
250 make_nmb_name(&called, "*SMBSERVER", 0x20);
252 if (!cli_session_request(*cli, &calling, &called)) {
253 DEBUG(8, ("cli_session_request failed for %s\n",
254 controller));
255 goto done;
259 cli_setup_signing_state(*cli, Undefined);
261 if (!cli_negprot(*cli)) {
262 DEBUG(1, ("cli_negprot failed\n"));
263 cli_shutdown(*cli);
264 goto done;
268 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
269 ADS_STATUS ads_status;
271 if (lp_security() == SEC_ADS) {
273 /* Try a krb5 session */
275 (*cli)->use_kerberos = True;
276 DEBUG(5, ("connecting to %s from %s with kerberos principal "
277 "[%s]\n", controller, global_myname(),
278 machine_krb5_principal));
280 ads_status = cli_session_setup_spnego(*cli,
281 machine_krb5_principal,
282 machine_password,
283 lp_workgroup());
285 if (!ADS_ERR_OK(ads_status)) {
286 DEBUG(4,("failed kerberos session setup with %s\n",
287 ads_errstr(ads_status)));
290 result = ads_ntstatus(ads_status);
291 if (NT_STATUS_IS_OK(result)) {
292 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
293 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
294 goto session_setup_done;
298 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
299 (*cli)->use_kerberos = False;
301 DEBUG(5, ("connecting to %s from %s with username "
302 "[%s]\\[%s]\n", controller, global_myname(),
303 machine_account, machine_password));
305 ads_status = cli_session_setup_spnego(*cli,
306 machine_account,
307 machine_password,
308 lp_workgroup());
309 if (!ADS_ERR_OK(ads_status)) {
310 DEBUG(4, ("authenticated session setup failed with %s\n",
311 ads_errstr(ads_status)));
314 result = ads_ntstatus(ads_status);
315 if (NT_STATUS_IS_OK(result)) {
316 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
317 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
318 goto session_setup_done;
322 /* Fall back to non-kerberos session setup */
324 (*cli)->use_kerberos = False;
326 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
327 (strlen(ipc_username) > 0)) {
329 /* Only try authenticated if we have a username */
331 DEBUG(5, ("connecting to %s from %s with username "
332 "[%s]\\[%s]\n", controller, global_myname(),
333 ipc_domain, ipc_username));
335 if (cli_session_setup(*cli, ipc_username,
336 ipc_password, strlen(ipc_password)+1,
337 ipc_password, strlen(ipc_password)+1,
338 ipc_domain)) {
339 /* Successful logon with given username. */
340 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
341 goto session_setup_done;
342 } else {
343 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
344 ipc_domain, ipc_username ));
348 /* Fall back to anonymous connection, this might fail later */
350 if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
351 DEBUG(5, ("Connected anonymously\n"));
352 cli_init_creds(*cli, "", "", "");
353 goto session_setup_done;
356 result = cli_nt_error(*cli);
358 if (NT_STATUS_IS_OK(result))
359 result = NT_STATUS_UNSUCCESSFUL;
361 /* We can't session setup */
363 goto done;
365 session_setup_done:
367 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
369 result = cli_nt_error(*cli);
371 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
373 if (NT_STATUS_IS_OK(result))
374 result = NT_STATUS_UNSUCCESSFUL;
376 cli_shutdown(*cli);
377 goto done;
380 secrets_named_mutex_release(controller);
381 got_mutex = False;
382 *retry = False;
384 /* set the domain if empty; needed for schannel connections */
385 if ( !*(*cli)->domain ) {
386 fstrcpy( (*cli)->domain, domain->name );
389 result = NT_STATUS_OK;
390 add_failed_connection = False;
392 done:
393 if (got_mutex) {
394 secrets_named_mutex_release(controller);
397 SAFE_FREE(machine_account);
398 SAFE_FREE(machine_password);
399 SAFE_FREE(machine_krb5_principal);
400 SAFE_FREE(ipc_username);
401 SAFE_FREE(ipc_domain);
402 SAFE_FREE(ipc_password);
404 if (add_failed_connection) {
405 add_failed_connection_entry(domain->name, controller, result);
408 return result;
411 struct dc_name_ip {
412 fstring name;
413 struct in_addr ip;
416 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
417 const char *dcname, struct in_addr ip,
418 struct dc_name_ip **dcs, int *num)
420 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
421 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
422 return False;
425 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
427 if (*dcs == NULL)
428 return False;
430 fstrcpy((*dcs)[*num].name, dcname);
431 (*dcs)[*num].ip = ip;
432 *num += 1;
433 return True;
436 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
437 struct in_addr ip, uint16 port,
438 struct sockaddr_in **addrs, int *num)
440 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
442 if (*addrs == NULL)
443 return False;
445 (*addrs)[*num].sin_family = PF_INET;
446 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
447 (*addrs)[*num].sin_port = htons(port);
449 *num += 1;
450 return True;
453 static void mailslot_name(struct in_addr dc_ip, fstring name)
455 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
458 static BOOL send_getdc_request(struct in_addr dc_ip,
459 const char *domain_name,
460 const DOM_SID *sid)
462 pstring outbuf;
463 char *p;
464 fstring my_acct_name;
465 fstring my_mailslot;
467 mailslot_name(dc_ip, my_mailslot);
469 memset(outbuf, '\0', sizeof(outbuf));
471 p = outbuf;
473 SCVAL(p, 0, SAMLOGON);
474 p++;
476 SCVAL(p, 0, 0); /* Count pointer ... */
477 p++;
479 SIVAL(p, 0, 0); /* The sender's token ... */
480 p += 2;
482 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
483 fstr_sprintf(my_acct_name, "%s$", global_myname());
484 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
486 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
487 p += strlen(my_mailslot)+1;
489 SIVAL(p, 0, 0x80);
490 p+=4;
492 SIVAL(p, 0, sid_size(sid));
493 p+=4;
495 p = ALIGN4(p, outbuf);
497 sid_linearize(p, sid_size(sid), sid);
498 p += sid_size(sid);
500 SIVAL(p, 0, 1);
501 SSVAL(p, 4, 0xffff);
502 SSVAL(p, 6, 0xffff);
503 p+=8;
505 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
506 outbuf, PTR_DIFF(p, outbuf),
507 global_myname(), 0, domain_name, 0x1c,
508 dc_ip);
511 static BOOL receive_getdc_response(struct in_addr dc_ip,
512 const char *domain_name,
513 fstring dc_name)
515 struct packet_struct *packet;
516 fstring my_mailslot;
517 char *buf, *p;
518 fstring dcname, user, domain;
519 int len;
521 mailslot_name(dc_ip, my_mailslot);
523 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
525 if (packet == NULL) {
526 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
527 return False;
530 DEBUG(5, ("Received packet for %s\n", my_mailslot));
532 buf = packet->packet.dgram.data;
533 len = packet->packet.dgram.datasize;
535 if (len < 70) {
536 /* 70 is a completely arbitrary value to make sure
537 the SVAL below does not read uninitialized memory */
538 DEBUG(3, ("GetDC got short response\n"));
539 return False;
542 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
543 p = buf+SVAL(buf, smb_vwv10);
545 if (CVAL(p,0) != SAMLOGON_R) {
546 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
547 return False;
550 p+=2;
551 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
552 STR_TERMINATE|STR_NOALIGN);
553 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
554 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
555 STR_TERMINATE|STR_NOALIGN);
556 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
557 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
558 STR_TERMINATE|STR_NOALIGN);
559 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
561 if (!strequal(domain, domain_name)) {
562 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
563 domain_name, domain));
564 return False;
567 p = dcname;
568 if (*p == '\\') p += 1;
569 if (*p == '\\') p += 1;
571 fstrcpy(dc_name, p);
573 DEBUG(10, ("GetDC gave name %s for domain %s\n",
574 dc_name, domain));
576 return True;
579 /*******************************************************************
580 convert an ip to a name
581 *******************************************************************/
583 static void dcip_to_name( const char *domainname, const char *realm,
584 const DOM_SID *sid, struct in_addr ip, fstring name )
587 /* try GETDC requests first */
589 if (send_getdc_request(ip, domainname, sid)) {
590 int i;
591 smb_msleep(100);
592 for (i=0; i<5; i++) {
593 if (receive_getdc_response(ip, domainname, name))
594 return;
595 smb_msleep(500);
599 /* try node status request */
601 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
602 return;
604 /* backup in case the netbios stuff fails */
606 fstrcpy( name, inet_ntoa(ip) );
608 #ifdef WITH_ADS
609 /* for active directory servers, try to get the ldap server name.
610 None of these failure should be considered critical for now */
612 if ( lp_security() == SEC_ADS )
614 ADS_STRUCT *ads;
615 ADS_STATUS status;
617 ads = ads_init( realm, domainname, NULL );
618 ads->auth.flags |= ADS_AUTH_NO_BIND;
620 if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) ) {
621 ads_destroy( &ads );
622 return;
625 status = ads_server_info(ads);
626 if ( !ADS_ERR_OK(status) ) {
627 ads_destroy( &ads );
628 return;
631 fstrcpy(name, ads->config.ldap_server_name);
633 ads_destroy( &ads );
635 #endif
637 return;
640 /*******************************************************************
641 Retreive a list of IP address for domain controllers. Fill in
642 the dcs[] with results.
643 *******************************************************************/
645 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
646 struct dc_name_ip **dcs, int *num_dcs)
648 fstring dcname;
649 struct in_addr ip;
650 struct ip_service *ip_list = NULL;
651 int iplist_size = 0;
652 int i;
653 BOOL is_our_domain;
656 is_our_domain = strequal(domain->name, lp_workgroup());
658 if ( !is_our_domain
659 && get_dc_name_via_netlogon(domain, dcname, &ip)
660 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
662 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
663 dcname, inet_ntoa(ip)));
664 return True;
667 if ( is_our_domain
668 && must_use_pdc(domain->name)
669 && get_pdc_ip(domain->name, &ip))
671 if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs))
672 return True;
675 /* try standard netbios queries first */
677 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
679 /* check for security = ads and use DNS if we can */
681 if ( iplist_size==0 && lp_security() == SEC_ADS )
682 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
684 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
686 /* now add to the dc array. We'll wait until the last minute
687 to look up the name of the DC. But we fill in the char* for
688 the ip now in to make the failed connection cache work */
690 for ( i=0; i<iplist_size; i++ ) {
691 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
692 ip_list[i].ip, dcs, num_dcs);
695 SAFE_FREE( ip_list );
697 return True;
700 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
701 const struct winbindd_domain *domain,
702 fstring dcname, struct sockaddr_in *addr, int *fd)
704 struct dc_name_ip *dcs = NULL;
705 int num_dcs = 0;
707 const char **dcnames = NULL;
708 int num_dcnames = 0;
710 struct sockaddr_in *addrs = NULL;
711 int num_addrs = 0;
713 int i, fd_index;
715 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
716 return False;
718 for (i=0; i<num_dcs; i++) {
720 add_string_to_array(mem_ctx, dcs[i].name,
721 &dcnames, &num_dcnames);
722 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
723 &addrs, &num_addrs);
725 add_string_to_array(mem_ctx, dcs[i].name,
726 &dcnames, &num_dcnames);
727 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
728 &addrs, &num_addrs);
731 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
732 return False;
734 if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) )
736 for (i=0; i<num_dcs; i++) {
737 add_failed_connection_entry(domain->name,
738 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
740 return False;
743 *addr = addrs[fd_index];
745 /* if we have no name on the server or just an IP address for
746 the name, now try to get the name */
748 if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
749 dcip_to_name( domain->name, domain->alt_name, &domain->sid, addr->sin_addr, dcname );
750 else
751 fstrcpy(dcname, dcnames[fd_index]);
753 return True;
756 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
757 struct winbindd_cm_conn *new_conn)
759 TALLOC_CTX *mem_ctx;
760 NTSTATUS result;
762 int retries;
764 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
765 return NT_STATUS_NO_MEMORY;
767 for (retries = 0; retries < 3; retries++) {
769 int fd = -1;
770 BOOL retry = False;
772 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
774 if ((strlen(domain->dcname) > 0) &&
775 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
776 domain->dcname))) {
777 int dummy;
778 if (!open_any_socket_out(&domain->dcaddr, 1, 10000,
779 &dummy, &fd)) {
780 fd = -1;
784 if ((fd == -1) &&
785 !find_new_dc(mem_ctx, domain, domain->dcname,
786 &domain->dcaddr, &fd))
787 break;
789 new_conn->cli = NULL;
791 result = cm_prepare_connection(domain, fd, domain->dcname,
792 &new_conn->cli, &retry);
794 if (!retry)
795 break;
798 talloc_destroy(mem_ctx);
799 return result;
802 /* Return true if a connection is still alive */
804 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
806 if (conn->samr_pipe != NULL) {
807 cli_rpc_pipe_close(conn->samr_pipe);
808 conn->samr_pipe = NULL;
811 if (conn->lsa_pipe != NULL) {
812 cli_rpc_pipe_close(conn->lsa_pipe);
813 conn->lsa_pipe = NULL;
816 if (conn->netlogon_pipe != NULL) {
817 cli_rpc_pipe_close(conn->netlogon_pipe);
818 conn->netlogon_pipe = NULL;
821 if (conn->cli) {
822 cli_shutdown(conn->cli);
825 conn->cli = NULL;
828 void close_conns_after_fork(void)
830 struct winbindd_domain *domain;
832 for (domain = domain_list(); domain; domain = domain->next) {
833 if (domain->conn.cli == NULL)
834 continue;
836 if (domain->conn.cli->fd == -1)
837 continue;
839 close(domain->conn.cli->fd);
840 domain->conn.cli->fd = -1;
844 static BOOL connection_ok(struct winbindd_domain *domain)
846 if (domain->conn.cli == NULL) {
847 DEBUG(8, ("Connection to %s for domain %s has NULL "
848 "cli!\n", domain->dcname, domain->name));
849 return False;
852 if (!domain->conn.cli->initialised) {
853 DEBUG(3, ("Connection to %s for domain %s was never "
854 "initialised!\n", domain->dcname, domain->name));
855 return False;
858 if (domain->conn.cli->fd == -1) {
859 DEBUG(3, ("Connection to %s for domain %s has died or was "
860 "never started (fd == -1)\n",
861 domain->dcname, domain->name));
862 return False;
865 return True;
868 /* Initialize a new connection up to the RPC BIND. */
870 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
872 if (connection_ok(domain))
873 return NT_STATUS_OK;
875 invalidate_cm_connection(&domain->conn);
877 return cm_open_connection(domain, &domain->conn);
880 /******************************************************************************
881 We can 'sense' certain things about the DC by it's replies to certain
882 questions.
884 This tells us if this particular remote server is Active Directory, and if it
885 is native mode.
886 ******************************************************************************/
888 void set_dc_type_and_flags( struct winbindd_domain *domain )
890 NTSTATUS result;
891 DS_DOMINFO_CTR ctr;
892 TALLOC_CTX *mem_ctx = NULL;
893 struct rpc_pipe_client *cli;
894 POLICY_HND pol;
896 char *domain_name = NULL;
897 char *dns_name = NULL;
898 DOM_SID *dom_sid = NULL;
900 ZERO_STRUCT( ctr );
902 domain->native_mode = False;
903 domain->active_directory = False;
905 if (domain->internal) {
906 domain->initialized = True;
907 return;
910 result = init_dc_connection(domain);
911 if (!NT_STATUS_IS_OK(result)) {
912 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
913 "to %s: (%s)\n", domain->name, nt_errstr(result)));
914 domain->initialized = True;
915 return;
918 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
919 &result);
921 if (cli == NULL) {
922 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
923 "PI_LSARPC_DS on domain %s: (%s)\n",
924 domain->name, nt_errstr(result)));
925 domain->initialized = True;
926 return;
929 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
930 DsRolePrimaryDomainInfoBasic,
931 &ctr);
932 cli_rpc_pipe_close(cli);
934 if (!NT_STATUS_IS_OK(result)) {
935 domain->initialized = True;
936 return;
939 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
940 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
941 domain->native_mode = True;
943 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
945 if (cli == NULL) {
946 domain->initialized = True;
947 return;
950 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
951 domain->name);
952 if (!mem_ctx) {
953 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
954 cli_rpc_pipe_close(cli);
955 return;
958 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
959 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
961 if (NT_STATUS_IS_OK(result)) {
962 /* This particular query is exactly what Win2k clients use
963 to determine that the DC is active directory */
964 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
965 12, &domain_name,
966 &dns_name, NULL,
967 NULL, &dom_sid);
970 if (NT_STATUS_IS_OK(result)) {
971 if (domain_name)
972 fstrcpy(domain->name, domain_name);
974 if (dns_name)
975 fstrcpy(domain->alt_name, dns_name);
977 if (dom_sid)
978 sid_copy(&domain->sid, dom_sid);
980 domain->active_directory = True;
981 } else {
983 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
984 SEC_RIGHTS_MAXIMUM_ALLOWED,
985 &pol);
987 if (!NT_STATUS_IS_OK(result))
988 goto done;
990 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
991 &pol, 5, &domain_name,
992 &dom_sid);
994 if (NT_STATUS_IS_OK(result)) {
995 if (domain_name)
996 fstrcpy(domain->name, domain_name);
998 if (dom_sid)
999 sid_copy(&domain->sid, dom_sid);
1002 done:
1004 cli_rpc_pipe_close(cli);
1006 talloc_destroy(mem_ctx);
1008 domain->initialized = True;
1010 return;
1013 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1014 struct dcinfo **ppdc)
1016 NTSTATUS result;
1017 struct rpc_pipe_client *netlogon_pipe;
1019 if (lp_client_schannel() == False) {
1020 return False;
1023 result = cm_connect_netlogon(domain, &netlogon_pipe);
1024 if (!NT_STATUS_IS_OK(result)) {
1025 return False;
1028 /* Return a pointer to the struct dcinfo from the
1029 netlogon pipe. */
1031 *ppdc = domain->conn.netlogon_pipe->dc;
1032 return True;
1035 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1036 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1038 struct winbindd_cm_conn *conn;
1039 NTSTATUS result;
1040 fstring conn_pwd;
1041 struct dcinfo *p_dcinfo;
1043 result = init_dc_connection(domain);
1044 if (!NT_STATUS_IS_OK(result)) {
1045 return result;
1048 conn = &domain->conn;
1050 if (conn->samr_pipe != NULL) {
1051 goto done;
1055 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1056 * sign and sealed pipe using the machine account password by
1057 * preference. If we can't - try schannel, if that fails, try
1058 * anonymous.
1061 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1062 if ((conn->cli->user_name[0] == '\0') ||
1063 (conn->cli->domain[0] == '\0') ||
1064 (conn_pwd[0] == '\0')) {
1065 DEBUG(10, ("cm_connect_sam: No no user available for "
1066 "domain %s, trying schannel\n", conn->cli->domain));
1067 goto schannel;
1070 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1071 authenticated SAMR pipe with sign & seal. */
1072 conn->samr_pipe =
1073 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1074 PIPE_AUTH_LEVEL_PRIVACY,
1075 conn->cli->domain,
1076 conn->cli->user_name,
1077 conn_pwd, &result);
1079 if (conn->samr_pipe == NULL) {
1080 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1081 "pipe for domain %s using NTLMSSP "
1082 "authenticated pipe: user %s\\%s. Error was "
1083 "%s\n", domain->name, conn->cli->domain,
1084 conn->cli->user_name, nt_errstr(result)));
1085 goto schannel;
1088 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1089 "domain %s using NTLMSSP authenticated "
1090 "pipe: user %s\\%s\n", domain->name,
1091 conn->cli->domain, conn->cli->user_name ));
1093 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1094 SEC_RIGHTS_MAXIMUM_ALLOWED,
1095 &conn->sam_connect_handle);
1096 if (NT_STATUS_IS_OK(result)) {
1097 goto open_domain;
1099 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1100 "failed for domain %s, error was %s. Trying schannel\n",
1101 domain->name, nt_errstr(result) ));
1102 cli_rpc_pipe_close(conn->samr_pipe);
1104 schannel:
1106 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1108 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1109 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1110 "for domain %s, trying anon\n", conn->cli->domain));
1111 goto anonymous;
1113 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1114 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1115 domain->name, p_dcinfo, &result);
1117 if (conn->samr_pipe == NULL) {
1118 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1119 "domain %s using schannel. Error was %s\n",
1120 domain->name, nt_errstr(result) ));
1121 goto anonymous;
1123 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1124 "schannel.\n", domain->name ));
1126 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1127 SEC_RIGHTS_MAXIMUM_ALLOWED,
1128 &conn->sam_connect_handle);
1129 if (NT_STATUS_IS_OK(result)) {
1130 goto open_domain;
1132 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1133 "for domain %s, error was %s. Trying anonymous\n",
1134 domain->name, nt_errstr(result) ));
1135 cli_rpc_pipe_close(conn->samr_pipe);
1137 anonymous:
1139 /* Finally fall back to anonymous. */
1140 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1141 &result);
1143 if (conn->samr_pipe == NULL) {
1144 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1145 goto done;
1148 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1149 SEC_RIGHTS_MAXIMUM_ALLOWED,
1150 &conn->sam_connect_handle);
1151 if (!NT_STATUS_IS_OK(result)) {
1152 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1153 "for domain %s Error was %s\n",
1154 domain->name, nt_errstr(result) ));
1155 goto done;
1158 open_domain:
1159 result = rpccli_samr_open_domain(conn->samr_pipe,
1160 mem_ctx,
1161 &conn->sam_connect_handle,
1162 SEC_RIGHTS_MAXIMUM_ALLOWED,
1163 &domain->sid,
1164 &conn->sam_domain_handle);
1166 done:
1168 if (!NT_STATUS_IS_OK(result)) {
1169 invalidate_cm_connection(conn);
1170 return result;
1173 *cli = conn->samr_pipe;
1174 *sam_handle = conn->sam_domain_handle;
1175 return result;
1178 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1179 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1181 struct winbindd_cm_conn *conn;
1182 NTSTATUS result;
1183 fstring conn_pwd;
1184 struct dcinfo *p_dcinfo;
1186 result = init_dc_connection(domain);
1187 if (!NT_STATUS_IS_OK(result))
1188 return result;
1190 conn = &domain->conn;
1192 if (conn->lsa_pipe != NULL) {
1193 goto done;
1196 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1197 if ((conn->cli->user_name[0] == '\0') ||
1198 (conn->cli->domain[0] == '\0') ||
1199 (conn_pwd[0] == '\0')) {
1200 DEBUG(10, ("cm_connect_lsa: No no user available for "
1201 "domain %s, trying schannel\n", conn->cli->domain));
1202 goto schannel;
1205 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1206 * authenticated LSA pipe with sign & seal. */
1207 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1208 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1209 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1211 if (conn->lsa_pipe == NULL) {
1212 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1213 "domain %s using NTLMSSP authenticated pipe: user "
1214 "%s\\%s. Error was %s. Trying schannel.\n",
1215 domain->name, conn->cli->domain,
1216 conn->cli->user_name, nt_errstr(result)));
1217 goto schannel;
1220 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1221 "NTLMSSP authenticated pipe: user %s\\%s\n",
1222 domain->name, conn->cli->domain, conn->cli->user_name ));
1224 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1225 SEC_RIGHTS_MAXIMUM_ALLOWED,
1226 &conn->lsa_policy);
1227 if (NT_STATUS_IS_OK(result)) {
1228 goto done;
1231 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1232 "schannel\n"));
1234 cli_rpc_pipe_close(conn->lsa_pipe);
1236 schannel:
1238 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1240 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1241 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1242 "for domain %s, trying anon\n", conn->cli->domain));
1243 goto anonymous;
1245 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1246 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1247 domain->name, p_dcinfo, &result);
1249 if (conn->lsa_pipe == NULL) {
1250 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1251 "domain %s using schannel. Error was %s\n",
1252 domain->name, nt_errstr(result) ));
1253 goto anonymous;
1255 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1256 "schannel.\n", domain->name ));
1258 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1259 SEC_RIGHTS_MAXIMUM_ALLOWED,
1260 &conn->lsa_policy);
1261 if (NT_STATUS_IS_OK(result)) {
1262 goto done;
1265 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1266 "anonymous\n"));
1268 cli_rpc_pipe_close(conn->lsa_pipe);
1270 anonymous:
1272 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1273 &result);
1274 if (conn->lsa_pipe == NULL) {
1275 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1276 goto done;
1279 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1280 SEC_RIGHTS_MAXIMUM_ALLOWED,
1281 &conn->lsa_policy);
1282 done:
1283 if (!NT_STATUS_IS_OK(result)) {
1284 invalidate_cm_connection(conn);
1285 return NT_STATUS_UNSUCCESSFUL;
1288 *cli = conn->lsa_pipe;
1289 *lsa_policy = conn->lsa_policy;
1290 return result;
1293 /****************************************************************************
1294 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1295 session key stored in conn->netlogon_pipe->dc->sess_key.
1296 ****************************************************************************/
1298 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1299 struct rpc_pipe_client **cli)
1301 struct winbindd_cm_conn *conn;
1302 NTSTATUS result;
1304 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1305 uint8 mach_pwd[16];
1306 uint32 sec_chan_type;
1307 const char *account_name;
1308 struct rpc_pipe_client *netlogon_pipe;
1310 result = init_dc_connection(domain);
1311 if (!NT_STATUS_IS_OK(result)) {
1312 return result;
1315 conn = &domain->conn;
1317 if (conn->netlogon_pipe != NULL) {
1318 *cli = conn->netlogon_pipe;
1319 return NT_STATUS_OK;
1322 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1323 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1326 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1327 &result);
1328 if (netlogon_pipe == NULL) {
1329 return result;
1332 if (lp_client_schannel() != False) {
1333 neg_flags |= NETLOGON_NEG_SCHANNEL;
1336 /* if we are a DC and this is a trusted domain, then we need to use our
1337 domain name in the net_req_auth2() request */
1339 if ( IS_DC
1340 && !strequal(domain->name, lp_workgroup())
1341 && lp_allow_trusted_domains() )
1343 account_name = lp_workgroup();
1344 } else {
1345 account_name = domain->primary ?
1346 global_myname() : domain->name;
1349 if (account_name == NULL) {
1350 cli_rpc_pipe_close(netlogon_pipe);
1351 return NT_STATUS_NO_MEMORY;
1354 result = rpccli_netlogon_setup_creds
1355 (netlogon_pipe,
1356 domain->dcname, /* server name. */
1357 domain->name, /* domain name */
1358 account_name, /* machine account */
1359 mach_pwd, /* machine password */
1360 sec_chan_type, /* from get_trust_pw */
1361 &neg_flags);
1363 if (!NT_STATUS_IS_OK(result)) {
1364 cli_rpc_pipe_close(netlogon_pipe);
1365 return result;
1368 if ((lp_client_schannel() == True) &&
1369 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1370 DEBUG(3, ("Server did not offer schannel\n"));
1371 cli_rpc_pipe_close(netlogon_pipe);
1372 return NT_STATUS_ACCESS_DENIED;
1375 if ((lp_client_schannel() == False) ||
1376 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1377 /* We're done - just keep the existing connection to NETLOGON
1378 * open */
1379 conn->netlogon_pipe = netlogon_pipe;
1380 *cli = conn->netlogon_pipe;
1381 return NT_STATUS_OK;
1384 /* Using the credentials from the first pipe, open a signed and sealed
1385 second netlogon pipe. The session key is stored in the schannel
1386 part of the new pipe auth struct.
1389 conn->netlogon_pipe =
1390 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1391 PI_NETLOGON,
1392 PIPE_AUTH_LEVEL_PRIVACY,
1393 domain->name,
1394 netlogon_pipe->dc,
1395 &result);
1397 /* We can now close the initial netlogon pipe. */
1398 cli_rpc_pipe_close(netlogon_pipe);
1400 if (conn->netlogon_pipe == NULL) {
1401 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1402 "was %s\n", nt_errstr(result)));
1403 return result;
1406 *cli = conn->netlogon_pipe;
1407 return NT_STATUS_OK;