10Sstevel@tonic-gate /*
2*441Ssdussud * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
70Sstevel@tonic-gate
80Sstevel@tonic-gate
90Sstevel@tonic-gate /*
100Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public
110Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file
120Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of
130Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/
140Sstevel@tonic-gate *
150Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS
160Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
170Sstevel@tonic-gate * implied. See the License for the specific language governing
180Sstevel@tonic-gate * rights and limitations under the License.
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released
210Sstevel@tonic-gate * March 31, 1998.
220Sstevel@tonic-gate *
230Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape
240Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
250Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All
260Sstevel@tonic-gate * Rights Reserved.
270Sstevel@tonic-gate *
280Sstevel@tonic-gate * Contributor(s):
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate * DNS callback functions for libldap that use the NSPR (Netscape
330Sstevel@tonic-gate * Portable Runtime) thread API.
340Sstevel@tonic-gate *
350Sstevel@tonic-gate */
360Sstevel@tonic-gate
370Sstevel@tonic-gate #ifdef _SOLARIS_SDK
380Sstevel@tonic-gate #include "solaris-int.h"
390Sstevel@tonic-gate #include <libintl.h>
400Sstevel@tonic-gate #include <syslog.h>
410Sstevel@tonic-gate #include <nsswitch.h>
420Sstevel@tonic-gate #include <synch.h>
430Sstevel@tonic-gate #include <nss_dbdefs.h>
440Sstevel@tonic-gate #include <netinet/in.h>
450Sstevel@tonic-gate static char *host_service = NULL;
460Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root_hosts);
470Sstevel@tonic-gate #endif
480Sstevel@tonic-gate
490Sstevel@tonic-gate #include "ldappr-int.h"
500Sstevel@tonic-gate
510Sstevel@tonic-gate static LDAPHostEnt *prldap_gethostbyname( const char *name,
520Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
530Sstevel@tonic-gate void *extradata );
540Sstevel@tonic-gate static LDAPHostEnt *prldap_gethostbyaddr( const char *addr, int length,
550Sstevel@tonic-gate int type, LDAPHostEnt *result, char *buffer, int buflen,
560Sstevel@tonic-gate int *statusp, void *extradata );
570Sstevel@tonic-gate static int prldap_getpeername( LDAP *ld, struct sockaddr *addr,
580Sstevel@tonic-gate char *buffer, int buflen );
590Sstevel@tonic-gate static LDAPHostEnt *prldap_convert_hostent( LDAPHostEnt *ldhp,
600Sstevel@tonic-gate PRHostEnt *prhp );
610Sstevel@tonic-gate
620Sstevel@tonic-gate #ifdef _SOLARIS_SDK
630Sstevel@tonic-gate static LDAPHostEnt *
640Sstevel@tonic-gate prldap_gethostbyname1(const char *name, LDAPHostEnt *result,
650Sstevel@tonic-gate char *buffer, int buflen, int *statusp, void *extradata);
660Sstevel@tonic-gate extern int
670Sstevel@tonic-gate str2hostent(const char *instr, int lenstr, void *ent, char *buffer,
680Sstevel@tonic-gate int buflen);
690Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
700Sstevel@tonic-gate
710Sstevel@tonic-gate
720Sstevel@tonic-gate /*
730Sstevel@tonic-gate * Install NSPR DNS functions into ld (if ld is NULL, they are installed
740Sstevel@tonic-gate * as the default functions for new LDAP * handles).
750Sstevel@tonic-gate *
760Sstevel@tonic-gate * Returns 0 if all goes well and -1 if not.
770Sstevel@tonic-gate */
780Sstevel@tonic-gate int
prldap_install_dns_functions(LDAP * ld)790Sstevel@tonic-gate prldap_install_dns_functions( LDAP *ld )
800Sstevel@tonic-gate {
810Sstevel@tonic-gate struct ldap_dns_fns dnsfns;
820Sstevel@tonic-gate
830Sstevel@tonic-gate memset( &dnsfns, '\0', sizeof(struct ldap_dns_fns) );
840Sstevel@tonic-gate dnsfns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE;
850Sstevel@tonic-gate dnsfns.lddnsfn_gethostbyname = prldap_gethostbyname;
860Sstevel@tonic-gate dnsfns.lddnsfn_gethostbyaddr = prldap_gethostbyaddr;
870Sstevel@tonic-gate dnsfns.lddnsfn_getpeername = prldap_getpeername;
880Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_OPT_DNS_FN_PTRS, (void *)&dnsfns ) != 0 ) {
890Sstevel@tonic-gate return( -1 );
900Sstevel@tonic-gate }
910Sstevel@tonic-gate
920Sstevel@tonic-gate return( 0 );
930Sstevel@tonic-gate }
940Sstevel@tonic-gate
950Sstevel@tonic-gate
960Sstevel@tonic-gate static LDAPHostEnt *
prldap_gethostbyname(const char * name,LDAPHostEnt * result,char * buffer,int buflen,int * statusp,void * extradata)970Sstevel@tonic-gate prldap_gethostbyname( const char *name, LDAPHostEnt *result,
980Sstevel@tonic-gate char *buffer, int buflen, int *statusp, void *extradata )
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate PRHostEnt prhent;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate if( !statusp || ( *statusp = (int)PR_GetIPNodeByName( name,
1030Sstevel@tonic-gate PRLDAP_DEFAULT_ADDRESS_FAMILY, PR_AI_DEFAULT,
1040Sstevel@tonic-gate buffer, buflen, &prhent )) == PR_FAILURE ) {
1050Sstevel@tonic-gate return( NULL );
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate return( prldap_convert_hostent( result, &prhent ));
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate static LDAPHostEnt *
prldap_gethostbyaddr(const char * addr,int length,int type,LDAPHostEnt * result,char * buffer,int buflen,int * statusp,void * extradata)1130Sstevel@tonic-gate prldap_gethostbyaddr( const char *addr, int length, int type,
1140Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
1150Sstevel@tonic-gate void *extradata )
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate PRHostEnt prhent;
1180Sstevel@tonic-gate PRNetAddr iaddr;
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate if ( PR_SetNetAddr(PR_IpAddrNull, PRLDAP_DEFAULT_ADDRESS_FAMILY,
1210Sstevel@tonic-gate 0, &iaddr) == PR_FAILURE
1220Sstevel@tonic-gate || PR_StringToNetAddr( addr, &iaddr ) == PR_FAILURE ) {
1230Sstevel@tonic-gate return( NULL );
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate if( !statusp || (*statusp = PR_GetHostByAddr(&iaddr, buffer,
1270Sstevel@tonic-gate buflen, &prhent )) == PR_FAILURE ) {
1280Sstevel@tonic-gate return( NULL );
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate return( prldap_convert_hostent( result, &prhent ));
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate static int
prldap_getpeername(LDAP * ld,struct sockaddr * addr,char * buffer,int buflen)1340Sstevel@tonic-gate prldap_getpeername( LDAP *ld, struct sockaddr *addr, char *buffer, int buflen)
1350Sstevel@tonic-gate {
1360Sstevel@tonic-gate PRLDAPIOSocketArg *sa;
1370Sstevel@tonic-gate PRFileDesc *fd;
1380Sstevel@tonic-gate PRNetAddr iaddr;
1390Sstevel@tonic-gate int ret;
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate if (NULL != ld) {
1420Sstevel@tonic-gate ret = prldap_socket_arg_from_ld( ld, &sa );
1430Sstevel@tonic-gate if (ret != LDAP_SUCCESS) {
1440Sstevel@tonic-gate return (-1);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate ret = PR_GetPeerName(sa->prsock_prfd, &iaddr);
1470Sstevel@tonic-gate if( ret == PR_FAILURE ) {
1480Sstevel@tonic-gate return( -1 );
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate *addr = *((struct sockaddr *)&iaddr.raw);
1510Sstevel@tonic-gate ret = PR_NetAddrToString(&iaddr, buffer, buflen);
1520Sstevel@tonic-gate if( ret == PR_FAILURE ) {
1530Sstevel@tonic-gate return( -1 );
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate return (0);
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate return (-1);
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate /*
1620Sstevel@tonic-gate * Function: prldap_convert_hostent()
1630Sstevel@tonic-gate * Description: copy the fields of a PRHostEnt struct to an LDAPHostEnt
1640Sstevel@tonic-gate * Returns: the LDAPHostEnt pointer passed in.
1650Sstevel@tonic-gate */
1660Sstevel@tonic-gate static LDAPHostEnt *
prldap_convert_hostent(LDAPHostEnt * ldhp,PRHostEnt * prhp)1670Sstevel@tonic-gate prldap_convert_hostent( LDAPHostEnt *ldhp, PRHostEnt *prhp )
1680Sstevel@tonic-gate {
1690Sstevel@tonic-gate ldhp->ldaphe_name = prhp->h_name;
1700Sstevel@tonic-gate ldhp->ldaphe_aliases = prhp->h_aliases;
1710Sstevel@tonic-gate ldhp->ldaphe_addrtype = prhp->h_addrtype;
1720Sstevel@tonic-gate ldhp->ldaphe_length = prhp->h_length;
1730Sstevel@tonic-gate ldhp->ldaphe_addr_list = prhp->h_addr_list;
1740Sstevel@tonic-gate return( ldhp );
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate #ifdef _SOLARIS_SDK
1780Sstevel@tonic-gate /*
1790Sstevel@tonic-gate * prldap_x_install_dns_skipdb attempts to prevent recursion in resolving
1800Sstevel@tonic-gate * the hostname to an IP address when a host name is given to LDAP user.
1810Sstevel@tonic-gate *
1820Sstevel@tonic-gate * For example, libsldap cannot use LDAP to resolve the host name to an
1830Sstevel@tonic-gate * address because of recursion. The caller is instructing libldap to skip
1840Sstevel@tonic-gate * the specified name service when resolving addresses for the specified
1850Sstevel@tonic-gate * ldap connection.
1860Sstevel@tonic-gate *
1870Sstevel@tonic-gate * Note:
1880Sstevel@tonic-gate * This only supports ipv4 addresses currently.
1890Sstevel@tonic-gate *
1900Sstevel@tonic-gate * Since host_service applies to all connections, calling
1910Sstevel@tonic-gate * prldap_x_install_dns_skipdb with name services other than
1920Sstevel@tonic-gate * ldap or what uses ldap (for example nis+ might use ldap) to
1930Sstevel@tonic-gate * skip will lead to unpredictable results.
1940Sstevel@tonic-gate *
1950Sstevel@tonic-gate * Returns:
1960Sstevel@tonic-gate * 0 if success and data base found
1970Sstevel@tonic-gate * -1 if failure
1980Sstevel@tonic-gate */
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate int
prldap_x_install_dns_skipdb(LDAP * ld,const char * skip)2010Sstevel@tonic-gate prldap_x_install_dns_skipdb(LDAP *ld, const char *skip)
2020Sstevel@tonic-gate {
2030Sstevel@tonic-gate enum __nsw_parse_err pserr;
2040Sstevel@tonic-gate struct __nsw_switchconfig *conf;
2050Sstevel@tonic-gate struct __nsw_lookup *lkp;
2060Sstevel@tonic-gate struct ldap_dns_fns dns_fns;
2070Sstevel@tonic-gate char *name_list = NULL;
2080Sstevel@tonic-gate char *tmp;
2090Sstevel@tonic-gate const char *name;
2100Sstevel@tonic-gate int len;
2110Sstevel@tonic-gate boolean_t got_skip = B_FALSE;
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate /*
2140Sstevel@tonic-gate * db_root_hosts.lock mutex is used to ensure that the name list
2150Sstevel@tonic-gate * is not in use by the name service switch while we are updating
2160Sstevel@tonic-gate * the host_service
2170Sstevel@tonic-gate */
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate (void) mutex_lock(&db_root_hosts.lock);
2200Sstevel@tonic-gate conf = __nsw_getconfig("hosts", &pserr);
2210Sstevel@tonic-gate if (conf == NULL) {
2220Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock);
2230Sstevel@tonic-gate return (0);
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate /* check for skip and count other backends */
2270Sstevel@tonic-gate for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) {
2280Sstevel@tonic-gate name = lkp->service_name;
2290Sstevel@tonic-gate if (strcmp(name, skip) == 0) {
2300Sstevel@tonic-gate got_skip = B_TRUE;
2310Sstevel@tonic-gate continue;
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate if (name_list == NULL)
2340Sstevel@tonic-gate name_list = strdup(name);
2350Sstevel@tonic-gate else {
2360Sstevel@tonic-gate len = strlen(name_list);
2370Sstevel@tonic-gate tmp = realloc(name_list, len + strlen(name) + 2);
2380Sstevel@tonic-gate if (tmp == NULL) {
2390Sstevel@tonic-gate free(name_list);
2400Sstevel@tonic-gate name_list = NULL;
2410Sstevel@tonic-gate } else {
2420Sstevel@tonic-gate name_list = tmp;
2430Sstevel@tonic-gate name_list[len++] = ' ';
2440Sstevel@tonic-gate (void) strcpy(name_list+len, name);
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate if (name_list == NULL) { /* alloc error */
2480Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock);
2490Sstevel@tonic-gate __nsw_freeconfig(conf);
2500Sstevel@tonic-gate return (-1);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate __nsw_freeconfig(conf);
2540Sstevel@tonic-gate if (!got_skip) {
2550Sstevel@tonic-gate /*
2560Sstevel@tonic-gate * Since skip name service not used for hosts, we do not need
2570Sstevel@tonic-gate * to install our private address resolution function
2580Sstevel@tonic-gate */
2590Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock);
2600Sstevel@tonic-gate if (name_list != NULL)
2610Sstevel@tonic-gate free(name_list);
2620Sstevel@tonic-gate return (0);
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate if (host_service != NULL)
2650Sstevel@tonic-gate free(host_service);
2660Sstevel@tonic-gate host_service = name_list;
2670Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock);
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate if (ldap_get_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
2700Sstevel@tonic-gate return (-1);
2710Sstevel@tonic-gate dns_fns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE;
2720Sstevel@tonic-gate dns_fns.lddnsfn_gethostbyname = prldap_gethostbyname1;
2730Sstevel@tonic-gate if (ldap_set_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
2740Sstevel@tonic-gate return (-1);
2750Sstevel@tonic-gate return (0);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate /*
2790Sstevel@tonic-gate * prldap_initf_hosts is passed to and called by nss_search() as a
2800Sstevel@tonic-gate * service routine.
2810Sstevel@tonic-gate *
2820Sstevel@tonic-gate * Returns:
2830Sstevel@tonic-gate * None
2840Sstevel@tonic-gate */
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate static void
prldap_initf_hosts(nss_db_params_t * p)2870Sstevel@tonic-gate prldap_initf_hosts(nss_db_params_t *p)
2880Sstevel@tonic-gate {
2890Sstevel@tonic-gate static char *no_service = "";
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate p->name = NSS_DBNAM_HOSTS;
2920Sstevel@tonic-gate p->flags |= NSS_USE_DEFAULT_CONFIG;
2930Sstevel@tonic-gate p->default_config = host_service == NULL ? no_service : host_service;
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate /*
2970Sstevel@tonic-gate * called by prldap_gethostbyname1()
2980Sstevel@tonic-gate */
2990Sstevel@tonic-gate /*
3000Sstevel@tonic-gate * prldap_switch_gethostbyname_r is called by prldap_gethostbyname1 as a
3010Sstevel@tonic-gate * substitute for gethostbyname_r(). A method which prevents recursion. see
3020Sstevel@tonic-gate * prldap_gethostbyname1() and prldap_x_install_dns_skipdb().
3030Sstevel@tonic-gate *
3040Sstevel@tonic-gate * Returns:
305*441Ssdussud * PR_SUCCESS if success
3060Sstevel@tonic-gate * PR_FAILURE if failure
3070Sstevel@tonic-gate */
3080Sstevel@tonic-gate
309*441Ssdussud static int
prldap_switch_gethostbyname_r(const char * name,struct hostent * result,char * buffer,int buflen,int * h_errnop)3100Sstevel@tonic-gate prldap_switch_gethostbyname_r(const char *name,
3110Sstevel@tonic-gate struct hostent *result, char *buffer, int buflen,
3120Sstevel@tonic-gate int *h_errnop)
3130Sstevel@tonic-gate {
3140Sstevel@tonic-gate nss_XbyY_args_t arg;
3150Sstevel@tonic-gate nss_status_t res;
316*441Ssdussud struct hostent *resp;
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate /*
3190Sstevel@tonic-gate * Log the information indicating that we are trying to
3200Sstevel@tonic-gate * resolve the LDAP server name.
3210Sstevel@tonic-gate */
3220Sstevel@tonic-gate syslog(LOG_INFO, "libldap: Resolving server name \"%s\"", name);
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2hostent);
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate arg.key.name = name;
3270Sstevel@tonic-gate arg.stayopen = 0;
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate res = nss_search(&db_root_hosts, prldap_initf_hosts,
3300Sstevel@tonic-gate NSS_DBOP_HOSTS_BYNAME, &arg);
3310Sstevel@tonic-gate arg.status = res;
3320Sstevel@tonic-gate *h_errnop = arg.h_errno;
333*441Ssdussud resp = (struct hostent *)NSS_XbyY_FINI(&arg);
334*441Ssdussud
335*441Ssdussud return (resp != NULL ? PR_SUCCESS : PR_FAILURE);
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate /*
3390Sstevel@tonic-gate * prldap_gethostbyname1 is used to be a substitute gethostbyname_r for
3400Sstevel@tonic-gate * libldap when it is unsafe to use the normal nameservice functions.
3410Sstevel@tonic-gate *
3420Sstevel@tonic-gate * Returns:
3430Sstevel@tonic-gate * pointer to LDAPHostEnt: if success contains the address
3440Sstevel@tonic-gate * NULL pointer: if failure
3450Sstevel@tonic-gate */
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate static LDAPHostEnt *
prldap_gethostbyname1(const char * name,LDAPHostEnt * result,char * buffer,int buflen,int * statusp,void * extradata)3480Sstevel@tonic-gate prldap_gethostbyname1(const char *name, LDAPHostEnt *result,
3490Sstevel@tonic-gate char *buffer, int buflen, int *statusp, void *extradata)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate int h_errno;
3520Sstevel@tonic-gate LDAPHostEnt prhent;
3530Sstevel@tonic-gate
354*441Ssdussud memset(&prhent, '\0', sizeof (prhent));
3550Sstevel@tonic-gate if (!statusp || ( *statusp = prldap_switch_gethostbyname_r(name,
3560Sstevel@tonic-gate &prhent, buffer, buflen, &h_errno )) == PR_FAILURE) {
3570Sstevel@tonic-gate /*
3580Sstevel@tonic-gate * If we got here, it means that we are not able to
3590Sstevel@tonic-gate * resolve the LDAP server name and so warn the system
3600Sstevel@tonic-gate * adminstrator accordingly.
3610Sstevel@tonic-gate */
3620Sstevel@tonic-gate syslog(LOG_WARNING, "libldap: server name \"%s\" could not "
3630Sstevel@tonic-gate "be resolved", name);
3640Sstevel@tonic-gate return (NULL);
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate return (prldap_convert_hostent(result, &prhent));
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
371