1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate 9*0Sstevel@tonic-gate /* 10*0Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public 11*0Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file 12*0Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of 13*0Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/ 14*0Sstevel@tonic-gate * 15*0Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS 16*0Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 17*0Sstevel@tonic-gate * implied. See the License for the specific language governing 18*0Sstevel@tonic-gate * rights and limitations under the License. 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released 21*0Sstevel@tonic-gate * March 31, 1998. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape 24*0Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are 25*0Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All 26*0Sstevel@tonic-gate * Rights Reserved. 27*0Sstevel@tonic-gate * 28*0Sstevel@tonic-gate * Contributor(s): 29*0Sstevel@tonic-gate */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate /* 32*0Sstevel@tonic-gate * DNS callback functions for libldap that use the NSPR (Netscape 33*0Sstevel@tonic-gate * Portable Runtime) thread API. 34*0Sstevel@tonic-gate * 35*0Sstevel@tonic-gate */ 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK 38*0Sstevel@tonic-gate #include "solaris-int.h" 39*0Sstevel@tonic-gate #include <libintl.h> 40*0Sstevel@tonic-gate #include <syslog.h> 41*0Sstevel@tonic-gate #include <nsswitch.h> 42*0Sstevel@tonic-gate #include <synch.h> 43*0Sstevel@tonic-gate #include <nss_dbdefs.h> 44*0Sstevel@tonic-gate #include <netinet/in.h> 45*0Sstevel@tonic-gate static char *host_service = NULL; 46*0Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root_hosts); 47*0Sstevel@tonic-gate #endif 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate #include "ldappr-int.h" 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate static LDAPHostEnt *prldap_gethostbyname( const char *name, 52*0Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp, 53*0Sstevel@tonic-gate void *extradata ); 54*0Sstevel@tonic-gate static LDAPHostEnt *prldap_gethostbyaddr( const char *addr, int length, 55*0Sstevel@tonic-gate int type, LDAPHostEnt *result, char *buffer, int buflen, 56*0Sstevel@tonic-gate int *statusp, void *extradata ); 57*0Sstevel@tonic-gate static int prldap_getpeername( LDAP *ld, struct sockaddr *addr, 58*0Sstevel@tonic-gate char *buffer, int buflen ); 59*0Sstevel@tonic-gate static LDAPHostEnt *prldap_convert_hostent( LDAPHostEnt *ldhp, 60*0Sstevel@tonic-gate PRHostEnt *prhp ); 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK 63*0Sstevel@tonic-gate static LDAPHostEnt * 64*0Sstevel@tonic-gate prldap_gethostbyname1(const char *name, LDAPHostEnt *result, 65*0Sstevel@tonic-gate char *buffer, int buflen, int *statusp, void *extradata); 66*0Sstevel@tonic-gate extern int 67*0Sstevel@tonic-gate str2hostent(const char *instr, int lenstr, void *ent, char *buffer, 68*0Sstevel@tonic-gate int buflen); 69*0Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate /* 73*0Sstevel@tonic-gate * Install NSPR DNS functions into ld (if ld is NULL, they are installed 74*0Sstevel@tonic-gate * as the default functions for new LDAP * handles). 75*0Sstevel@tonic-gate * 76*0Sstevel@tonic-gate * Returns 0 if all goes well and -1 if not. 77*0Sstevel@tonic-gate */ 78*0Sstevel@tonic-gate int 79*0Sstevel@tonic-gate prldap_install_dns_functions( LDAP *ld ) 80*0Sstevel@tonic-gate { 81*0Sstevel@tonic-gate struct ldap_dns_fns dnsfns; 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate memset( &dnsfns, '\0', sizeof(struct ldap_dns_fns) ); 84*0Sstevel@tonic-gate dnsfns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE; 85*0Sstevel@tonic-gate dnsfns.lddnsfn_gethostbyname = prldap_gethostbyname; 86*0Sstevel@tonic-gate dnsfns.lddnsfn_gethostbyaddr = prldap_gethostbyaddr; 87*0Sstevel@tonic-gate dnsfns.lddnsfn_getpeername = prldap_getpeername; 88*0Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_OPT_DNS_FN_PTRS, (void *)&dnsfns ) != 0 ) { 89*0Sstevel@tonic-gate return( -1 ); 90*0Sstevel@tonic-gate } 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate return( 0 ); 93*0Sstevel@tonic-gate } 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate static LDAPHostEnt * 97*0Sstevel@tonic-gate prldap_gethostbyname( const char *name, LDAPHostEnt *result, 98*0Sstevel@tonic-gate char *buffer, int buflen, int *statusp, void *extradata ) 99*0Sstevel@tonic-gate { 100*0Sstevel@tonic-gate PRHostEnt prhent; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate if( !statusp || ( *statusp = (int)PR_GetIPNodeByName( name, 103*0Sstevel@tonic-gate PRLDAP_DEFAULT_ADDRESS_FAMILY, PR_AI_DEFAULT, 104*0Sstevel@tonic-gate buffer, buflen, &prhent )) == PR_FAILURE ) { 105*0Sstevel@tonic-gate return( NULL ); 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate return( prldap_convert_hostent( result, &prhent )); 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate static LDAPHostEnt * 113*0Sstevel@tonic-gate prldap_gethostbyaddr( const char *addr, int length, int type, 114*0Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp, 115*0Sstevel@tonic-gate void *extradata ) 116*0Sstevel@tonic-gate { 117*0Sstevel@tonic-gate PRHostEnt prhent; 118*0Sstevel@tonic-gate PRNetAddr iaddr; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate if ( PR_SetNetAddr(PR_IpAddrNull, PRLDAP_DEFAULT_ADDRESS_FAMILY, 121*0Sstevel@tonic-gate 0, &iaddr) == PR_FAILURE 122*0Sstevel@tonic-gate || PR_StringToNetAddr( addr, &iaddr ) == PR_FAILURE ) { 123*0Sstevel@tonic-gate return( NULL ); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate if( !statusp || (*statusp = PR_GetHostByAddr(&iaddr, buffer, 127*0Sstevel@tonic-gate buflen, &prhent )) == PR_FAILURE ) { 128*0Sstevel@tonic-gate return( NULL ); 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate return( prldap_convert_hostent( result, &prhent )); 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate static int 134*0Sstevel@tonic-gate prldap_getpeername( LDAP *ld, struct sockaddr *addr, char *buffer, int buflen) 135*0Sstevel@tonic-gate { 136*0Sstevel@tonic-gate PRLDAPIOSocketArg *sa; 137*0Sstevel@tonic-gate PRFileDesc *fd; 138*0Sstevel@tonic-gate PRNetAddr iaddr; 139*0Sstevel@tonic-gate int ret; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate if (NULL != ld) { 142*0Sstevel@tonic-gate ret = prldap_socket_arg_from_ld( ld, &sa ); 143*0Sstevel@tonic-gate if (ret != LDAP_SUCCESS) { 144*0Sstevel@tonic-gate return (-1); 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate ret = PR_GetPeerName(sa->prsock_prfd, &iaddr); 147*0Sstevel@tonic-gate if( ret == PR_FAILURE ) { 148*0Sstevel@tonic-gate return( -1 ); 149*0Sstevel@tonic-gate } 150*0Sstevel@tonic-gate *addr = *((struct sockaddr *)&iaddr.raw); 151*0Sstevel@tonic-gate ret = PR_NetAddrToString(&iaddr, buffer, buflen); 152*0Sstevel@tonic-gate if( ret == PR_FAILURE ) { 153*0Sstevel@tonic-gate return( -1 ); 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate return (0); 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate return (-1); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate /* 162*0Sstevel@tonic-gate * Function: prldap_convert_hostent() 163*0Sstevel@tonic-gate * Description: copy the fields of a PRHostEnt struct to an LDAPHostEnt 164*0Sstevel@tonic-gate * Returns: the LDAPHostEnt pointer passed in. 165*0Sstevel@tonic-gate */ 166*0Sstevel@tonic-gate static LDAPHostEnt * 167*0Sstevel@tonic-gate prldap_convert_hostent( LDAPHostEnt *ldhp, PRHostEnt *prhp ) 168*0Sstevel@tonic-gate { 169*0Sstevel@tonic-gate ldhp->ldaphe_name = prhp->h_name; 170*0Sstevel@tonic-gate ldhp->ldaphe_aliases = prhp->h_aliases; 171*0Sstevel@tonic-gate ldhp->ldaphe_addrtype = prhp->h_addrtype; 172*0Sstevel@tonic-gate ldhp->ldaphe_length = prhp->h_length; 173*0Sstevel@tonic-gate ldhp->ldaphe_addr_list = prhp->h_addr_list; 174*0Sstevel@tonic-gate return( ldhp ); 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK 178*0Sstevel@tonic-gate /* 179*0Sstevel@tonic-gate * prldap_x_install_dns_skipdb attempts to prevent recursion in resolving 180*0Sstevel@tonic-gate * the hostname to an IP address when a host name is given to LDAP user. 181*0Sstevel@tonic-gate * 182*0Sstevel@tonic-gate * For example, libsldap cannot use LDAP to resolve the host name to an 183*0Sstevel@tonic-gate * address because of recursion. The caller is instructing libldap to skip 184*0Sstevel@tonic-gate * the specified name service when resolving addresses for the specified 185*0Sstevel@tonic-gate * ldap connection. 186*0Sstevel@tonic-gate * 187*0Sstevel@tonic-gate * Note: 188*0Sstevel@tonic-gate * This only supports ipv4 addresses currently. 189*0Sstevel@tonic-gate * 190*0Sstevel@tonic-gate * Since host_service applies to all connections, calling 191*0Sstevel@tonic-gate * prldap_x_install_dns_skipdb with name services other than 192*0Sstevel@tonic-gate * ldap or what uses ldap (for example nis+ might use ldap) to 193*0Sstevel@tonic-gate * skip will lead to unpredictable results. 194*0Sstevel@tonic-gate * 195*0Sstevel@tonic-gate * Returns: 196*0Sstevel@tonic-gate * 0 if success and data base found 197*0Sstevel@tonic-gate * -1 if failure 198*0Sstevel@tonic-gate */ 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate int 201*0Sstevel@tonic-gate prldap_x_install_dns_skipdb(LDAP *ld, const char *skip) 202*0Sstevel@tonic-gate { 203*0Sstevel@tonic-gate enum __nsw_parse_err pserr; 204*0Sstevel@tonic-gate struct __nsw_switchconfig *conf; 205*0Sstevel@tonic-gate struct __nsw_lookup *lkp; 206*0Sstevel@tonic-gate struct ldap_dns_fns dns_fns; 207*0Sstevel@tonic-gate char *name_list = NULL; 208*0Sstevel@tonic-gate char *tmp; 209*0Sstevel@tonic-gate const char *name; 210*0Sstevel@tonic-gate int len; 211*0Sstevel@tonic-gate boolean_t got_skip = B_FALSE; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * db_root_hosts.lock mutex is used to ensure that the name list 215*0Sstevel@tonic-gate * is not in use by the name service switch while we are updating 216*0Sstevel@tonic-gate * the host_service 217*0Sstevel@tonic-gate */ 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate (void) mutex_lock(&db_root_hosts.lock); 220*0Sstevel@tonic-gate conf = __nsw_getconfig("hosts", &pserr); 221*0Sstevel@tonic-gate if (conf == NULL) { 222*0Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock); 223*0Sstevel@tonic-gate return (0); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate /* check for skip and count other backends */ 227*0Sstevel@tonic-gate for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) { 228*0Sstevel@tonic-gate name = lkp->service_name; 229*0Sstevel@tonic-gate if (strcmp(name, skip) == 0) { 230*0Sstevel@tonic-gate got_skip = B_TRUE; 231*0Sstevel@tonic-gate continue; 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate if (name_list == NULL) 234*0Sstevel@tonic-gate name_list = strdup(name); 235*0Sstevel@tonic-gate else { 236*0Sstevel@tonic-gate len = strlen(name_list); 237*0Sstevel@tonic-gate tmp = realloc(name_list, len + strlen(name) + 2); 238*0Sstevel@tonic-gate if (tmp == NULL) { 239*0Sstevel@tonic-gate free(name_list); 240*0Sstevel@tonic-gate name_list = NULL; 241*0Sstevel@tonic-gate } else { 242*0Sstevel@tonic-gate name_list = tmp; 243*0Sstevel@tonic-gate name_list[len++] = ' '; 244*0Sstevel@tonic-gate (void) strcpy(name_list+len, name); 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate if (name_list == NULL) { /* alloc error */ 248*0Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock); 249*0Sstevel@tonic-gate __nsw_freeconfig(conf); 250*0Sstevel@tonic-gate return (-1); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate __nsw_freeconfig(conf); 254*0Sstevel@tonic-gate if (!got_skip) { 255*0Sstevel@tonic-gate /* 256*0Sstevel@tonic-gate * Since skip name service not used for hosts, we do not need 257*0Sstevel@tonic-gate * to install our private address resolution function 258*0Sstevel@tonic-gate */ 259*0Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock); 260*0Sstevel@tonic-gate if (name_list != NULL) 261*0Sstevel@tonic-gate free(name_list); 262*0Sstevel@tonic-gate return (0); 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate if (host_service != NULL) 265*0Sstevel@tonic-gate free(host_service); 266*0Sstevel@tonic-gate host_service = name_list; 267*0Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock); 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate if (ldap_get_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0) 270*0Sstevel@tonic-gate return (-1); 271*0Sstevel@tonic-gate dns_fns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE; 272*0Sstevel@tonic-gate dns_fns.lddnsfn_gethostbyname = prldap_gethostbyname1; 273*0Sstevel@tonic-gate if (ldap_set_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0) 274*0Sstevel@tonic-gate return (-1); 275*0Sstevel@tonic-gate return (0); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate /* 279*0Sstevel@tonic-gate * prldap_initf_hosts is passed to and called by nss_search() as a 280*0Sstevel@tonic-gate * service routine. 281*0Sstevel@tonic-gate * 282*0Sstevel@tonic-gate * Returns: 283*0Sstevel@tonic-gate * None 284*0Sstevel@tonic-gate */ 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate static void 287*0Sstevel@tonic-gate prldap_initf_hosts(nss_db_params_t *p) 288*0Sstevel@tonic-gate { 289*0Sstevel@tonic-gate static char *no_service = ""; 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate p->name = NSS_DBNAM_HOSTS; 292*0Sstevel@tonic-gate p->flags |= NSS_USE_DEFAULT_CONFIG; 293*0Sstevel@tonic-gate p->default_config = host_service == NULL ? no_service : host_service; 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate /* 297*0Sstevel@tonic-gate * called by prldap_gethostbyname1() 298*0Sstevel@tonic-gate */ 299*0Sstevel@tonic-gate /* 300*0Sstevel@tonic-gate * prldap_switch_gethostbyname_r is called by prldap_gethostbyname1 as a 301*0Sstevel@tonic-gate * substitute for gethostbyname_r(). A method which prevents recursion. see 302*0Sstevel@tonic-gate * prldap_gethostbyname1() and prldap_x_install_dns_skipdb(). 303*0Sstevel@tonic-gate * 304*0Sstevel@tonic-gate * Returns: 305*0Sstevel@tonic-gate * Valid pointer to hostent if success 306*0Sstevel@tonic-gate * PR_FAILURE if failure 307*0Sstevel@tonic-gate */ 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate static struct hostent * 310*0Sstevel@tonic-gate prldap_switch_gethostbyname_r(const char *name, 311*0Sstevel@tonic-gate struct hostent *result, char *buffer, int buflen, 312*0Sstevel@tonic-gate int *h_errnop) 313*0Sstevel@tonic-gate { 314*0Sstevel@tonic-gate nss_XbyY_args_t arg; 315*0Sstevel@tonic-gate nss_status_t res; 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate /* 318*0Sstevel@tonic-gate * Log the information indicating that we are trying to 319*0Sstevel@tonic-gate * resolve the LDAP server name. 320*0Sstevel@tonic-gate */ 321*0Sstevel@tonic-gate syslog(LOG_INFO, "libldap: Resolving server name \"%s\"", name); 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2hostent); 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate arg.key.name = name; 326*0Sstevel@tonic-gate arg.stayopen = 0; 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate res = nss_search(&db_root_hosts, prldap_initf_hosts, 329*0Sstevel@tonic-gate NSS_DBOP_HOSTS_BYNAME, &arg); 330*0Sstevel@tonic-gate arg.status = res; 331*0Sstevel@tonic-gate *h_errnop = arg.h_errno; 332*0Sstevel@tonic-gate return (struct hostent *)NSS_XbyY_FINI(&arg); 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* 336*0Sstevel@tonic-gate * prldap_gethostbyname1 is used to be a substitute gethostbyname_r for 337*0Sstevel@tonic-gate * libldap when it is unsafe to use the normal nameservice functions. 338*0Sstevel@tonic-gate * 339*0Sstevel@tonic-gate * Returns: 340*0Sstevel@tonic-gate * pointer to LDAPHostEnt: if success contains the address 341*0Sstevel@tonic-gate * NULL pointer: if failure 342*0Sstevel@tonic-gate */ 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate static LDAPHostEnt * 345*0Sstevel@tonic-gate prldap_gethostbyname1(const char *name, LDAPHostEnt *result, 346*0Sstevel@tonic-gate char *buffer, int buflen, int *statusp, void *extradata) 347*0Sstevel@tonic-gate { 348*0Sstevel@tonic-gate int h_errno; 349*0Sstevel@tonic-gate LDAPHostEnt prhent; 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate if (!statusp || ( *statusp = prldap_switch_gethostbyname_r(name, 352*0Sstevel@tonic-gate &prhent, buffer, buflen, &h_errno )) == PR_FAILURE) { 353*0Sstevel@tonic-gate /* 354*0Sstevel@tonic-gate * If we got here, it means that we are not able to 355*0Sstevel@tonic-gate * resolve the LDAP server name and so warn the system 356*0Sstevel@tonic-gate * adminstrator accordingly. 357*0Sstevel@tonic-gate */ 358*0Sstevel@tonic-gate syslog(LOG_WARNING, "libldap: server name \"%s\" could not " 359*0Sstevel@tonic-gate "be resolved", name); 360*0Sstevel@tonic-gate return (NULL); 361*0Sstevel@tonic-gate } 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate return (prldap_convert_hostent(result, &prhent)); 364*0Sstevel@tonic-gate } 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 367