1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* 7*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public 8*7c478bd9Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file 9*7c478bd9Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of 10*7c478bd9Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/ 11*7c478bd9Sstevel@tonic-gate * 12*7c478bd9Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS 13*7c478bd9Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 14*7c478bd9Sstevel@tonic-gate * implied. See the License for the specific language governing 15*7c478bd9Sstevel@tonic-gate * rights and limitations under the License. 16*7c478bd9Sstevel@tonic-gate * 17*7c478bd9Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released 18*7c478bd9Sstevel@tonic-gate * March 31, 1998. 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape 21*7c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are 22*7c478bd9Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All 23*7c478bd9Sstevel@tonic-gate * Rights Reserved. 24*7c478bd9Sstevel@tonic-gate * 25*7c478bd9Sstevel@tonic-gate * Contributor(s): 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * ldapsinit.c 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #if defined(NET_SSL) 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #if defined( _WINDOWS ) 37*7c478bd9Sstevel@tonic-gate #include <windows.h> 38*7c478bd9Sstevel@tonic-gate #endif 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate /* XXX:mhein The following is a workaround for the redefinition of */ 41*7c478bd9Sstevel@tonic-gate /* const problem on OSF. Fix to be provided by NSS */ 42*7c478bd9Sstevel@tonic-gate /* This is a pretty benign workaround for us which */ 43*7c478bd9Sstevel@tonic-gate /* should not cause problems in the future even if */ 44*7c478bd9Sstevel@tonic-gate /* we forget to take it out :-) */ 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #ifdef OSF1V4D 47*7c478bd9Sstevel@tonic-gate #ifndef __STDC__ 48*7c478bd9Sstevel@tonic-gate # define __STDC__ 49*7c478bd9Sstevel@tonic-gate #endif /* __STDC__ */ 50*7c478bd9Sstevel@tonic-gate #endif /* OSF1V4D */ 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #include <errno.h> 53*7c478bd9Sstevel@tonic-gate #include <nspr.h> 54*7c478bd9Sstevel@tonic-gate #include <cert.h> 55*7c478bd9Sstevel@tonic-gate #include <key.h> 56*7c478bd9Sstevel@tonic-gate #include <ssl.h> 57*7c478bd9Sstevel@tonic-gate #include <sslproto.h> 58*7c478bd9Sstevel@tonic-gate #include <sslerr.h> 59*7c478bd9Sstevel@tonic-gate #include <prnetdb.h> 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #include <ldap.h> 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #include <ldappr.h> 64*7c478bd9Sstevel@tonic-gate #include <pk11func.h> 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 67*7c478bd9Sstevel@tonic-gate #include "solaris-int.h" 68*7c478bd9Sstevel@tonic-gate #include <libintl.h> 69*7c478bd9Sstevel@tonic-gate #include <syslog.h> 70*7c478bd9Sstevel@tonic-gate #include <nsswitch.h> 71*7c478bd9Sstevel@tonic-gate #include <synch.h> 72*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h> 73*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate #define HOST_BUF_SIZE 2048 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate #ifndef INADDR_NONE 78*7c478bd9Sstevel@tonic-gate #define INADDR_NONE (-1) 79*7c478bd9Sstevel@tonic-gate #endif 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate extern int 82*7c478bd9Sstevel@tonic-gate str2hostent(const char *instr, int lenstr, void *ent, char *buffer, 83*7c478bd9Sstevel@tonic-gate int buflen); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate extern int 86*7c478bd9Sstevel@tonic-gate str2hostent6(const char *instr, int lenstr, void *ent, char *buffer, 87*7c478bd9Sstevel@tonic-gate int buflen); 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate extern LDAPHostEnt * 90*7c478bd9Sstevel@tonic-gate _ns_gethostbyaddr(LDAP *ld, const char *addr, int length, int type, 91*7c478bd9Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp, 92*7c478bd9Sstevel@tonic-gate void *extradata); 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate static char *host_service = NULL; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root_hosts); 97*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root_ipnodes); 98*7c478bd9Sstevel@tonic-gate #endif 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate /* 101*7c478bd9Sstevel@tonic-gate * Data structure to hold the standard NSPR I/O function pointers set by 102*7c478bd9Sstevel@tonic-gate * libprldap. We save them in our session data structure so we can call 103*7c478bd9Sstevel@tonic-gate * them from our own I/O functions (we add functionality to support SSL 104*7c478bd9Sstevel@tonic-gate * while using libprldap's functions as much as possible). 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate typedef struct ldapssl_std_functions { 107*7c478bd9Sstevel@tonic-gate LDAP_X_EXTIOF_CLOSE_CALLBACK *lssf_close_fn; 108*7c478bd9Sstevel@tonic-gate LDAP_X_EXTIOF_CONNECT_CALLBACK *lssf_connect_fn; 109*7c478bd9Sstevel@tonic-gate LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *lssf_disposehdl_fn; 110*7c478bd9Sstevel@tonic-gate } LDAPSSLStdFunctions; 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* 115*7c478bd9Sstevel@tonic-gate * LDAP session data structure. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate typedef struct ldapssl_session_info { 118*7c478bd9Sstevel@tonic-gate int lssei_using_pcks_fns; 119*7c478bd9Sstevel@tonic-gate int lssei_ssl_strength; 120*7c478bd9Sstevel@tonic-gate char *lssei_certnickname; 121*7c478bd9Sstevel@tonic-gate char *lssei_keypasswd; 122*7c478bd9Sstevel@tonic-gate LDAPSSLStdFunctions lssei_std_functions; 123*7c478bd9Sstevel@tonic-gate CERTCertDBHandle *lssei_certdbh; 124*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 125*7c478bd9Sstevel@tonic-gate /* 126*7c478bd9Sstevel@tonic-gate * This is a hack. 127*7c478bd9Sstevel@tonic-gate * ld is used so that we can use libldap's gethostbyaddr 128*7c478bd9Sstevel@tonic-gate * resolver. This is needed to prevent recursion with libsldap. 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate LDAP *ld; 131*7c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 132*7c478bd9Sstevel@tonic-gate } LDAPSSLSessionInfo; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* 136*7c478bd9Sstevel@tonic-gate * LDAP socket data structure. 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate typedef struct ldapssl_socket_info { 139*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *soi_sessioninfo; /* session info */ 140*7c478bd9Sstevel@tonic-gate } LDAPSSLSocketInfo; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * XXXceb This is a hack until the new IO functions are done. 145*7c478bd9Sstevel@tonic-gate * this function MUST be called before ldap_enable_clienauth. 146*7c478bd9Sstevel@tonic-gate * right now, this function is called in ldapssl_pkcs_init(); 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate static int using_pkcs_functions = 0; 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate void set_using_pkcs_functions( int val ) 152*7c478bd9Sstevel@tonic-gate { 153*7c478bd9Sstevel@tonic-gate using_pkcs_functions = val; 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate /* 158*7c478bd9Sstevel@tonic-gate * Utility functions: 159*7c478bd9Sstevel@tonic-gate */ 160*7c478bd9Sstevel@tonic-gate static void ldapssl_free_session_info( LDAPSSLSessionInfo **ssipp ); 161*7c478bd9Sstevel@tonic-gate static void ldapssl_free_socket_info( LDAPSSLSocketInfo **soipp ); 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate /* 165*7c478bd9Sstevel@tonic-gate * SSL Stuff 166*7c478bd9Sstevel@tonic-gate */ 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate static int ldapssl_AuthCertificate(void *sessionarg, PRFileDesc *fd, 169*7c478bd9Sstevel@tonic-gate PRBool checkSig, PRBool isServer); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * client auth stuff 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate static int get_clientauth_data( void *sessionarg, PRFileDesc *prfd, 175*7c478bd9Sstevel@tonic-gate CERTDistNames *caNames, CERTCertificate **pRetCert, 176*7c478bd9Sstevel@tonic-gate SECKEYPrivateKey **pRetKey ); 177*7c478bd9Sstevel@tonic-gate static int get_keyandcert( LDAPSSLSessionInfo *ssip, 178*7c478bd9Sstevel@tonic-gate CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey, 179*7c478bd9Sstevel@tonic-gate char **errmsgp ); 180*7c478bd9Sstevel@tonic-gate static int check_clientauth_nicknames_and_passwd( LDAP *ld, 181*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip ); 182*7c478bd9Sstevel@tonic-gate static char *get_keypassword( PK11SlotInfo *slot, PRBool retry, 183*7c478bd9Sstevel@tonic-gate void *sessionarg ); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * Static variables. 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 189*7c478bd9Sstevel@tonic-gate static int default_ssl_strength = LDAPSSL_AUTH_CNCHECK; 190*7c478bd9Sstevel@tonic-gate #else 191*7c478bd9Sstevel@tonic-gate static int default_ssl_strength = LDAPSSL_AUTH_CERT; 192*7c478bd9Sstevel@tonic-gate #endif 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate /* 195*7c478bd9Sstevel@tonic-gate * Like ldap_init(), except also install I/O routines from libsec so we 196*7c478bd9Sstevel@tonic-gate * can support SSL. If defsecure is non-zero, SSL is enabled for the 197*7c478bd9Sstevel@tonic-gate * default connection as well. 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate LDAP * 200*7c478bd9Sstevel@tonic-gate LDAP_CALL 201*7c478bd9Sstevel@tonic-gate ldapssl_init( const char *defhost, int defport, int defsecure ) 202*7c478bd9Sstevel@tonic-gate { 203*7c478bd9Sstevel@tonic-gate LDAP *ld; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate #ifndef LDAP_SSLIO_HOOKS 207*7c478bd9Sstevel@tonic-gate return( NULL ); 208*7c478bd9Sstevel@tonic-gate #else 209*7c478bd9Sstevel@tonic-gate if (0 ==defport) 210*7c478bd9Sstevel@tonic-gate defport = LDAPS_PORT; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate if (( ld = ldap_init( defhost, defport )) == NULL ) { 213*7c478bd9Sstevel@tonic-gate return( NULL ); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate if ( ldapssl_install_routines( ld ) < 0 || ldap_set_option( ld, 217*7c478bd9Sstevel@tonic-gate LDAP_OPT_SSL, defsecure ? LDAP_OPT_ON : LDAP_OPT_OFF ) != 0 ) { 218*7c478bd9Sstevel@tonic-gate PR_SetError( PR_UNKNOWN_ERROR, EINVAL ); /* XXXmcs: just a guess! */ 219*7c478bd9Sstevel@tonic-gate ldap_unbind( ld ); 220*7c478bd9Sstevel@tonic-gate return( NULL ); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate return( ld ); 224*7c478bd9Sstevel@tonic-gate #endif 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate static int 229*7c478bd9Sstevel@tonic-gate ldapssl_close(int s, struct lextiof_socket_private *socketarg) 230*7c478bd9Sstevel@tonic-gate { 231*7c478bd9Sstevel@tonic-gate PRLDAPSocketInfo soi; 232*7c478bd9Sstevel@tonic-gate LDAPSSLSocketInfo *ssoip; 233*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate memset( &soi, 0, sizeof(soi)); 236*7c478bd9Sstevel@tonic-gate soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE; 237*7c478bd9Sstevel@tonic-gate if ( prldap_get_socket_info( s, socketarg, &soi ) != LDAP_SUCCESS ) { 238*7c478bd9Sstevel@tonic-gate return( -1 ); 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate ssoip = (LDAPSSLSocketInfo *)soi.soinfo_appdata; 242*7c478bd9Sstevel@tonic-gate sseip = ssoip->soi_sessioninfo; 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate ldapssl_free_socket_info( (LDAPSSLSocketInfo **)&soi.soinfo_appdata ); 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate return( (*(sseip->lssei_std_functions.lssf_close_fn))( s, socketarg )); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate static int 250*7c478bd9Sstevel@tonic-gate do_ldapssl_connect(const char *hostlist, int defport, int timeout, 251*7c478bd9Sstevel@tonic-gate unsigned long options, struct lextiof_session_private *sessionarg, 252*7c478bd9Sstevel@tonic-gate struct lextiof_socket_private **socketargp, int clientauth ) 253*7c478bd9Sstevel@tonic-gate { 254*7c478bd9Sstevel@tonic-gate int intfd = -1; 255*7c478bd9Sstevel@tonic-gate PRBool secure; 256*7c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei; 257*7c478bd9Sstevel@tonic-gate PRLDAPSocketInfo soi; 258*7c478bd9Sstevel@tonic-gate LDAPSSLSocketInfo *ssoip = NULL; 259*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip; 260*7c478bd9Sstevel@tonic-gate PRFileDesc *sslfd = NULL; 261*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 262*7c478bd9Sstevel@tonic-gate int port; 263*7c478bd9Sstevel@tonic-gate int parse_err; 264*7c478bd9Sstevel@tonic-gate char *host = NULL; 265*7c478bd9Sstevel@tonic-gate char *name; 266*7c478bd9Sstevel@tonic-gate struct ldap_x_hostlist_status 267*7c478bd9Sstevel@tonic-gate *status = NULL; 268*7c478bd9Sstevel@tonic-gate in_addr_t addr_ipv4; 269*7c478bd9Sstevel@tonic-gate in6_addr_t addr_ipv6; 270*7c478bd9Sstevel@tonic-gate char *host_buf; 271*7c478bd9Sstevel@tonic-gate LDAPHostEnt *hent; 272*7c478bd9Sstevel@tonic-gate LDAPHostEnt host_ent; 273*7c478bd9Sstevel@tonic-gate int stat; 274*7c478bd9Sstevel@tonic-gate int type; 275*7c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate /* 278*7c478bd9Sstevel@tonic-gate * Determine if secure option is set. Also, clear secure bit in options 279*7c478bd9Sstevel@tonic-gate * the we pass to the standard connect() function (since it doesn't know 280*7c478bd9Sstevel@tonic-gate * how to handle the secure option). 281*7c478bd9Sstevel@tonic-gate */ 282*7c478bd9Sstevel@tonic-gate if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) { 283*7c478bd9Sstevel@tonic-gate secure = PR_TRUE; 284*7c478bd9Sstevel@tonic-gate options &= ~LDAP_X_EXTIOF_OPT_SECURE; 285*7c478bd9Sstevel@tonic-gate } else { 286*7c478bd9Sstevel@tonic-gate secure = PR_FALSE; 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * Retrieve session info. so we can store a pointer to our session info. 291*7c478bd9Sstevel@tonic-gate * in our socket info. later. 292*7c478bd9Sstevel@tonic-gate */ 293*7c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof(sei)); 294*7c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE; 295*7c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( NULL, sessionarg, &sei ) != LDAP_SUCCESS ) { 296*7c478bd9Sstevel@tonic-gate return( -1 ); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata; 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * Call the standard connect() callback to make the TCP connection. 302*7c478bd9Sstevel@tonic-gate * If it succeeds, *socketargp is set. 303*7c478bd9Sstevel@tonic-gate */ 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate intfd = (*(sseip->lssei_std_functions.lssf_connect_fn))( hostlist, defport, 306*7c478bd9Sstevel@tonic-gate timeout, options, sessionarg, socketargp 307*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 308*7c478bd9Sstevel@tonic-gate , &host ); 309*7c478bd9Sstevel@tonic-gate #else 310*7c478bd9Sstevel@tonic-gate ); 311*7c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate if ( intfd < 0 ) { 314*7c478bd9Sstevel@tonic-gate return( intfd ); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 318*7c478bd9Sstevel@tonic-gate /* 319*7c478bd9Sstevel@tonic-gate * Determine if the "host name" is an ip address. If so, 320*7c478bd9Sstevel@tonic-gate * we must look up the actual host name corresponding to 321*7c478bd9Sstevel@tonic-gate * it. 322*7c478bd9Sstevel@tonic-gate */ 323*7c478bd9Sstevel@tonic-gate if ( NULL == host ) { 324*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate type = AF_UNSPEC; 327*7c478bd9Sstevel@tonic-gate if (strlen(host) < INET6_ADDRSTRLEN && 328*7c478bd9Sstevel@tonic-gate inet_pton(AF_INET6, host, &addr_ipv6) == 1) { 329*7c478bd9Sstevel@tonic-gate type = AF_INET6; 330*7c478bd9Sstevel@tonic-gate } else if (strlen(host) < INET_ADDRSTRLEN && 331*7c478bd9Sstevel@tonic-gate inet_pton(AF_INET, host, &addr_ipv4) == 1) { 332*7c478bd9Sstevel@tonic-gate type = AF_INET; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate if (type == AF_INET || type == AF_INET6) { 335*7c478bd9Sstevel@tonic-gate host_buf = malloc(HOST_BUF_SIZE); 336*7c478bd9Sstevel@tonic-gate if (host_buf == NULL) { 337*7c478bd9Sstevel@tonic-gate /* will free host in close_socket_and_exit_with_error */ 338*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate /* Call ldap layer's gethostbyaddr resolver */ 342*7c478bd9Sstevel@tonic-gate hent = _ns_gethostbyaddr(sseip->ld, host, strlen(host), type, 343*7c478bd9Sstevel@tonic-gate &host_ent, host_buf, HOST_BUF_SIZE, &stat, NULL); 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate /* If we are unable to lookup the host addr, we fail! */ 346*7c478bd9Sstevel@tonic-gate if (hent == NULL) { 347*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 348*7c478bd9Sstevel@tonic-gate "libldap: do_ldapssl_connect: " 349*7c478bd9Sstevel@tonic-gate "Unable to resolve '%s'", host); 350*7c478bd9Sstevel@tonic-gate free(host_buf); 351*7c478bd9Sstevel@tonic-gate /* will free host in close_socket_and_exit_with_error */ 352*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate /* We support only the primary host name */ 355*7c478bd9Sstevel@tonic-gate else { 356*7c478bd9Sstevel@tonic-gate if (hent->ldaphe_name != NULL) 357*7c478bd9Sstevel@tonic-gate name = strdup(hent->ldaphe_name); 358*7c478bd9Sstevel@tonic-gate free(host_buf); 359*7c478bd9Sstevel@tonic-gate if (name == NULL) 360*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 361*7c478bd9Sstevel@tonic-gate else 362*7c478bd9Sstevel@tonic-gate ldap_memfree(host); host = NULL; 363*7c478bd9Sstevel@tonic-gate host = name; 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate /* 369*7c478bd9Sstevel@tonic-gate * Retrieve socket info. so we have the PRFileDesc. 370*7c478bd9Sstevel@tonic-gate */ 371*7c478bd9Sstevel@tonic-gate memset( &soi, 0, sizeof(soi)); 372*7c478bd9Sstevel@tonic-gate soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE; 373*7c478bd9Sstevel@tonic-gate if ( prldap_get_socket_info( intfd, *socketargp, &soi ) != LDAP_SUCCESS ) { 374*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate /* 378*7c478bd9Sstevel@tonic-gate * Allocate a structure to hold our socket-specific data. 379*7c478bd9Sstevel@tonic-gate */ 380*7c478bd9Sstevel@tonic-gate if ( NULL == ( ssoip = PR_Calloc( 1, sizeof( LDAPSSLSocketInfo )))) { 381*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate ssoip->soi_sessioninfo = sseip; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate /* 386*7c478bd9Sstevel@tonic-gate * Add SSL layer and let the standard NSPR to LDAP layer and enable SSL. 387*7c478bd9Sstevel@tonic-gate */ 388*7c478bd9Sstevel@tonic-gate if (( sslfd = SSL_ImportFD( NULL, soi.soinfo_prfd )) == NULL ) { 389*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate if ( SSL_OptionSet( sslfd, SSL_SECURITY, secure ) != SECSuccess || 393*7c478bd9Sstevel@tonic-gate SSL_OptionSet( sslfd, SSL_HANDSHAKE_AS_CLIENT, secure ) 394*7c478bd9Sstevel@tonic-gate != SECSuccess || ( secure && SSL_ResetHandshake( sslfd, 395*7c478bd9Sstevel@tonic-gate PR_FALSE ) != SECSuccess )) { 396*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* 400*7c478bd9Sstevel@tonic-gate * Let the standard NSPR to LDAP layer know about the new socket and 401*7c478bd9Sstevel@tonic-gate * our own socket-specific data. 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate soi.soinfo_prfd = sslfd; 404*7c478bd9Sstevel@tonic-gate soi.soinfo_appdata = (void *)ssoip; 405*7c478bd9Sstevel@tonic-gate if ( prldap_set_socket_info( intfd, *socketargp, &soi ) != LDAP_SUCCESS ) { 406*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 410*7c478bd9Sstevel@tonic-gate /* 411*7c478bd9Sstevel@tonic-gate * Set hostname which will be retrieved (depending on ssl strength) when 412*7c478bd9Sstevel@tonic-gate * using client or server auth. 413*7c478bd9Sstevel@tonic-gate */ 414*7c478bd9Sstevel@tonic-gate if (SSL_SetURL(sslfd, host) != SECSuccess) 415*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 416*7c478bd9Sstevel@tonic-gate ldap_memfree(host); 417*7c478bd9Sstevel@tonic-gate host = NULL; 418*7c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate sslfd = NULL; /* so we don't close the socket twice upon error */ 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate /* 423*7c478bd9Sstevel@tonic-gate * Install certificate hook function. 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate SSL_AuthCertificateHook( soi.soinfo_prfd, 426*7c478bd9Sstevel@tonic-gate (SSLAuthCertificate)ldapssl_AuthCertificate, 427*7c478bd9Sstevel@tonic-gate (void *)sseip); 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate if ( SSL_GetClientAuthDataHook( soi.soinfo_prfd, 430*7c478bd9Sstevel@tonic-gate get_clientauth_data, clientauth ? sseip : NULL ) != 0 ) { 431*7c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error; 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate return( intfd ); /* success */ 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate close_socket_and_exit_with_error: 437*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 438*7c478bd9Sstevel@tonic-gate if ( NULL != host ) ldap_memfree(host); 439*7c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 440*7c478bd9Sstevel@tonic-gate if ( NULL != sslfd ) { 441*7c478bd9Sstevel@tonic-gate PR_Close( sslfd ); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate if ( NULL != ssoip ) { 444*7c478bd9Sstevel@tonic-gate ldapssl_free_socket_info( &ssoip ); 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate if ( intfd >= 0 && NULL != *socketargp ) { 447*7c478bd9Sstevel@tonic-gate (*(sseip->lssei_std_functions.lssf_close_fn))( intfd, *socketargp ); 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate return( -1 ); 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate static int 454*7c478bd9Sstevel@tonic-gate ldapssl_connect(const char *hostlist, int defport, int timeout, 455*7c478bd9Sstevel@tonic-gate unsigned long options, struct lextiof_session_private *sessionarg, 456*7c478bd9Sstevel@tonic-gate struct lextiof_socket_private **socketargp ) 457*7c478bd9Sstevel@tonic-gate { 458*7c478bd9Sstevel@tonic-gate return( do_ldapssl_connect( hostlist, defport, timeout, options, 459*7c478bd9Sstevel@tonic-gate sessionarg, socketargp, 0 )); 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate static int 464*7c478bd9Sstevel@tonic-gate ldapssl_clientauth_connect(const char *hostlist, int defport, int timeout, 465*7c478bd9Sstevel@tonic-gate unsigned long options, struct lextiof_session_private *sessionarg, 466*7c478bd9Sstevel@tonic-gate struct lextiof_socket_private **socketargp ) 467*7c478bd9Sstevel@tonic-gate { 468*7c478bd9Sstevel@tonic-gate return( do_ldapssl_connect( hostlist, defport, timeout, options, 469*7c478bd9Sstevel@tonic-gate sessionarg, socketargp, 1 )); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate static void 474*7c478bd9Sstevel@tonic-gate ldapssl_disposehandle(LDAP *ld, struct lextiof_session_private *sessionarg) 475*7c478bd9Sstevel@tonic-gate { 476*7c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei; 477*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip; 478*7c478bd9Sstevel@tonic-gate LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *disposehdl_fn; 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof( sei )); 481*7c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE; 482*7c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) == LDAP_SUCCESS ) { 483*7c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata; 484*7c478bd9Sstevel@tonic-gate disposehdl_fn = sseip->lssei_std_functions.lssf_disposehdl_fn; 485*7c478bd9Sstevel@tonic-gate ldapssl_free_session_info( &sseip ); 486*7c478bd9Sstevel@tonic-gate (*disposehdl_fn)( ld, sessionarg ); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate /* 492*7c478bd9Sstevel@tonic-gate * Install I/O routines from libsec and NSPR into libldap to allow libldap 493*7c478bd9Sstevel@tonic-gate * to do SSL. 494*7c478bd9Sstevel@tonic-gate * 495*7c478bd9Sstevel@tonic-gate * We rely on libprldap to provide most of the functions, and then we override 496*7c478bd9Sstevel@tonic-gate * a few of them to support SSL. 497*7c478bd9Sstevel@tonic-gate */ 498*7c478bd9Sstevel@tonic-gate int 499*7c478bd9Sstevel@tonic-gate LDAP_CALL 500*7c478bd9Sstevel@tonic-gate ldapssl_install_routines( LDAP *ld ) 501*7c478bd9Sstevel@tonic-gate { 502*7c478bd9Sstevel@tonic-gate #ifndef LDAP_SSLIO_HOOKS 503*7c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); 504*7c478bd9Sstevel@tonic-gate return( -1 ); 505*7c478bd9Sstevel@tonic-gate #else 506*7c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns; 507*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip; 508*7c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei; 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate /* 511*7c478bd9Sstevel@tonic-gate * This is done within ldap_init() and 512*7c478bd9Sstevel@tonic-gate * ldap_init() is called from ldapssl_init() 513*7c478bd9Sstevel@tonic-gate */ 514*7c478bd9Sstevel@tonic-gate #ifndef _SOLARIS_SDK 515*7c478bd9Sstevel@tonic-gate if ( prldap_install_routines( 516*7c478bd9Sstevel@tonic-gate ld, 517*7c478bd9Sstevel@tonic-gate 1 /* shared -- we have to assume it is */ ) 518*7c478bd9Sstevel@tonic-gate != LDAP_SUCCESS ) { 519*7c478bd9Sstevel@tonic-gate return( -1 ); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate #endif /*_SOLARIS_SDK*/ 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate /* 524*7c478bd9Sstevel@tonic-gate * Allocate our own session information. 525*7c478bd9Sstevel@tonic-gate */ 526*7c478bd9Sstevel@tonic-gate if ( NULL == ( ssip = (LDAPSSLSessionInfo *)PR_Calloc( 1, 527*7c478bd9Sstevel@tonic-gate sizeof( LDAPSSLSessionInfo )))) { 528*7c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL ); 529*7c478bd9Sstevel@tonic-gate return( -1 ); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate /* 532*7c478bd9Sstevel@tonic-gate * Initialize session info. 533*7c478bd9Sstevel@tonic-gate * XXX: it would be nice to be able to set these on a per-session basis: 534*7c478bd9Sstevel@tonic-gate * lssei_using_pcks_fns 535*7c478bd9Sstevel@tonic-gate * lssei_certdbh 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate ssip->lssei_ssl_strength = default_ssl_strength; 538*7c478bd9Sstevel@tonic-gate ssip->lssei_using_pcks_fns = using_pkcs_functions; 539*7c478bd9Sstevel@tonic-gate ssip->lssei_certdbh = CERT_GetDefaultCertDB(); 540*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 541*7c478bd9Sstevel@tonic-gate /* 542*7c478bd9Sstevel@tonic-gate * This is part of a hack to allow the ssl portion of the 543*7c478bd9Sstevel@tonic-gate * library to call the ldap library gethostbyaddr resolver. 544*7c478bd9Sstevel@tonic-gate */ 545*7c478bd9Sstevel@tonic-gate ssip->ld = ld; 546*7c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate /* 549*7c478bd9Sstevel@tonic-gate * override a few functions, saving a pointer to the standard function 550*7c478bd9Sstevel@tonic-gate * in each case so we can call it from our SSL savvy functions. 551*7c478bd9Sstevel@tonic-gate */ 552*7c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns)); 553*7c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; 554*7c478bd9Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) { 555*7c478bd9Sstevel@tonic-gate ldapssl_free_session_info( &ssip ); 556*7c478bd9Sstevel@tonic-gate return( -1 ); 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate /* override socket, connect, and ioctl */ 560*7c478bd9Sstevel@tonic-gate ssip->lssei_std_functions.lssf_connect_fn = iofns.lextiof_connect; 561*7c478bd9Sstevel@tonic-gate iofns.lextiof_connect = ldapssl_connect; 562*7c478bd9Sstevel@tonic-gate ssip->lssei_std_functions.lssf_close_fn = iofns.lextiof_close; 563*7c478bd9Sstevel@tonic-gate iofns.lextiof_close = ldapssl_close; 564*7c478bd9Sstevel@tonic-gate ssip->lssei_std_functions.lssf_disposehdl_fn = iofns.lextiof_disposehandle; 565*7c478bd9Sstevel@tonic-gate iofns.lextiof_disposehandle = ldapssl_disposehandle; 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) { 568*7c478bd9Sstevel@tonic-gate ldapssl_free_session_info( &ssip ); 569*7c478bd9Sstevel@tonic-gate return( -1 ); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate /* 573*7c478bd9Sstevel@tonic-gate * Store session info. for later retrieval. 574*7c478bd9Sstevel@tonic-gate */ 575*7c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE; 576*7c478bd9Sstevel@tonic-gate sei.seinfo_appdata = (void *)ssip; 577*7c478bd9Sstevel@tonic-gate if ( prldap_set_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) { 578*7c478bd9Sstevel@tonic-gate return( -1 ); 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate return( 0 ); 582*7c478bd9Sstevel@tonic-gate #endif 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate /* 587*7c478bd9Sstevel@tonic-gate * Set the SSL strength for an existing SSL-enabled LDAP session handle. 588*7c478bd9Sstevel@tonic-gate * 589*7c478bd9Sstevel@tonic-gate * See the description of ldapssl_serverauth_init() above for valid 590*7c478bd9Sstevel@tonic-gate * sslstrength values. If ld is NULL, the default for new LDAP session 591*7c478bd9Sstevel@tonic-gate * handles is set. 592*7c478bd9Sstevel@tonic-gate * 593*7c478bd9Sstevel@tonic-gate * Returns 0 if all goes well and -1 if an error occurs. 594*7c478bd9Sstevel@tonic-gate */ 595*7c478bd9Sstevel@tonic-gate int 596*7c478bd9Sstevel@tonic-gate LDAP_CALL 597*7c478bd9Sstevel@tonic-gate ldapssl_set_strength( LDAP *ld, int sslstrength ) 598*7c478bd9Sstevel@tonic-gate { 599*7c478bd9Sstevel@tonic-gate int rc = 0; /* assume success */ 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate if ( sslstrength != LDAPSSL_AUTH_WEAK && 602*7c478bd9Sstevel@tonic-gate sslstrength != LDAPSSL_AUTH_CERT && 603*7c478bd9Sstevel@tonic-gate sslstrength != LDAPSSL_AUTH_CNCHECK ) { 604*7c478bd9Sstevel@tonic-gate rc = -1; 605*7c478bd9Sstevel@tonic-gate } else { 606*7c478bd9Sstevel@tonic-gate if ( NULL == ld ) { /* set default strength */ 607*7c478bd9Sstevel@tonic-gate default_ssl_strength = sslstrength; 608*7c478bd9Sstevel@tonic-gate } else { /* set session-specific strength */ 609*7c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei; 610*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip; 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof( sei )); 613*7c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE; 614*7c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) == LDAP_SUCCESS ) 615*7c478bd9Sstevel@tonic-gate { 616*7c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata; 617*7c478bd9Sstevel@tonic-gate sseip->lssei_ssl_strength = sslstrength; 618*7c478bd9Sstevel@tonic-gate } else { 619*7c478bd9Sstevel@tonic-gate rc = -1; 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate } 622*7c478bd9Sstevel@tonic-gate } 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate return( rc ); 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate int 628*7c478bd9Sstevel@tonic-gate LDAP_CALL 629*7c478bd9Sstevel@tonic-gate ldapssl_enable_clientauth( LDAP *ld, char *keynickname, 630*7c478bd9Sstevel@tonic-gate char *keypasswd, char *certnickname ) 631*7c478bd9Sstevel@tonic-gate { 632*7c478bd9Sstevel@tonic-gate #ifndef LDAP_SSLIO_HOOKS 633*7c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); 634*7c478bd9Sstevel@tonic-gate return( -1 ); 635*7c478bd9Sstevel@tonic-gate #else 636*7c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns; 637*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip; 638*7c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* 641*7c478bd9Sstevel@tonic-gate * Check parameters 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate if ( certnickname == NULL || keypasswd == NULL ) { 644*7c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); 645*7c478bd9Sstevel@tonic-gate return( -1 ); 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate /* 649*7c478bd9Sstevel@tonic-gate * Update session info. data structure. 650*7c478bd9Sstevel@tonic-gate */ 651*7c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE; 652*7c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) { 653*7c478bd9Sstevel@tonic-gate return( -1 ); 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate ssip = (LDAPSSLSessionInfo *)sei.seinfo_appdata; 656*7c478bd9Sstevel@tonic-gate if ( NULL == ssip ) { 657*7c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); 658*7c478bd9Sstevel@tonic-gate return( -1 ); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate ssip->lssei_certnickname = PL_strdup( certnickname ); 661*7c478bd9Sstevel@tonic-gate ssip->lssei_keypasswd = PL_strdup( keypasswd ); 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate if ( NULL == ssip->lssei_certnickname || NULL == ssip->lssei_keypasswd ) { 664*7c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL ); 665*7c478bd9Sstevel@tonic-gate return( -1 ); 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate if ( check_clientauth_nicknames_and_passwd( ld, ssip ) != 0 ) { 669*7c478bd9Sstevel@tonic-gate return( -1 ); 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate /* 673*7c478bd9Sstevel@tonic-gate * replace standard SSL CONNECT function with client auth aware one 674*7c478bd9Sstevel@tonic-gate */ 675*7c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns)); 676*7c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; 677*7c478bd9Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) 678*7c478bd9Sstevel@tonic-gate != 0 ) { 679*7c478bd9Sstevel@tonic-gate return( -1 ); 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate if ( iofns.lextiof_connect != ldapssl_connect ) { 683*7c478bd9Sstevel@tonic-gate /* standard SSL setup has not done */ 684*7c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); 685*7c478bd9Sstevel@tonic-gate return( -1 ); 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate iofns.lextiof_connect = ldapssl_clientauth_connect; 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) 691*7c478bd9Sstevel@tonic-gate != 0 ) { 692*7c478bd9Sstevel@tonic-gate return( -1 ); 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate return( 0 ); 696*7c478bd9Sstevel@tonic-gate #endif 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate static void 701*7c478bd9Sstevel@tonic-gate ldapssl_free_session_info( LDAPSSLSessionInfo **ssipp ) 702*7c478bd9Sstevel@tonic-gate { 703*7c478bd9Sstevel@tonic-gate if ( NULL != ssipp && NULL != *ssipp ) { 704*7c478bd9Sstevel@tonic-gate if ( NULL != (*ssipp)->lssei_certnickname ) { 705*7c478bd9Sstevel@tonic-gate PL_strfree( (*ssipp)->lssei_certnickname ); 706*7c478bd9Sstevel@tonic-gate (*ssipp)->lssei_certnickname = NULL; 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate if ( NULL != (*ssipp)->lssei_keypasswd ) { 709*7c478bd9Sstevel@tonic-gate PL_strfree( (*ssipp)->lssei_keypasswd ); 710*7c478bd9Sstevel@tonic-gate (*ssipp)->lssei_keypasswd = NULL; 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate PR_Free( *ssipp ); 713*7c478bd9Sstevel@tonic-gate *ssipp = NULL; 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate static void 719*7c478bd9Sstevel@tonic-gate ldapssl_free_socket_info( LDAPSSLSocketInfo **soipp ) 720*7c478bd9Sstevel@tonic-gate { 721*7c478bd9Sstevel@tonic-gate if ( NULL != soipp && NULL != *soipp ) { 722*7c478bd9Sstevel@tonic-gate PR_Free( *soipp ); 723*7c478bd9Sstevel@tonic-gate *soipp = NULL; 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate /* this function provides cert authentication. This is called during 729*7c478bd9Sstevel@tonic-gate * the SSL_Handshake process. Once the cert has been retrieved from 730*7c478bd9Sstevel@tonic-gate * the server, the it is checked, using VerifyCertNow(), then 731*7c478bd9Sstevel@tonic-gate * the cn is checked against the host name, set with SSL_SetURL() 732*7c478bd9Sstevel@tonic-gate */ 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate static int 735*7c478bd9Sstevel@tonic-gate ldapssl_AuthCertificate(void *sessionarg, PRFileDesc *fd, PRBool checkSig, 736*7c478bd9Sstevel@tonic-gate PRBool isServer) 737*7c478bd9Sstevel@tonic-gate { 738*7c478bd9Sstevel@tonic-gate SECStatus rv = SECFailure; 739*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip; 740*7c478bd9Sstevel@tonic-gate CERTCertificate *cert; 741*7c478bd9Sstevel@tonic-gate SECCertUsage certUsage; 742*7c478bd9Sstevel@tonic-gate char *hostname = (char *)0; 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate if (!sessionarg || !socket) 745*7c478bd9Sstevel@tonic-gate return rv; 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sessionarg; 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate if (LDAPSSL_AUTH_WEAK == sseip->lssei_ssl_strength ) { /* no check */ 750*7c478bd9Sstevel@tonic-gate return SECSuccess; 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate if ( isServer ) { 754*7c478bd9Sstevel@tonic-gate certUsage = certUsageSSLClient; 755*7c478bd9Sstevel@tonic-gate } else { 756*7c478bd9Sstevel@tonic-gate certUsage = certUsageSSLServer; 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate cert = SSL_PeerCertificate( fd ); 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate rv = CERT_VerifyCertNow(sseip->lssei_certdbh, cert, checkSig, 761*7c478bd9Sstevel@tonic-gate certUsage, NULL); 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate if ( rv != SECSuccess || isServer ) 764*7c478bd9Sstevel@tonic-gate return rv; 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate if ( LDAPSSL_AUTH_CNCHECK == sseip->lssei_ssl_strength ) 767*7c478bd9Sstevel@tonic-gate { 768*7c478bd9Sstevel@tonic-gate /* cert is OK. This is the client side of an SSL connection. 769*7c478bd9Sstevel@tonic-gate * Now check the name field in the cert against the desired hostname. 770*7c478bd9Sstevel@tonic-gate * NB: This is our only defense against Man-In-The-Middle (MITM) 771*7c478bd9Sstevel@tonic-gate * attacks! 772*7c478bd9Sstevel@tonic-gate */ 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate hostname = SSL_RevealURL( fd ); 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate if (hostname && hostname[0]) { 777*7c478bd9Sstevel@tonic-gate rv = CERT_VerifyCertName(cert, hostname); 778*7c478bd9Sstevel@tonic-gate } else { 779*7c478bd9Sstevel@tonic-gate rv = SECFailure; 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate if (hostname) 782*7c478bd9Sstevel@tonic-gate PORT_Free(hostname); 783*7c478bd9Sstevel@tonic-gate if (rv != SECSuccess) 784*7c478bd9Sstevel@tonic-gate PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); 785*7c478bd9Sstevel@tonic-gate } 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate return((int)rv); 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate /* 792*7c478bd9Sstevel@tonic-gate * called during SSL client auth. when server wants our cert and key. 793*7c478bd9Sstevel@tonic-gate * return 0 if we succeeded and set *pRetCert and *pRetKey, -1 otherwise. 794*7c478bd9Sstevel@tonic-gate * if -1 is returned SSL will proceed without sending a cert. 795*7c478bd9Sstevel@tonic-gate */ 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate static int 798*7c478bd9Sstevel@tonic-gate get_clientauth_data( void *sessionarg, PRFileDesc *prfd, 799*7c478bd9Sstevel@tonic-gate CERTDistNames *caNames, CERTCertificate **pRetCert, 800*7c478bd9Sstevel@tonic-gate SECKEYPrivateKey **pRetKey ) 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate { 803*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip; 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate if (( ssip = (LDAPSSLSessionInfo *)sessionarg ) == NULL ) { 806*7c478bd9Sstevel@tonic-gate return( -1 ); /* client auth. not enabled */ 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate return( get_keyandcert( ssip, pRetCert, pRetKey, NULL )); 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate static int 813*7c478bd9Sstevel@tonic-gate get_keyandcert( LDAPSSLSessionInfo *ssip, 814*7c478bd9Sstevel@tonic-gate CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey, 815*7c478bd9Sstevel@tonic-gate char **errmsgp ) 816*7c478bd9Sstevel@tonic-gate { 817*7c478bd9Sstevel@tonic-gate CERTCertificate *cert; 818*7c478bd9Sstevel@tonic-gate SECKEYPrivateKey *key; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate if (( cert = PK11_FindCertFromNickname( ssip->lssei_certnickname, NULL )) 821*7c478bd9Sstevel@tonic-gate == NULL ) { 822*7c478bd9Sstevel@tonic-gate if ( errmsgp != NULL ) { 823*7c478bd9Sstevel@tonic-gate *errmsgp = dgettext(TEXT_DOMAIN, "unable to find certificate"); 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate return( -1 ); 826*7c478bd9Sstevel@tonic-gate } 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate { 829*7c478bd9Sstevel@tonic-gate PK11_SetPasswordFunc( get_keypassword ); 830*7c478bd9Sstevel@tonic-gate } 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate if (( key = PK11_FindKeyByAnyCert( cert, (void *)ssip )) == NULL ) { 835*7c478bd9Sstevel@tonic-gate CERT_DestroyCertificate( cert ); 836*7c478bd9Sstevel@tonic-gate if ( errmsgp != NULL ) { 837*7c478bd9Sstevel@tonic-gate *errmsgp = dgettext(TEXT_DOMAIN, "bad key or key password"); 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate return( -1 ); 840*7c478bd9Sstevel@tonic-gate } 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate *pRetCert = cert; 843*7c478bd9Sstevel@tonic-gate *pRetKey = key; 844*7c478bd9Sstevel@tonic-gate return( 0 ); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate /* 849*7c478bd9Sstevel@tonic-gate * This function returns the password to NSS. 850*7c478bd9Sstevel@tonic-gate * This function is enable through PK11_SetPasswordFunc 851*7c478bd9Sstevel@tonic-gate * only if pkcs functions are not being used. 852*7c478bd9Sstevel@tonic-gate */ 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate static char * 855*7c478bd9Sstevel@tonic-gate get_keypassword( PK11SlotInfo *slot, PRBool retry, void *sessionarg ) 856*7c478bd9Sstevel@tonic-gate { 857*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip; 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate if ( retry) 860*7c478bd9Sstevel@tonic-gate return (NULL); 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate ssip = (LDAPSSLSessionInfo *)sessionarg; 863*7c478bd9Sstevel@tonic-gate if ( NULL == ssip ) { 864*7c478bd9Sstevel@tonic-gate return( NULL ); 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate return( ssip->lssei_keypasswd ); 868*7c478bd9Sstevel@tonic-gate } 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate /* 872*7c478bd9Sstevel@tonic-gate * performs some basic checks on clientauth cert and key/password 873*7c478bd9Sstevel@tonic-gate * 874*7c478bd9Sstevel@tonic-gate * XXXmcs: could perform additional checks... see servers/slapd/ssl.c 875*7c478bd9Sstevel@tonic-gate * 1) check expiration 876*7c478bd9Sstevel@tonic-gate * 2) check that public key in cert matches private key 877*7c478bd9Sstevel@tonic-gate * see ns/netsite/ldap/servers/slapd/ssl.c:slapd_ssl_init() for example code. 878*7c478bd9Sstevel@tonic-gate */ 879*7c478bd9Sstevel@tonic-gate static int 880*7c478bd9Sstevel@tonic-gate check_clientauth_nicknames_and_passwd( LDAP *ld, LDAPSSLSessionInfo *ssip ) 881*7c478bd9Sstevel@tonic-gate { 882*7c478bd9Sstevel@tonic-gate char *errmsg = NULL; 883*7c478bd9Sstevel@tonic-gate CERTCertificate *cert = NULL; 884*7c478bd9Sstevel@tonic-gate SECKEYPrivateKey *key = NULL; 885*7c478bd9Sstevel@tonic-gate int rv; 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate rv = get_keyandcert( ssip, &cert, &key, &errmsg ); 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate if ( rv != 0 ) { 890*7c478bd9Sstevel@tonic-gate if ( errmsg != NULL ) { 891*7c478bd9Sstevel@tonic-gate errmsg = strdup( errmsg ); 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, errmsg ); 894*7c478bd9Sstevel@tonic-gate return( -1 ); 895*7c478bd9Sstevel@tonic-gate } 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate if ( cert != NULL ) { 898*7c478bd9Sstevel@tonic-gate CERT_DestroyCertificate( cert ); 899*7c478bd9Sstevel@tonic-gate } 900*7c478bd9Sstevel@tonic-gate if ( key != NULL ) { 901*7c478bd9Sstevel@tonic-gate SECKEY_DestroyPrivateKey( key ); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate return( 0 ); 904*7c478bd9Sstevel@tonic-gate } 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate #if 0 /* NOT_NEEDED_IN_LIBLDAP */ 908*7c478bd9Sstevel@tonic-gate /* there are patches and kludges. this is both. force some linkers to 909*7c478bd9Sstevel@tonic-gate * link this stuff in 910*7c478bd9Sstevel@tonic-gate */ 911*7c478bd9Sstevel@tonic-gate int stubs_o_stuff( void ) 912*7c478bd9Sstevel@tonic-gate { 913*7c478bd9Sstevel@tonic-gate PRExplodedTime exploded; 914*7c478bd9Sstevel@tonic-gate PLArenaPool pool; 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate const char *name ="t"; 917*7c478bd9Sstevel@tonic-gate PRUint32 size = 0, align = 0; 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate PR_ImplodeTime( &exploded ); 920*7c478bd9Sstevel@tonic-gate PL_InitArenaPool( &pool, name, size, align); 921*7c478bd9Sstevel@tonic-gate PR_Cleanup(); 922*7c478bd9Sstevel@tonic-gate PR_fprintf((PRFileDesc*)stderr, "Bad IDEA!!"); 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate return 0; 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate } 927*7c478bd9Sstevel@tonic-gate #endif /* NOT_NEEDED_IN_LIBLDAP */ 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate /* 931*7c478bd9Sstevel@tonic-gate * Import the file descriptor corresponding to the socket of an already 932*7c478bd9Sstevel@tonic-gate * open LDAP connection into SSL, and update the socket and session 933*7c478bd9Sstevel@tonic-gate * information accordingly. 934*7c478bd9Sstevel@tonic-gate */ 935*7c478bd9Sstevel@tonic-gate int ldapssl_import_fd ( LDAP *ld, int secure ) 936*7c478bd9Sstevel@tonic-gate { 937*7c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei; 938*7c478bd9Sstevel@tonic-gate PRLDAPSocketInfo soi; 939*7c478bd9Sstevel@tonic-gate LDAPSSLSocketInfo *ssoip = NULL; 940*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip; 941*7c478bd9Sstevel@tonic-gate PRFileDesc *sslfd = NULL; 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate /* 945*7c478bd9Sstevel@tonic-gate * Retrieve session info. so we can store a pointer to our session info. 946*7c478bd9Sstevel@tonic-gate * in our socket info. later. 947*7c478bd9Sstevel@tonic-gate */ 948*7c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof(sei)); 949*7c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE; 950*7c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) { 951*7c478bd9Sstevel@tonic-gate return( -1 ); 952*7c478bd9Sstevel@tonic-gate } 953*7c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata; 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate /* 957*7c478bd9Sstevel@tonic-gate * Retrieve socket info. so we have the PRFileDesc. 958*7c478bd9Sstevel@tonic-gate */ 959*7c478bd9Sstevel@tonic-gate memset( &soi, 0, sizeof(soi)); 960*7c478bd9Sstevel@tonic-gate soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE; 961*7c478bd9Sstevel@tonic-gate if ( prldap_get_default_socket_info( ld, &soi ) != LDAP_SUCCESS ) { 962*7c478bd9Sstevel@tonic-gate return( -1 ); 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate /* 966*7c478bd9Sstevel@tonic-gate * Allocate a structure to hold our socket-specific data. 967*7c478bd9Sstevel@tonic-gate */ 968*7c478bd9Sstevel@tonic-gate if ( NULL == ( ssoip = PR_Calloc( 1, sizeof( LDAPSSLSocketInfo )))) { 969*7c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error; 970*7c478bd9Sstevel@tonic-gate } 971*7c478bd9Sstevel@tonic-gate ssoip->soi_sessioninfo = sseip; 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate /* 974*7c478bd9Sstevel@tonic-gate * Add SSL layer and let the standard NSPR to LDAP layer and enable SSL. 975*7c478bd9Sstevel@tonic-gate */ 976*7c478bd9Sstevel@tonic-gate if (( sslfd = SSL_ImportFD( NULL, soi.soinfo_prfd )) == NULL ) { 977*7c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error; 978*7c478bd9Sstevel@tonic-gate } 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate if ( SSL_OptionSet( sslfd, SSL_SECURITY, secure ) != SECSuccess || 981*7c478bd9Sstevel@tonic-gate SSL_OptionSet( sslfd, SSL_HANDSHAKE_AS_CLIENT, secure ) 982*7c478bd9Sstevel@tonic-gate != SECSuccess || ( secure && SSL_ResetHandshake( sslfd, 983*7c478bd9Sstevel@tonic-gate PR_FALSE ) != SECSuccess )) { 984*7c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error; 985*7c478bd9Sstevel@tonic-gate } 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate /* 988*7c478bd9Sstevel@tonic-gate * Let the standard NSPR to LDAP layer know about the new socket and 989*7c478bd9Sstevel@tonic-gate * our own socket-specific data. 990*7c478bd9Sstevel@tonic-gate */ 991*7c478bd9Sstevel@tonic-gate soi.soinfo_prfd = sslfd; 992*7c478bd9Sstevel@tonic-gate soi.soinfo_appdata = (void *)ssoip; 993*7c478bd9Sstevel@tonic-gate if ( prldap_set_default_socket_info( ld, &soi ) != LDAP_SUCCESS ) { 994*7c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error; 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate /* 998*7c478bd9Sstevel@tonic-gate * Install certificate hook function. 999*7c478bd9Sstevel@tonic-gate */ 1000*7c478bd9Sstevel@tonic-gate if ( SSL_AuthCertificateHook( soi.soinfo_prfd, 1001*7c478bd9Sstevel@tonic-gate (SSLAuthCertificate)ldapssl_AuthCertificate, 1002*7c478bd9Sstevel@tonic-gate (void *)CERT_GetDefaultCertDB()) != 0 ) { 1003*7c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error; 1004*7c478bd9Sstevel@tonic-gate } 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate if ( SSL_GetClientAuthDataHook( soi.soinfo_prfd, 1007*7c478bd9Sstevel@tonic-gate get_clientauth_data, sseip->lssei_certnickname ? sseip : NULL ) 1008*7c478bd9Sstevel@tonic-gate != 0 ) { 1009*7c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error; 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate return 0; 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate reset_socket_and_exit_with_error: 1015*7c478bd9Sstevel@tonic-gate if ( NULL != sslfd ) { 1016*7c478bd9Sstevel@tonic-gate /* 1017*7c478bd9Sstevel@tonic-gate * "Unimport" the socket from SSL, i.e. get rid of the upper layer of 1018*7c478bd9Sstevel@tonic-gate * the file descriptor stack, which represents SSL. 1019*7c478bd9Sstevel@tonic-gate */ 1020*7c478bd9Sstevel@tonic-gate soi.soinfo_prfd = sslfd; 1021*7c478bd9Sstevel@tonic-gate sslfd = PR_PopIOLayer( soi.soinfo_prfd, PR_TOP_IO_LAYER ); 1022*7c478bd9Sstevel@tonic-gate sslfd->dtor( sslfd ); 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate if ( NULL != ssoip ) { 1025*7c478bd9Sstevel@tonic-gate ldapssl_free_socket_info( &ssoip ); 1026*7c478bd9Sstevel@tonic-gate soi.soinfo_appdata = NULL; 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate prldap_set_default_socket_info( ld, &soi ); 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate return( -1 ); 1031*7c478bd9Sstevel@tonic-gate } 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate 1034*7c478bd9Sstevel@tonic-gate /* 1035*7c478bd9Sstevel@tonic-gate * Reset an LDAP session from SSL to a non-secure status. 1036*7c478bd9Sstevel@tonic-gate * Basically, this function undoes the work done by ldapssl_install_routines. 1037*7c478bd9Sstevel@tonic-gate */ 1038*7c478bd9Sstevel@tonic-gate int ldapssl_reset_to_nonsecure ( LDAP *ld ) 1039*7c478bd9Sstevel@tonic-gate { 1040*7c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei; 1041*7c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip; 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns; 1044*7c478bd9Sstevel@tonic-gate int rc = 0; 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate /* 1047*7c478bd9Sstevel@tonic-gate * Retrieve session info. 1048*7c478bd9Sstevel@tonic-gate */ 1049*7c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof(sei)); 1050*7c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE; 1051*7c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) { 1052*7c478bd9Sstevel@tonic-gate return( -1 ); 1053*7c478bd9Sstevel@tonic-gate } 1054*7c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata; 1055*7c478bd9Sstevel@tonic-gate 1056*7c478bd9Sstevel@tonic-gate if ( sseip != NULL ) { 1057*7c478bd9Sstevel@tonic-gate /* 1058*7c478bd9Sstevel@tonic-gate * Reset the standard extended io functions. 1059*7c478bd9Sstevel@tonic-gate */ 1060*7c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns)); 1061*7c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; 1062*7c478bd9Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) 1063*7c478bd9Sstevel@tonic-gate < 0) { 1064*7c478bd9Sstevel@tonic-gate rc = -1; 1065*7c478bd9Sstevel@tonic-gate goto free_session_info; 1066*7c478bd9Sstevel@tonic-gate } 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate /* reset socket, connect, and ioctl */ 1069*7c478bd9Sstevel@tonic-gate iofns.lextiof_connect = sseip->lssei_std_functions.lssf_connect_fn; 1070*7c478bd9Sstevel@tonic-gate iofns.lextiof_close = sseip->lssei_std_functions.lssf_close_fn; 1071*7c478bd9Sstevel@tonic-gate iofns.lextiof_disposehandle = 1072*7c478bd9Sstevel@tonic-gate sseip->lssei_std_functions.lssf_disposehdl_fn; 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) 1075*7c478bd9Sstevel@tonic-gate < 0) { 1076*7c478bd9Sstevel@tonic-gate rc = -1; 1077*7c478bd9Sstevel@tonic-gate goto free_session_info; 1078*7c478bd9Sstevel@tonic-gate } 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate free_session_info: 1081*7c478bd9Sstevel@tonic-gate ldapssl_free_session_info( &sseip ); 1082*7c478bd9Sstevel@tonic-gate sei.seinfo_appdata = NULL; 1083*7c478bd9Sstevel@tonic-gate if ( prldap_set_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) { 1084*7c478bd9Sstevel@tonic-gate rc = -1; 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate } /* if ( sseip && *sseip ) */ 1087*7c478bd9Sstevel@tonic-gate 1088*7c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_OFF ) < 0 ) { 1089*7c478bd9Sstevel@tonic-gate return (-1); 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate return rc; 1093*7c478bd9Sstevel@tonic-gate } 1094*7c478bd9Sstevel@tonic-gate 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 1097*7c478bd9Sstevel@tonic-gate static void 1098*7c478bd9Sstevel@tonic-gate _nss_initf_ipnodes(nss_db_params_t *p) 1099*7c478bd9Sstevel@tonic-gate { 1100*7c478bd9Sstevel@tonic-gate static char *no_service = ""; 1101*7c478bd9Sstevel@tonic-gate 1102*7c478bd9Sstevel@tonic-gate p->name = NSS_DBNAM_IPNODES; 1103*7c478bd9Sstevel@tonic-gate p->flags |= NSS_USE_DEFAULT_CONFIG; 1104*7c478bd9Sstevel@tonic-gate p->default_config = host_service == NULL ? no_service : host_service; 1105*7c478bd9Sstevel@tonic-gate } 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate static void 1108*7c478bd9Sstevel@tonic-gate _nss_initf_hosts(nss_db_params_t *p) 1109*7c478bd9Sstevel@tonic-gate { 1110*7c478bd9Sstevel@tonic-gate static char *no_service = ""; 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate p->name = NSS_DBNAM_HOSTS; 1113*7c478bd9Sstevel@tonic-gate p->flags |= NSS_USE_DEFAULT_CONFIG; 1114*7c478bd9Sstevel@tonic-gate p->default_config = host_service == NULL ? no_service : host_service; 1115*7c478bd9Sstevel@tonic-gate } 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate static struct hostent * 1118*7c478bd9Sstevel@tonic-gate _switch_gethostbyaddr_r(const char *addr, int len, int type, 1119*7c478bd9Sstevel@tonic-gate struct hostent *result, char *buffer, int buflen, 1120*7c478bd9Sstevel@tonic-gate int *h_errnop) 1121*7c478bd9Sstevel@tonic-gate { 1122*7c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 1123*7c478bd9Sstevel@tonic-gate nss_status_t res; 1124*7c478bd9Sstevel@tonic-gate int (*str2ent)(); 1125*7c478bd9Sstevel@tonic-gate void (*nss_initf)(); 1126*7c478bd9Sstevel@tonic-gate nss_db_root_t *nss_db_root; 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate if (AF_INET == type) { 1129*7c478bd9Sstevel@tonic-gate str2ent = str2hostent; 1130*7c478bd9Sstevel@tonic-gate nss_initf = _nss_initf_hosts; 1131*7c478bd9Sstevel@tonic-gate nss_db_root = &db_root_hosts; 1132*7c478bd9Sstevel@tonic-gate } else if (AF_INET6 == type) { 1133*7c478bd9Sstevel@tonic-gate str2ent = str2hostent6; 1134*7c478bd9Sstevel@tonic-gate nss_initf = _nss_initf_ipnodes; 1135*7c478bd9Sstevel@tonic-gate nss_db_root = &db_root_ipnodes; 1136*7c478bd9Sstevel@tonic-gate } else { 1137*7c478bd9Sstevel@tonic-gate return NULL; 1138*7c478bd9Sstevel@tonic-gate } 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2ent); 1141*7c478bd9Sstevel@tonic-gate 1142*7c478bd9Sstevel@tonic-gate arg.key.hostaddr.addr = addr; 1143*7c478bd9Sstevel@tonic-gate arg.key.hostaddr.len = len; 1144*7c478bd9Sstevel@tonic-gate arg.key.hostaddr.type = type; 1145*7c478bd9Sstevel@tonic-gate arg.stayopen = 0; 1146*7c478bd9Sstevel@tonic-gate 1147*7c478bd9Sstevel@tonic-gate res = nss_search(nss_db_root, nss_initf, 1148*7c478bd9Sstevel@tonic-gate NSS_DBOP_HOSTS_BYADDR, &arg); 1149*7c478bd9Sstevel@tonic-gate arg.status = res; 1150*7c478bd9Sstevel@tonic-gate *h_errnop = arg.h_errno; 1151*7c478bd9Sstevel@tonic-gate return (struct hostent *)NSS_XbyY_FINI(&arg); 1152*7c478bd9Sstevel@tonic-gate } 1153*7c478bd9Sstevel@tonic-gate 1154*7c478bd9Sstevel@tonic-gate /* 1155*7c478bd9Sstevel@tonic-gate * ns_gethostbyaddr is used to be a substitute gethostbyaddr for 1156*7c478bd9Sstevel@tonic-gate * libldap when ssl will need to determine the fully qualified 1157*7c478bd9Sstevel@tonic-gate * host name from an address when it is unsafe to use the normal 1158*7c478bd9Sstevel@tonic-gate * nameservice functions. 1159*7c478bd9Sstevel@tonic-gate * 1160*7c478bd9Sstevel@tonic-gate * Note that the ldap name service resolver calls this with the address as 1161*7c478bd9Sstevel@tonic-gate * a character string - which we must convert into address form. 1162*7c478bd9Sstevel@tonic-gate */ 1163*7c478bd9Sstevel@tonic-gate 1164*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1165*7c478bd9Sstevel@tonic-gate static LDAPHostEnt * 1166*7c478bd9Sstevel@tonic-gate ns_gethostbyaddr(const char *addr, int len, int type, 1167*7c478bd9Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp, 1168*7c478bd9Sstevel@tonic-gate void *extradata) 1169*7c478bd9Sstevel@tonic-gate { 1170*7c478bd9Sstevel@tonic-gate LDAPHostEnt *ldap_hent; 1171*7c478bd9Sstevel@tonic-gate int h_errno; 1172*7c478bd9Sstevel@tonic-gate struct hostent h_ent; 1173*7c478bd9Sstevel@tonic-gate struct hostent *h_e = NULL; 1174*7c478bd9Sstevel@tonic-gate struct in_addr a; 1175*7c478bd9Sstevel@tonic-gate struct in6_addr a6; 1176*7c478bd9Sstevel@tonic-gate int inet_error; /* error returned by inet_pton */ 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate if (addr == NULL || result == NULL || buffer == NULL || 1180*7c478bd9Sstevel@tonic-gate (type != AF_INET && type != AF_INET6)) 1181*7c478bd9Sstevel@tonic-gate return (NULL); 1182*7c478bd9Sstevel@tonic-gate 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate (void) memset(&h_ent, 0, sizeof (h_ent)); 1185*7c478bd9Sstevel@tonic-gate 1186*7c478bd9Sstevel@tonic-gate if (AF_INET == type) { 1187*7c478bd9Sstevel@tonic-gate if (inet_pton(type, addr, &a.s_addr) == 1) { 1188*7c478bd9Sstevel@tonic-gate h_e = _switch_gethostbyaddr_r((char *)&a, 1189*7c478bd9Sstevel@tonic-gate sizeof (a.s_addr), type, &h_ent, 1190*7c478bd9Sstevel@tonic-gate buffer, buflen, &h_errno); 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate } else if (AF_INET6 == type) { 1193*7c478bd9Sstevel@tonic-gate if (inet_pton(type, addr, &a6.s6_addr) == 1) { 1194*7c478bd9Sstevel@tonic-gate h_e = _switch_gethostbyaddr_r((char *)&a6, 1195*7c478bd9Sstevel@tonic-gate sizeof (a6.s6_addr), type, &h_ent, 1196*7c478bd9Sstevel@tonic-gate buffer, buflen, &h_errno); 1197*7c478bd9Sstevel@tonic-gate } 1198*7c478bd9Sstevel@tonic-gate } 1199*7c478bd9Sstevel@tonic-gate 1200*7c478bd9Sstevel@tonic-gate if (h_e == NULL) { 1201*7c478bd9Sstevel@tonic-gate ldap_hent = NULL; 1202*7c478bd9Sstevel@tonic-gate } else { 1203*7c478bd9Sstevel@tonic-gate (void) memset(result, 0, sizeof (LDAPHostEnt)); 1204*7c478bd9Sstevel@tonic-gate ldap_hent = result; 1205*7c478bd9Sstevel@tonic-gate result->ldaphe_name = h_e->h_name; 1206*7c478bd9Sstevel@tonic-gate result->ldaphe_aliases = h_e->h_aliases; 1207*7c478bd9Sstevel@tonic-gate result->ldaphe_addrtype = h_e->h_addrtype; 1208*7c478bd9Sstevel@tonic-gate result->ldaphe_length = h_e->h_length; 1209*7c478bd9Sstevel@tonic-gate result->ldaphe_addr_list = h_e->h_addr_list; 1210*7c478bd9Sstevel@tonic-gate } 1211*7c478bd9Sstevel@tonic-gate return (ldap_hent); 1212*7c478bd9Sstevel@tonic-gate } 1213*7c478bd9Sstevel@tonic-gate 1214*7c478bd9Sstevel@tonic-gate /* 1215*7c478bd9Sstevel@tonic-gate * ldapssl_install_gethostbyaddr attempts to prevent recursion in 1216*7c478bd9Sstevel@tonic-gate * gethostbyaddr calls when an ip address is given to ssl. This ip address 1217*7c478bd9Sstevel@tonic-gate * must be resolved to a host name. 1218*7c478bd9Sstevel@tonic-gate * 1219*7c478bd9Sstevel@tonic-gate * For example, libsldap cannot use LDAP to resolve this address to a 1220*7c478bd9Sstevel@tonic-gate * name because of recursion. The caller is instructing libldap to skip 1221*7c478bd9Sstevel@tonic-gate * the specified name service when resolving addresses for the specified 1222*7c478bd9Sstevel@tonic-gate * ldap connection. 1223*7c478bd9Sstevel@tonic-gate * 1224*7c478bd9Sstevel@tonic-gate * Currently only ldap and dns name services always return fully qualified 1225*7c478bd9Sstevel@tonic-gate * names. The other name services (files, nis, and nisplus) will returned 1226*7c478bd9Sstevel@tonic-gate * fully qualified names if the host names are stored as fully qualified names 1227*7c478bd9Sstevel@tonic-gate * in these name services. 1228*7c478bd9Sstevel@tonic-gate * 1229*7c478bd9Sstevel@tonic-gate * Note: 1230*7c478bd9Sstevel@tonic-gate * 1231*7c478bd9Sstevel@tonic-gate * Since host_service applies to all connections, calling 1232*7c478bd9Sstevel@tonic-gate * ldapssl_install_gethostbyaddr with different name services to 1233*7c478bd9Sstevel@tonic-gate * skip will lead to unpredictable results. 1234*7c478bd9Sstevel@tonic-gate * 1235*7c478bd9Sstevel@tonic-gate * Returns: 1236*7c478bd9Sstevel@tonic-gate * 0 if success 1237*7c478bd9Sstevel@tonic-gate * -1 if failure 1238*7c478bd9Sstevel@tonic-gate */ 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate int 1241*7c478bd9Sstevel@tonic-gate ldapssl_install_gethostbyaddr(LDAP *ld, const char *skip) 1242*7c478bd9Sstevel@tonic-gate { 1243*7c478bd9Sstevel@tonic-gate enum __nsw_parse_err pserr; 1244*7c478bd9Sstevel@tonic-gate struct __nsw_switchconfig *conf; 1245*7c478bd9Sstevel@tonic-gate struct __nsw_lookup *lkp; 1246*7c478bd9Sstevel@tonic-gate struct ldap_dns_fns dns_fns; 1247*7c478bd9Sstevel@tonic-gate char *name_list = NULL; 1248*7c478bd9Sstevel@tonic-gate char *tmp; 1249*7c478bd9Sstevel@tonic-gate const char *name; 1250*7c478bd9Sstevel@tonic-gate int len; 1251*7c478bd9Sstevel@tonic-gate boolean_t got_skip = B_FALSE; 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate /* 1254*7c478bd9Sstevel@tonic-gate * db_root_hosts.lock mutex is used to ensure that the name list 1255*7c478bd9Sstevel@tonic-gate * is not in use by the name service switch while we are updating 1256*7c478bd9Sstevel@tonic-gate * the host_service 1257*7c478bd9Sstevel@tonic-gate */ 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&db_root_hosts.lock); 1260*7c478bd9Sstevel@tonic-gate conf = __nsw_getconfig("hosts", &pserr); 1261*7c478bd9Sstevel@tonic-gate if (conf == NULL) { 1262*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock); 1263*7c478bd9Sstevel@tonic-gate return (0); 1264*7c478bd9Sstevel@tonic-gate } 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate /* check for ldap and count other backends */ 1267*7c478bd9Sstevel@tonic-gate for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) { 1268*7c478bd9Sstevel@tonic-gate name = lkp->service_name; 1269*7c478bd9Sstevel@tonic-gate if (strcmp(name, skip) == 0) { 1270*7c478bd9Sstevel@tonic-gate got_skip = B_TRUE; 1271*7c478bd9Sstevel@tonic-gate continue; 1272*7c478bd9Sstevel@tonic-gate } 1273*7c478bd9Sstevel@tonic-gate if (name_list == NULL) 1274*7c478bd9Sstevel@tonic-gate name_list = strdup(name); 1275*7c478bd9Sstevel@tonic-gate else { 1276*7c478bd9Sstevel@tonic-gate len = strlen(name_list); 1277*7c478bd9Sstevel@tonic-gate tmp = realloc(name_list, len + strlen(name) + 2); 1278*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 1279*7c478bd9Sstevel@tonic-gate free(name_list); 1280*7c478bd9Sstevel@tonic-gate name_list = NULL; 1281*7c478bd9Sstevel@tonic-gate } else { 1282*7c478bd9Sstevel@tonic-gate name_list = tmp; 1283*7c478bd9Sstevel@tonic-gate name_list[len++] = ' '; 1284*7c478bd9Sstevel@tonic-gate (void) strcpy(name_list+len, name); 1285*7c478bd9Sstevel@tonic-gate } 1286*7c478bd9Sstevel@tonic-gate } 1287*7c478bd9Sstevel@tonic-gate if (name_list == NULL) { /* alloc error */ 1288*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock); 1289*7c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf); 1290*7c478bd9Sstevel@tonic-gate return (-1); 1291*7c478bd9Sstevel@tonic-gate } 1292*7c478bd9Sstevel@tonic-gate } 1293*7c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf); 1294*7c478bd9Sstevel@tonic-gate if (!got_skip) { 1295*7c478bd9Sstevel@tonic-gate /* 1296*7c478bd9Sstevel@tonic-gate * Since skip name service not used for hosts, we do not need 1297*7c478bd9Sstevel@tonic-gate * to install our private address resolution function 1298*7c478bd9Sstevel@tonic-gate */ 1299*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock); 1300*7c478bd9Sstevel@tonic-gate if (name_list != NULL) 1301*7c478bd9Sstevel@tonic-gate free(name_list); 1302*7c478bd9Sstevel@tonic-gate return (0); 1303*7c478bd9Sstevel@tonic-gate } 1304*7c478bd9Sstevel@tonic-gate if (host_service != NULL) 1305*7c478bd9Sstevel@tonic-gate free(host_service); 1306*7c478bd9Sstevel@tonic-gate host_service = name_list; 1307*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock); 1308*7c478bd9Sstevel@tonic-gate 1309*7c478bd9Sstevel@tonic-gate if (ldap_get_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0) 1310*7c478bd9Sstevel@tonic-gate return (-1); 1311*7c478bd9Sstevel@tonic-gate dns_fns.lddnsfn_gethostbyaddr = ns_gethostbyaddr; 1312*7c478bd9Sstevel@tonic-gate if (ldap_set_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0) 1313*7c478bd9Sstevel@tonic-gate return (-1); 1314*7c478bd9Sstevel@tonic-gate return (0); 1315*7c478bd9Sstevel@tonic-gate } 1316*7c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 1317*7c478bd9Sstevel@tonic-gate #endif /* NET_SSL */ 1318