Samba 3: added Samba 3.0.24 sources
[tomato.git] / release / src / router / samba3 / source / nsswitch / winbindd_cm.c
blob98e799851fcbd112182197b4528276c87c9fe528
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 WERROR werr;
108 TALLOC_CTX *mem_ctx;
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 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
136 domain->name, tmp);
138 talloc_destroy(mem_ctx);
140 if (!W_ERROR_IS_OK(werr)) {
141 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
142 dos_errstr(werr)));
143 return False;
146 /* cli_netlogon_getdcname gives us a name with \\ */
147 p = tmp;
148 if (*p == '\\') {
149 p+=1;
151 if (*p == '\\') {
152 p+=1;
155 fstrcpy(dcname, p);
157 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
159 if (!resolve_name(dcname, dc_ip, 0x20)) {
160 return False;
163 return True;
166 /************************************************************************
167 Given a fd with a just-connected TCP connection to a DC, open a connection
168 to the pipe.
169 ************************************************************************/
171 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
172 const int sockfd,
173 const char *controller,
174 struct cli_state **cli,
175 BOOL *retry)
177 char *machine_password, *machine_krb5_principal, *machine_account;
178 char *ipc_username, *ipc_domain, *ipc_password;
180 BOOL got_mutex;
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 result = NT_STATUS_UNSUCCESSFUL;
237 goto done;
240 if (ntohs(peeraddr_in->sin_port) == 139) {
241 struct nmb_name calling;
242 struct nmb_name called;
244 make_nmb_name(&calling, global_myname(), 0x0);
245 make_nmb_name(&called, "*SMBSERVER", 0x20);
247 if (!cli_session_request(*cli, &calling, &called)) {
248 DEBUG(8, ("cli_session_request failed for %s\n",
249 controller));
250 result = NT_STATUS_UNSUCCESSFUL;
251 goto done;
255 cli_setup_signing_state(*cli, Undefined);
257 if (!cli_negprot(*cli)) {
258 DEBUG(1, ("cli_negprot failed\n"));
259 result = NT_STATUS_UNSUCCESSFUL;
260 goto done;
263 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
264 ADS_STATUS ads_status;
266 if (lp_security() == SEC_ADS) {
268 /* Try a krb5 session */
270 (*cli)->use_kerberos = True;
271 DEBUG(5, ("connecting to %s from %s with kerberos principal "
272 "[%s]\n", controller, global_myname(),
273 machine_krb5_principal));
275 ads_status = cli_session_setup_spnego(*cli,
276 machine_krb5_principal,
277 machine_password,
278 lp_workgroup());
280 if (!ADS_ERR_OK(ads_status)) {
281 DEBUG(4,("failed kerberos session setup with %s\n",
282 ads_errstr(ads_status)));
285 result = ads_ntstatus(ads_status);
286 if (NT_STATUS_IS_OK(result)) {
287 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
288 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
289 goto session_setup_done;
293 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
294 (*cli)->use_kerberos = False;
296 DEBUG(5, ("connecting to %s from %s with username "
297 "[%s]\\[%s]\n", controller, global_myname(),
298 lp_workgroup(), machine_account));
300 ads_status = cli_session_setup_spnego(*cli,
301 machine_account,
302 machine_password,
303 lp_workgroup());
304 if (!ADS_ERR_OK(ads_status)) {
305 DEBUG(4, ("authenticated session setup failed with %s\n",
306 ads_errstr(ads_status)));
309 result = ads_ntstatus(ads_status);
310 if (NT_STATUS_IS_OK(result)) {
311 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
312 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
313 goto session_setup_done;
317 /* Fall back to non-kerberos session setup */
319 (*cli)->use_kerberos = False;
321 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
322 (strlen(ipc_username) > 0)) {
324 /* Only try authenticated if we have a username */
326 DEBUG(5, ("connecting to %s from %s with username "
327 "[%s]\\[%s]\n", controller, global_myname(),
328 ipc_domain, ipc_username));
330 if (cli_session_setup(*cli, ipc_username,
331 ipc_password, strlen(ipc_password)+1,
332 ipc_password, strlen(ipc_password)+1,
333 ipc_domain)) {
334 /* Successful logon with given username. */
335 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
336 goto session_setup_done;
337 } else {
338 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
339 ipc_domain, ipc_username ));
343 /* Fall back to anonymous connection, this might fail later */
345 if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
346 DEBUG(5, ("Connected anonymously\n"));
347 cli_init_creds(*cli, "", "", "");
348 goto session_setup_done;
351 result = cli_nt_error(*cli);
353 if (NT_STATUS_IS_OK(result))
354 result = NT_STATUS_UNSUCCESSFUL;
356 /* We can't session setup */
358 goto done;
360 session_setup_done:
362 /* cache the server name for later connections */
364 saf_store( domain->name, (*cli)->desthost );
366 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
368 result = cli_nt_error(*cli);
370 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
372 if (NT_STATUS_IS_OK(result))
373 result = NT_STATUS_UNSUCCESSFUL;
375 goto done;
378 secrets_named_mutex_release(controller);
379 got_mutex = False;
380 *retry = False;
382 /* set the domain if empty; needed for schannel connections */
383 if ( !*(*cli)->domain ) {
384 fstrcpy( (*cli)->domain, domain->name );
387 result = NT_STATUS_OK;
389 done:
390 if (got_mutex) {
391 secrets_named_mutex_release(controller);
394 SAFE_FREE(machine_account);
395 SAFE_FREE(machine_password);
396 SAFE_FREE(machine_krb5_principal);
397 SAFE_FREE(ipc_username);
398 SAFE_FREE(ipc_domain);
399 SAFE_FREE(ipc_password);
401 if (!NT_STATUS_IS_OK(result)) {
402 add_failed_connection_entry(domain->name, controller, result);
403 if ((*cli) != NULL) {
404 cli_shutdown(*cli);
405 *cli = NULL;
409 return result;
412 struct dc_name_ip {
413 fstring name;
414 struct in_addr ip;
417 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
418 const char *dcname, struct in_addr ip,
419 struct dc_name_ip **dcs, int *num)
421 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
422 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
423 return False;
426 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
428 if (*dcs == NULL)
429 return False;
431 fstrcpy((*dcs)[*num].name, dcname);
432 (*dcs)[*num].ip = ip;
433 *num += 1;
434 return True;
437 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
438 struct in_addr ip, uint16 port,
439 struct sockaddr_in **addrs, int *num)
441 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
443 if (*addrs == NULL)
444 return False;
446 (*addrs)[*num].sin_family = PF_INET;
447 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
448 (*addrs)[*num].sin_port = htons(port);
450 *num += 1;
451 return True;
454 static void mailslot_name(struct in_addr dc_ip, fstring name)
456 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
459 static BOOL send_getdc_request(struct in_addr dc_ip,
460 const char *domain_name,
461 const DOM_SID *sid)
463 pstring outbuf;
464 char *p;
465 fstring my_acct_name;
466 fstring my_mailslot;
468 mailslot_name(dc_ip, my_mailslot);
470 memset(outbuf, '\0', sizeof(outbuf));
472 p = outbuf;
474 SCVAL(p, 0, SAMLOGON);
475 p++;
477 SCVAL(p, 0, 0); /* Count pointer ... */
478 p++;
480 SIVAL(p, 0, 0); /* The sender's token ... */
481 p += 2;
483 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
484 fstr_sprintf(my_acct_name, "%s$", global_myname());
485 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
487 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
488 p += strlen(my_mailslot)+1;
490 SIVAL(p, 0, 0x80);
491 p+=4;
493 SIVAL(p, 0, sid_size(sid));
494 p+=4;
496 p = ALIGN4(p, outbuf);
498 sid_linearize(p, sid_size(sid), sid);
499 p += sid_size(sid);
501 SIVAL(p, 0, 1);
502 SSVAL(p, 4, 0xffff);
503 SSVAL(p, 6, 0xffff);
504 p+=8;
506 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
507 outbuf, PTR_DIFF(p, outbuf),
508 global_myname(), 0, domain_name, 0x1c,
509 dc_ip);
512 static BOOL receive_getdc_response(struct in_addr dc_ip,
513 const char *domain_name,
514 fstring dc_name)
516 struct packet_struct *packet;
517 fstring my_mailslot;
518 char *buf, *p;
519 fstring dcname, user, domain;
520 int len;
522 mailslot_name(dc_ip, my_mailslot);
524 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
526 if (packet == NULL) {
527 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
528 return False;
531 DEBUG(5, ("Received packet for %s\n", my_mailslot));
533 buf = packet->packet.dgram.data;
534 len = packet->packet.dgram.datasize;
536 if (len < 70) {
537 /* 70 is a completely arbitrary value to make sure
538 the SVAL below does not read uninitialized memory */
539 DEBUG(3, ("GetDC got short response\n"));
540 return False;
543 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
544 p = buf+SVAL(buf, smb_vwv10);
546 if (CVAL(p,0) != SAMLOGON_R) {
547 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
548 return False;
551 p+=2;
552 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
553 STR_TERMINATE|STR_NOALIGN);
554 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
555 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
556 STR_TERMINATE|STR_NOALIGN);
557 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
558 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
559 STR_TERMINATE|STR_NOALIGN);
560 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
562 if (!strequal(domain, domain_name)) {
563 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
564 domain_name, domain));
565 return False;
568 p = dcname;
569 if (*p == '\\') p += 1;
570 if (*p == '\\') p += 1;
572 fstrcpy(dc_name, p);
574 DEBUG(10, ("GetDC gave name %s for domain %s\n",
575 dc_name, domain));
577 return True;
580 /*******************************************************************
581 convert an ip to a name
582 *******************************************************************/
584 static BOOL dcip_to_name( const char *domainname, const char *realm,
585 const DOM_SID *sid, struct in_addr ip, fstring name )
587 struct ip_service ip_list;
589 ip_list.ip = ip;
590 ip_list.port = 0;
592 /* try GETDC requests first */
594 if (send_getdc_request(ip, domainname, sid)) {
595 int i;
596 smb_msleep(100);
597 for (i=0; i<5; i++) {
598 if (receive_getdc_response(ip, domainname, name)) {
599 namecache_store(name, 0x20, 1, &ip_list);
600 return True;
602 smb_msleep(500);
606 /* try node status request */
608 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
609 namecache_store(name, 0x20, 1, &ip_list);
610 return True;
613 #ifdef WITH_ADS
614 /* for active directory servers, try to get the ldap server name.
615 None of these failure should be considered critical for now */
617 if ( lp_security() == SEC_ADS )
619 ADS_STRUCT *ads;
621 ads = ads_init( realm, domainname, NULL );
622 ads->auth.flags |= ADS_AUTH_NO_BIND;
624 if ( !ads_try_connect( ads, inet_ntoa(ip) ) ) {
625 ads_destroy( &ads );
626 return False;
629 fstrcpy(name, ads->config.ldap_server_name);
630 namecache_store(name, 0x20, 1, &ip_list);
632 ads_destroy( &ads );
633 return True;
635 #endif
637 return False;
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 /* try standard netbios queries first */
669 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
671 /* check for security = ads and use DNS if we can */
673 if ( iplist_size==0 && lp_security() == SEC_ADS )
674 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
676 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
678 /* now add to the dc array. We'll wait until the last minute
679 to look up the name of the DC. But we fill in the char* for
680 the ip now in to make the failed connection cache work */
682 for ( i=0; i<iplist_size; i++ ) {
683 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
684 ip_list[i].ip, dcs, num_dcs);
687 SAFE_FREE( ip_list );
689 return True;
692 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
693 const struct winbindd_domain *domain,
694 fstring dcname, struct sockaddr_in *addr, int *fd)
696 struct dc_name_ip *dcs = NULL;
697 int num_dcs = 0;
699 const char **dcnames = NULL;
700 int num_dcnames = 0;
702 struct sockaddr_in *addrs = NULL;
703 int num_addrs = 0;
705 int i, fd_index;
707 again:
708 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
709 return False;
711 for (i=0; i<num_dcs; i++) {
713 add_string_to_array(mem_ctx, dcs[i].name,
714 &dcnames, &num_dcnames);
715 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
716 &addrs, &num_addrs);
718 add_string_to_array(mem_ctx, dcs[i].name,
719 &dcnames, &num_dcnames);
720 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
721 &addrs, &num_addrs);
724 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
725 return False;
727 if ((addrs == NULL) || (dcnames == NULL))
728 return False;
730 if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) )
732 for (i=0; i<num_dcs; i++) {
733 add_failed_connection_entry(domain->name,
734 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
736 return False;
739 *addr = addrs[fd_index];
741 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
742 /* Ok, we've got a name for the DC */
743 fstrcpy(dcname, dcnames[fd_index]);
744 return True;
747 /* Try to figure out the name */
748 if (dcip_to_name( domain->name, domain->alt_name, &domain->sid,
749 addr->sin_addr, dcname )) {
750 return True;
753 /* We can not continue without the DC's name */
754 add_failed_connection_entry(domain->name, dcs[fd_index].name,
755 NT_STATUS_UNSUCCESSFUL);
756 goto again;
759 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
760 struct winbindd_cm_conn *new_conn)
762 TALLOC_CTX *mem_ctx;
763 NTSTATUS result;
764 char *saf_servername = saf_fetch( domain->name );
765 int retries;
767 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
768 return NT_STATUS_NO_MEMORY;
770 /* we have to check the server affinity cache here since
771 later we selecte a DC based on response time and not preference */
773 if ( saf_servername )
775 /* convert an ip address to a name */
776 if ( is_ipaddress( saf_servername ) )
778 fstring saf_name;
779 struct in_addr ip;
781 ip = *interpret_addr2( saf_servername );
782 if (dcip_to_name( domain->name, domain->alt_name,
783 &domain->sid, ip, saf_name )) {
784 fstrcpy( domain->dcname, saf_name );
785 } else {
786 add_failed_connection_entry(
787 domain->name, saf_servername,
788 NT_STATUS_UNSUCCESSFUL);
791 else
793 fstrcpy( domain->dcname, saf_servername );
796 SAFE_FREE( saf_servername );
799 for (retries = 0; retries < 3; retries++) {
801 int fd = -1;
802 BOOL retry = False;
804 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
806 if ((strlen(domain->dcname) > 0)
807 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
808 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
810 struct sockaddr_in *addrs = NULL;
811 int num_addrs = 0;
812 int dummy = 0;
814 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
815 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
817 if (!open_any_socket_out(addrs, num_addrs, 10000, &dummy, &fd)) {
818 domain->online = False;
819 fd = -1;
823 if ((fd == -1)
824 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
826 /* This is the one place where we will
827 set the global winbindd offline state
828 to true, if a "WINBINDD_OFFLINE" entry
829 is found in the winbindd cache. */
830 set_global_winbindd_state_offline();
831 domain->online = False;
832 break;
835 new_conn->cli = NULL;
837 result = cm_prepare_connection(domain, fd, domain->dcname,
838 &new_conn->cli, &retry);
840 if (!retry)
841 break;
844 if (NT_STATUS_IS_OK(result)) {
845 if (domain->online == False) {
846 /* We're changing state from offline to online. */
847 set_global_winbindd_state_online();
849 domain->online = True;
852 talloc_destroy(mem_ctx);
853 return result;
856 /* Close down all open pipes on a connection. */
858 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
860 if (conn->samr_pipe != NULL) {
861 cli_rpc_pipe_close(conn->samr_pipe);
862 conn->samr_pipe = NULL;
865 if (conn->lsa_pipe != NULL) {
866 cli_rpc_pipe_close(conn->lsa_pipe);
867 conn->lsa_pipe = NULL;
870 if (conn->netlogon_pipe != NULL) {
871 cli_rpc_pipe_close(conn->netlogon_pipe);
872 conn->netlogon_pipe = NULL;
875 if (conn->cli) {
876 cli_shutdown(conn->cli);
879 conn->cli = NULL;
882 void close_conns_after_fork(void)
884 struct winbindd_domain *domain;
886 for (domain = domain_list(); domain; domain = domain->next) {
887 if (domain->conn.cli == NULL)
888 continue;
890 if (domain->conn.cli->fd == -1)
891 continue;
893 close(domain->conn.cli->fd);
894 domain->conn.cli->fd = -1;
898 static BOOL connection_ok(struct winbindd_domain *domain)
900 if (domain->conn.cli == NULL) {
901 DEBUG(8, ("Connection to %s for domain %s has NULL "
902 "cli!\n", domain->dcname, domain->name));
903 return False;
906 if (!domain->conn.cli->initialised) {
907 DEBUG(3, ("Connection to %s for domain %s was never "
908 "initialised!\n", domain->dcname, domain->name));
909 return False;
912 if (domain->conn.cli->fd == -1) {
913 DEBUG(3, ("Connection to %s for domain %s has died or was "
914 "never started (fd == -1)\n",
915 domain->dcname, domain->name));
916 return False;
919 return True;
922 /* Initialize a new connection up to the RPC BIND. */
924 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
926 if (connection_ok(domain))
927 return NT_STATUS_OK;
929 invalidate_cm_connection(&domain->conn);
931 return cm_open_connection(domain, &domain->conn);
934 /******************************************************************************
935 We can 'sense' certain things about the DC by it's replies to certain
936 questions.
938 This tells us if this particular remote server is Active Directory, and if it
939 is native mode.
940 ******************************************************************************/
942 void set_dc_type_and_flags( struct winbindd_domain *domain )
944 NTSTATUS result;
945 DS_DOMINFO_CTR ctr;
946 TALLOC_CTX *mem_ctx = NULL;
947 struct rpc_pipe_client *cli;
948 POLICY_HND pol;
950 char *domain_name = NULL;
951 char *dns_name = NULL;
952 DOM_SID *dom_sid = NULL;
954 ZERO_STRUCT( ctr );
956 domain->native_mode = False;
957 domain->active_directory = False;
959 if (domain->internal) {
960 domain->initialized = True;
961 return;
964 result = init_dc_connection(domain);
965 if (!NT_STATUS_IS_OK(result)) {
966 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
967 "to %s: (%s)\n", domain->name, nt_errstr(result)));
968 domain->initialized = True;
969 return;
972 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
973 &result);
975 if (cli == NULL) {
976 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
977 "PI_LSARPC_DS on domain %s: (%s)\n",
978 domain->name, nt_errstr(result)));
979 domain->initialized = True;
980 return;
983 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
984 DsRolePrimaryDomainInfoBasic,
985 &ctr);
986 cli_rpc_pipe_close(cli);
988 if (!NT_STATUS_IS_OK(result)) {
989 domain->initialized = True;
990 return;
993 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
994 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
995 domain->native_mode = True;
997 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
999 if (cli == NULL) {
1000 domain->initialized = True;
1001 return;
1004 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1005 domain->name);
1006 if (!mem_ctx) {
1007 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1008 cli_rpc_pipe_close(cli);
1009 return;
1012 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1013 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1015 if (NT_STATUS_IS_OK(result)) {
1016 /* This particular query is exactly what Win2k clients use
1017 to determine that the DC is active directory */
1018 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1019 12, &domain_name,
1020 &dns_name, NULL,
1021 NULL, &dom_sid);
1024 if (NT_STATUS_IS_OK(result)) {
1025 if (domain_name)
1026 fstrcpy(domain->name, domain_name);
1028 if (dns_name)
1029 fstrcpy(domain->alt_name, dns_name);
1031 if (dom_sid)
1032 sid_copy(&domain->sid, dom_sid);
1034 domain->active_directory = True;
1035 } else {
1037 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1038 SEC_RIGHTS_MAXIMUM_ALLOWED,
1039 &pol);
1041 if (!NT_STATUS_IS_OK(result))
1042 goto done;
1044 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1045 &pol, 5, &domain_name,
1046 &dom_sid);
1048 if (NT_STATUS_IS_OK(result)) {
1049 if (domain_name)
1050 fstrcpy(domain->name, domain_name);
1052 if (dom_sid)
1053 sid_copy(&domain->sid, dom_sid);
1056 done:
1058 cli_rpc_pipe_close(cli);
1060 talloc_destroy(mem_ctx);
1062 domain->initialized = True;
1064 return;
1067 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1068 struct dcinfo **ppdc)
1070 NTSTATUS result;
1071 struct rpc_pipe_client *netlogon_pipe;
1073 if (lp_client_schannel() == False) {
1074 return False;
1077 result = cm_connect_netlogon(domain, &netlogon_pipe);
1078 if (!NT_STATUS_IS_OK(result)) {
1079 return False;
1082 /* Return a pointer to the struct dcinfo from the
1083 netlogon pipe. */
1085 *ppdc = domain->conn.netlogon_pipe->dc;
1086 return True;
1089 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1090 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1092 struct winbindd_cm_conn *conn;
1093 NTSTATUS result;
1094 fstring conn_pwd;
1095 struct dcinfo *p_dcinfo;
1097 result = init_dc_connection(domain);
1098 if (!NT_STATUS_IS_OK(result)) {
1099 return result;
1102 conn = &domain->conn;
1104 if (conn->samr_pipe != NULL) {
1105 goto done;
1109 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1110 * sign and sealed pipe using the machine account password by
1111 * preference. If we can't - try schannel, if that fails, try
1112 * anonymous.
1115 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1116 if ((conn->cli->user_name[0] == '\0') ||
1117 (conn->cli->domain[0] == '\0') ||
1118 (conn_pwd[0] == '\0')) {
1119 DEBUG(10, ("cm_connect_sam: No no user available for "
1120 "domain %s, trying schannel\n", conn->cli->domain));
1121 goto schannel;
1124 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1125 authenticated SAMR pipe with sign & seal. */
1126 conn->samr_pipe =
1127 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1128 PIPE_AUTH_LEVEL_PRIVACY,
1129 conn->cli->domain,
1130 conn->cli->user_name,
1131 conn_pwd, &result);
1133 if (conn->samr_pipe == NULL) {
1134 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1135 "pipe for domain %s using NTLMSSP "
1136 "authenticated pipe: user %s\\%s. Error was "
1137 "%s\n", domain->name, conn->cli->domain,
1138 conn->cli->user_name, nt_errstr(result)));
1139 goto schannel;
1142 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1143 "domain %s using NTLMSSP authenticated "
1144 "pipe: user %s\\%s\n", domain->name,
1145 conn->cli->domain, conn->cli->user_name ));
1147 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1148 SEC_RIGHTS_MAXIMUM_ALLOWED,
1149 &conn->sam_connect_handle);
1150 if (NT_STATUS_IS_OK(result)) {
1151 goto open_domain;
1153 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1154 "failed for domain %s, error was %s. Trying schannel\n",
1155 domain->name, nt_errstr(result) ));
1156 cli_rpc_pipe_close(conn->samr_pipe);
1158 schannel:
1160 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1162 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1163 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1164 "for domain %s, trying anon\n", conn->cli->domain));
1165 goto anonymous;
1167 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1168 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1169 domain->name, p_dcinfo, &result);
1171 if (conn->samr_pipe == NULL) {
1172 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1173 "domain %s using schannel. Error was %s\n",
1174 domain->name, nt_errstr(result) ));
1175 goto anonymous;
1177 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1178 "schannel.\n", domain->name ));
1180 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1181 SEC_RIGHTS_MAXIMUM_ALLOWED,
1182 &conn->sam_connect_handle);
1183 if (NT_STATUS_IS_OK(result)) {
1184 goto open_domain;
1186 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1187 "for domain %s, error was %s. Trying anonymous\n",
1188 domain->name, nt_errstr(result) ));
1189 cli_rpc_pipe_close(conn->samr_pipe);
1191 anonymous:
1193 /* Finally fall back to anonymous. */
1194 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1195 &result);
1197 if (conn->samr_pipe == NULL) {
1198 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1199 goto done;
1202 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1203 SEC_RIGHTS_MAXIMUM_ALLOWED,
1204 &conn->sam_connect_handle);
1205 if (!NT_STATUS_IS_OK(result)) {
1206 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1207 "for domain %s Error was %s\n",
1208 domain->name, nt_errstr(result) ));
1209 goto done;
1212 open_domain:
1213 result = rpccli_samr_open_domain(conn->samr_pipe,
1214 mem_ctx,
1215 &conn->sam_connect_handle,
1216 SEC_RIGHTS_MAXIMUM_ALLOWED,
1217 &domain->sid,
1218 &conn->sam_domain_handle);
1220 done:
1222 if (!NT_STATUS_IS_OK(result)) {
1223 invalidate_cm_connection(conn);
1224 return result;
1227 *cli = conn->samr_pipe;
1228 *sam_handle = conn->sam_domain_handle;
1229 return result;
1232 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1233 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1235 struct winbindd_cm_conn *conn;
1236 NTSTATUS result;
1237 fstring conn_pwd;
1238 struct dcinfo *p_dcinfo;
1240 result = init_dc_connection(domain);
1241 if (!NT_STATUS_IS_OK(result))
1242 return result;
1244 conn = &domain->conn;
1246 if (conn->lsa_pipe != NULL) {
1247 goto done;
1250 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1251 if ((conn->cli->user_name[0] == '\0') ||
1252 (conn->cli->domain[0] == '\0') ||
1253 (conn_pwd[0] == '\0')) {
1254 DEBUG(10, ("cm_connect_lsa: No no user available for "
1255 "domain %s, trying schannel\n", conn->cli->domain));
1256 goto schannel;
1259 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1260 * authenticated LSA pipe with sign & seal. */
1261 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1262 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1263 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1265 if (conn->lsa_pipe == NULL) {
1266 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1267 "domain %s using NTLMSSP authenticated pipe: user "
1268 "%s\\%s. Error was %s. Trying schannel.\n",
1269 domain->name, conn->cli->domain,
1270 conn->cli->user_name, nt_errstr(result)));
1271 goto schannel;
1274 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1275 "NTLMSSP authenticated pipe: user %s\\%s\n",
1276 domain->name, conn->cli->domain, conn->cli->user_name ));
1278 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1279 SEC_RIGHTS_MAXIMUM_ALLOWED,
1280 &conn->lsa_policy);
1281 if (NT_STATUS_IS_OK(result)) {
1282 goto done;
1285 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1286 "schannel\n"));
1288 cli_rpc_pipe_close(conn->lsa_pipe);
1290 schannel:
1292 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1294 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1295 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1296 "for domain %s, trying anon\n", conn->cli->domain));
1297 goto anonymous;
1299 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1300 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1301 domain->name, p_dcinfo, &result);
1303 if (conn->lsa_pipe == NULL) {
1304 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1305 "domain %s using schannel. Error was %s\n",
1306 domain->name, nt_errstr(result) ));
1307 goto anonymous;
1309 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1310 "schannel.\n", domain->name ));
1312 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1313 SEC_RIGHTS_MAXIMUM_ALLOWED,
1314 &conn->lsa_policy);
1315 if (NT_STATUS_IS_OK(result)) {
1316 goto done;
1319 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1320 "anonymous\n"));
1322 cli_rpc_pipe_close(conn->lsa_pipe);
1324 anonymous:
1326 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1327 &result);
1328 if (conn->lsa_pipe == NULL) {
1329 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1330 goto done;
1333 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1334 SEC_RIGHTS_MAXIMUM_ALLOWED,
1335 &conn->lsa_policy);
1336 done:
1337 if (!NT_STATUS_IS_OK(result)) {
1338 invalidate_cm_connection(conn);
1339 return NT_STATUS_UNSUCCESSFUL;
1342 *cli = conn->lsa_pipe;
1343 *lsa_policy = conn->lsa_policy;
1344 return result;
1347 /****************************************************************************
1348 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1349 session key stored in conn->netlogon_pipe->dc->sess_key.
1350 ****************************************************************************/
1352 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1353 struct rpc_pipe_client **cli)
1355 struct winbindd_cm_conn *conn;
1356 NTSTATUS result;
1358 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1359 uint8 mach_pwd[16];
1360 uint32 sec_chan_type;
1361 const char *account_name;
1362 struct rpc_pipe_client *netlogon_pipe = NULL;
1364 *cli = NULL;
1366 result = init_dc_connection(domain);
1367 if (!NT_STATUS_IS_OK(result)) {
1368 return result;
1371 conn = &domain->conn;
1373 if (conn->netlogon_pipe != NULL) {
1374 *cli = conn->netlogon_pipe;
1375 return NT_STATUS_OK;
1378 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1379 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1382 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1383 &result);
1384 if (netlogon_pipe == NULL) {
1385 return result;
1388 if (lp_client_schannel() != False) {
1389 neg_flags |= NETLOGON_NEG_SCHANNEL;
1392 /* if we are a DC and this is a trusted domain, then we need to use our
1393 domain name in the net_req_auth2() request */
1395 if ( IS_DC
1396 && !strequal(domain->name, lp_workgroup())
1397 && lp_allow_trusted_domains() )
1399 account_name = lp_workgroup();
1400 } else {
1401 account_name = domain->primary ?
1402 global_myname() : domain->name;
1405 if (account_name == NULL) {
1406 cli_rpc_pipe_close(netlogon_pipe);
1407 return NT_STATUS_NO_MEMORY;
1410 result = rpccli_netlogon_setup_creds(
1411 netlogon_pipe,
1412 domain->dcname, /* server name. */
1413 domain->name, /* domain name */
1414 global_myname(), /* client name */
1415 account_name, /* machine account */
1416 mach_pwd, /* machine password */
1417 sec_chan_type, /* from get_trust_pw */
1418 &neg_flags);
1420 if (!NT_STATUS_IS_OK(result)) {
1421 cli_rpc_pipe_close(netlogon_pipe);
1422 return result;
1425 if ((lp_client_schannel() == True) &&
1426 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1427 DEBUG(3, ("Server did not offer schannel\n"));
1428 cli_rpc_pipe_close(netlogon_pipe);
1429 return NT_STATUS_ACCESS_DENIED;
1432 if ((lp_client_schannel() == False) ||
1433 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1434 /* We're done - just keep the existing connection to NETLOGON
1435 * open */
1436 conn->netlogon_pipe = netlogon_pipe;
1437 *cli = conn->netlogon_pipe;
1438 return NT_STATUS_OK;
1441 /* Using the credentials from the first pipe, open a signed and sealed
1442 second netlogon pipe. The session key is stored in the schannel
1443 part of the new pipe auth struct.
1446 conn->netlogon_pipe =
1447 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1448 PI_NETLOGON,
1449 PIPE_AUTH_LEVEL_PRIVACY,
1450 domain->name,
1451 netlogon_pipe->dc,
1452 &result);
1454 /* We can now close the initial netlogon pipe. */
1455 cli_rpc_pipe_close(netlogon_pipe);
1457 if (conn->netlogon_pipe == NULL) {
1458 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1459 "was %s\n", nt_errstr(result)));
1461 /* make sure we return something besides OK */
1462 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
1465 *cli = conn->netlogon_pipe;
1466 return NT_STATUS_OK;