#if defined(NET_SSL)
#if defined( _WINDOWS )
#include <windows.h>
#endif
#ifdef OSF1V4D
#ifndef __STDC__
# define __STDC__
#endif
#endif
#include <errno.h>
#include <nspr.h>
#include <cert.h>
#include <key.h>
#include <ssl.h>
#include <sslproto.h>
#include <sslerr.h>
#include <prnetdb.h>
#include <ldap.h>
#include <ldappr.h>
#include <pk11func.h>
#ifdef _SOLARIS_SDK
#include "solaris-int.h"
#include <libintl.h>
#include <syslog.h>
#include <nsswitch.h>
#include <synch.h>
#include <nss_dbdefs.h>
#include <netinet/in.h>
#define HOST_BUF_SIZE 2048
#ifndef INADDR_NONE
#define INADDR_NONE (-1)
#endif
extern int
str2hostent(const char *instr, int lenstr, void *ent, char *buffer,
int buflen);
extern int
str2hostent6(const char *instr, int lenstr, void *ent, char *buffer,
int buflen);
extern LDAPHostEnt *
_ns_gethostbyaddr(LDAP *ld, const char *addr, int length, int type,
LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
void *extradata);
static char *host_service = NULL;
static DEFINE_NSS_DB_ROOT(db_root_hosts);
static DEFINE_NSS_DB_ROOT(db_root_ipnodes);
#endif
typedef struct ldapssl_std_functions {
LDAP_X_EXTIOF_CLOSE_CALLBACK *lssf_close_fn;
LDAP_X_EXTIOF_CONNECT_CALLBACK *lssf_connect_fn;
LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *lssf_disposehdl_fn;
} LDAPSSLStdFunctions;
typedef struct ldapssl_session_info {
int lssei_using_pcks_fns;
int lssei_ssl_strength;
char *lssei_certnickname;
char *lssei_keypasswd;
LDAPSSLStdFunctions lssei_std_functions;
CERTCertDBHandle *lssei_certdbh;
#ifdef _SOLARIS_SDK
LDAP *ld;
#endif
} LDAPSSLSessionInfo;
typedef struct ldapssl_socket_info {
LDAPSSLSessionInfo *soi_sessioninfo;
} LDAPSSLSocketInfo;
static int using_pkcs_functions = 0;
void set_using_pkcs_functions( int val )
{
using_pkcs_functions = val;
}
static void ldapssl_free_session_info( LDAPSSLSessionInfo **ssipp );
static void ldapssl_free_socket_info( LDAPSSLSocketInfo **soipp );
static int ldapssl_AuthCertificate(void *sessionarg, PRFileDesc *fd,
PRBool checkSig, PRBool isServer);
static int get_clientauth_data( void *sessionarg, PRFileDesc *prfd,
CERTDistNames *caNames, CERTCertificate **pRetCert,
SECKEYPrivateKey **pRetKey );
static int get_keyandcert( LDAPSSLSessionInfo *ssip,
CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey,
char **errmsgp );
static int check_clientauth_nicknames_and_passwd( LDAP *ld,
LDAPSSLSessionInfo *ssip );
static char *get_keypassword( PK11SlotInfo *slot, PRBool retry,
void *sessionarg );
#ifdef _SOLARIS_SDK
static int default_ssl_strength = LDAPSSL_AUTH_CNCHECK;
#else
static int default_ssl_strength = LDAPSSL_AUTH_CERT;
#endif
LDAP *
LDAP_CALL
ldapssl_init( const char *defhost, int defport, int defsecure )
{
LDAP *ld;
#ifndef LDAP_SSLIO_HOOKS
return( NULL );
#else
if (0 ==defport)
defport = LDAPS_PORT;
if (( ld = ldap_init( defhost, defport )) == NULL ) {
return( NULL );
}
if ( ldapssl_install_routines( ld ) < 0 || ldap_set_option( ld,
LDAP_OPT_SSL, defsecure ? LDAP_OPT_ON : LDAP_OPT_OFF ) != 0 ) {
PR_SetError( PR_UNKNOWN_ERROR, EINVAL );
ldap_unbind( ld );
return( NULL );
}
return( ld );
#endif
}
static int
ldapssl_close(int s, struct lextiof_socket_private *socketarg)
{
PRLDAPSocketInfo soi;
LDAPSSLSocketInfo *ssoip;
LDAPSSLSessionInfo *sseip;
memset( &soi, 0, sizeof(soi));
soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
if ( prldap_get_socket_info( s, socketarg, &soi ) != LDAP_SUCCESS ) {
return( -1 );
}
ssoip = (LDAPSSLSocketInfo *)soi.soinfo_appdata;
sseip = ssoip->soi_sessioninfo;
ldapssl_free_socket_info( (LDAPSSLSocketInfo **)&soi.soinfo_appdata );
return( (*(sseip->lssei_std_functions.lssf_close_fn))( s, socketarg ));
}
static int
do_ldapssl_connect(const char *hostlist, int defport, int timeout,
unsigned long options, struct lextiof_session_private *sessionarg,
struct lextiof_socket_private **socketargp, int clientauth )
{
int intfd = -1;
PRBool secure;
PRLDAPSessionInfo sei;
PRLDAPSocketInfo soi;
LDAPSSLSocketInfo *ssoip = NULL;
LDAPSSLSessionInfo *sseip;
PRFileDesc *sslfd = NULL;
#ifdef _SOLARIS_SDK
int port;
int parse_err;
char *host = NULL;
char *name;
struct ldap_x_hostlist_status
*status = NULL;
in_addr_t addr_ipv4;
in6_addr_t addr_ipv6;
char *host_buf;
LDAPHostEnt *hent;
LDAPHostEnt host_ent;
int stat;
int type;
#endif
if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) {
secure = PR_TRUE;
options &= ~LDAP_X_EXTIOF_OPT_SECURE;
} else {
secure = PR_FALSE;
}
memset( &sei, 0, sizeof(sei));
sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
if ( prldap_get_session_info( NULL, sessionarg, &sei ) != LDAP_SUCCESS ) {
return( -1 );
}
sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
intfd = (*(sseip->lssei_std_functions.lssf_connect_fn))( hostlist, defport,
timeout, options, sessionarg, socketargp
#ifdef _SOLARIS_SDK
, &host );
#else
);
#endif
if ( intfd < 0 ) {
return( intfd );
}
#ifdef _SOLARIS_SDK
if ( NULL == host ) {
goto close_socket_and_exit_with_error;
}
type = AF_UNSPEC;
if (strlen(host) < INET6_ADDRSTRLEN &&
inet_pton(AF_INET6, host, &addr_ipv6) == 1) {
type = AF_INET6;
} else if (strlen(host) < INET_ADDRSTRLEN &&
inet_pton(AF_INET, host, &addr_ipv4) == 1) {
type = AF_INET;
}
if (type == AF_INET || type == AF_INET6) {
host_buf = malloc(HOST_BUF_SIZE);
if (host_buf == NULL) {
goto close_socket_and_exit_with_error;
}
hent = _ns_gethostbyaddr(sseip->ld, host, strlen(host), type,
&host_ent, host_buf, HOST_BUF_SIZE, &stat, NULL);
if (hent == NULL) {
syslog(LOG_WARNING,
"libldap: do_ldapssl_connect: "
"Unable to resolve '%s'", host);
free(host_buf);
goto close_socket_and_exit_with_error;
}
else {
if (hent->ldaphe_name != NULL)
name = strdup(hent->ldaphe_name);
free(host_buf);
if (name == NULL)
goto close_socket_and_exit_with_error;
else
ldap_memfree(host); host = NULL;
host = name;
}
}
#endif
memset( &soi, 0, sizeof(soi));
soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
if ( prldap_get_socket_info( intfd, *socketargp, &soi ) != LDAP_SUCCESS ) {
goto close_socket_and_exit_with_error;
}
if ( NULL == ( ssoip = PR_Calloc( 1, sizeof( LDAPSSLSocketInfo )))) {
goto close_socket_and_exit_with_error;
}
ssoip->soi_sessioninfo = sseip;
if (( sslfd = SSL_ImportFD( NULL, soi.soinfo_prfd )) == NULL ) {
goto close_socket_and_exit_with_error;
}
if ( SSL_OptionSet( sslfd, SSL_SECURITY, secure ) != SECSuccess ||
SSL_OptionSet( sslfd, SSL_HANDSHAKE_AS_CLIENT, secure )
!= SECSuccess || ( secure && SSL_ResetHandshake( sslfd,
PR_FALSE ) != SECSuccess )) {
goto close_socket_and_exit_with_error;
}
soi.soinfo_prfd = sslfd;
soi.soinfo_appdata = (void *)ssoip;
if ( prldap_set_socket_info( intfd, *socketargp, &soi ) != LDAP_SUCCESS ) {
goto close_socket_and_exit_with_error;
}
#ifdef _SOLARIS_SDK
if (SSL_SetURL(sslfd, host) != SECSuccess)
goto close_socket_and_exit_with_error;
ldap_memfree(host);
host = NULL;
#endif
sslfd = NULL;
SSL_AuthCertificateHook( soi.soinfo_prfd,
(SSLAuthCertificate)ldapssl_AuthCertificate,
(void *)sseip);
if ( SSL_GetClientAuthDataHook( soi.soinfo_prfd,
get_clientauth_data, clientauth ? sseip : NULL ) != 0 ) {
goto close_socket_and_exit_with_error;
}
return( intfd );
close_socket_and_exit_with_error:
#ifdef _SOLARIS_SDK
if ( NULL != host ) ldap_memfree(host);
#endif
if ( NULL != sslfd ) {
PR_Close( sslfd );
}
if ( NULL != ssoip ) {
ldapssl_free_socket_info( &ssoip );
}
if ( intfd >= 0 && NULL != *socketargp ) {
(*(sseip->lssei_std_functions.lssf_close_fn))( intfd, *socketargp );
}
return( -1 );
}
static int
ldapssl_connect(const char *hostlist, int defport, int timeout,
unsigned long options, struct lextiof_session_private *sessionarg,
struct lextiof_socket_private **socketargp )
{
return( do_ldapssl_connect( hostlist, defport, timeout, options,
sessionarg, socketargp, 0 ));
}
static int
ldapssl_clientauth_connect(const char *hostlist, int defport, int timeout,
unsigned long options, struct lextiof_session_private *sessionarg,
struct lextiof_socket_private **socketargp )
{
return( do_ldapssl_connect( hostlist, defport, timeout, options,
sessionarg, socketargp, 1 ));
}
static void
ldapssl_disposehandle(LDAP *ld, struct lextiof_session_private *sessionarg)
{
PRLDAPSessionInfo sei;
LDAPSSLSessionInfo *sseip;
LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *disposehdl_fn;
memset( &sei, 0, sizeof( sei ));
sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
if ( prldap_get_session_info( ld, NULL, &sei ) == LDAP_SUCCESS ) {
sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
disposehdl_fn = sseip->lssei_std_functions.lssf_disposehdl_fn;
ldapssl_free_session_info( &sseip );
(*disposehdl_fn)( ld, sessionarg );
}
}
int
LDAP_CALL
ldapssl_install_routines( LDAP *ld )
{
#ifndef LDAP_SSLIO_HOOKS
ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
return( -1 );
#else
struct ldap_x_ext_io_fns iofns;
LDAPSSLSessionInfo *ssip;
PRLDAPSessionInfo sei;
#ifndef _SOLARIS_SDK
if ( prldap_install_routines(
ld,
1 )
!= LDAP_SUCCESS ) {
return( -1 );
}
#endif
if ( NULL == ( ssip = (LDAPSSLSessionInfo *)PR_Calloc( 1,
sizeof( LDAPSSLSessionInfo )))) {
ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL );
return( -1 );
}
ssip->lssei_ssl_strength = default_ssl_strength;
ssip->lssei_using_pcks_fns = using_pkcs_functions;
ssip->lssei_certdbh = CERT_GetDefaultCertDB();
#ifdef _SOLARIS_SDK
ssip->ld = ld;
#endif
memset( &iofns, 0, sizeof(iofns));
iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) {
ldapssl_free_session_info( &ssip );
return( -1 );
}
ssip->lssei_std_functions.lssf_connect_fn = iofns.lextiof_connect;
iofns.lextiof_connect = ldapssl_connect;
ssip->lssei_std_functions.lssf_close_fn = iofns.lextiof_close;
iofns.lextiof_close = ldapssl_close;
ssip->lssei_std_functions.lssf_disposehdl_fn = iofns.lextiof_disposehandle;
iofns.lextiof_disposehandle = ldapssl_disposehandle;
if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) {
ldapssl_free_session_info( &ssip );
return( -1 );
}
sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
sei.seinfo_appdata = (void *)ssip;
if ( prldap_set_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
return( -1 );
}
return( 0 );
#endif
}
int
LDAP_CALL
ldapssl_set_strength( LDAP *ld, int sslstrength )
{
int rc = 0;
if ( sslstrength != LDAPSSL_AUTH_WEAK &&
sslstrength != LDAPSSL_AUTH_CERT &&
sslstrength != LDAPSSL_AUTH_CNCHECK ) {
rc = -1;
} else {
if ( NULL == ld ) {
default_ssl_strength = sslstrength;
} else {
PRLDAPSessionInfo sei;
LDAPSSLSessionInfo *sseip;
memset( &sei, 0, sizeof( sei ));
sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
if ( prldap_get_session_info( ld, NULL, &sei ) == LDAP_SUCCESS )
{
sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
sseip->lssei_ssl_strength = sslstrength;
} else {
rc = -1;
}
}
}
return( rc );
}
int
LDAP_CALL
ldapssl_enable_clientauth( LDAP *ld, char *keynickname,
char *keypasswd, char *certnickname )
{
#ifndef LDAP_SSLIO_HOOKS
ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
return( -1 );
#else
struct ldap_x_ext_io_fns iofns;
LDAPSSLSessionInfo *ssip;
PRLDAPSessionInfo sei;
if ( certnickname == NULL || keypasswd == NULL ) {
ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
return( -1 );
}
sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
if ( prldap_get_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
return( -1 );
}
ssip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
if ( NULL == ssip ) {
ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
return( -1 );
}
ssip->lssei_certnickname = PL_strdup( certnickname );
ssip->lssei_keypasswd = PL_strdup( keypasswd );
if ( NULL == ssip->lssei_certnickname || NULL == ssip->lssei_keypasswd ) {
ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL );
return( -1 );
}
if ( check_clientauth_nicknames_and_passwd( ld, ssip ) != 0 ) {
return( -1 );
}
memset( &iofns, 0, sizeof(iofns));
iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns )
!= 0 ) {
return( -1 );
}
if ( iofns.lextiof_connect != ldapssl_connect ) {
ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
return( -1 );
}
iofns.lextiof_connect = ldapssl_clientauth_connect;
if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns )
!= 0 ) {
return( -1 );
}
return( 0 );
#endif
}
static void
ldapssl_free_session_info( LDAPSSLSessionInfo **ssipp )
{
if ( NULL != ssipp && NULL != *ssipp ) {
if ( NULL != (*ssipp)->lssei_certnickname ) {
PL_strfree( (*ssipp)->lssei_certnickname );
(*ssipp)->lssei_certnickname = NULL;
}
if ( NULL != (*ssipp)->lssei_keypasswd ) {
PL_strfree( (*ssipp)->lssei_keypasswd );
(*ssipp)->lssei_keypasswd = NULL;
}
PR_Free( *ssipp );
*ssipp = NULL;
}
}
static void
ldapssl_free_socket_info( LDAPSSLSocketInfo **soipp )
{
if ( NULL != soipp && NULL != *soipp ) {
PR_Free( *soipp );
*soipp = NULL;
}
}
static int
ldapssl_AuthCertificate(void *sessionarg, PRFileDesc *fd, PRBool checkSig,
PRBool isServer)
{
SECStatus rv = SECFailure;
LDAPSSLSessionInfo *sseip;
CERTCertificate *cert;
SECCertUsage certUsage;
char *hostname = (char *)0;
if (!sessionarg || !socket)
return rv;
sseip = (LDAPSSLSessionInfo *)sessionarg;
if (LDAPSSL_AUTH_WEAK == sseip->lssei_ssl_strength ) {
return SECSuccess;
}
if ( isServer ) {
certUsage = certUsageSSLClient;
} else {
certUsage = certUsageSSLServer;
}
cert = SSL_PeerCertificate( fd );
rv = CERT_VerifyCertNow(sseip->lssei_certdbh, cert, checkSig,
certUsage, NULL);
if ( rv != SECSuccess || isServer )
return rv;
if ( LDAPSSL_AUTH_CNCHECK == sseip->lssei_ssl_strength )
{
hostname = SSL_RevealURL( fd );
if (hostname && hostname[0]) {
rv = CERT_VerifyCertName(cert, hostname);
} else {
rv = SECFailure;
}
if (hostname)
PORT_Free(hostname);
if (rv != SECSuccess)
PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
}
return((int)rv);
}
static int
get_clientauth_data( void *sessionarg, PRFileDesc *prfd,
CERTDistNames *caNames, CERTCertificate **pRetCert,
SECKEYPrivateKey **pRetKey )
{
LDAPSSLSessionInfo *ssip;
if (( ssip = (LDAPSSLSessionInfo *)sessionarg ) == NULL ) {
return( -1 );
}
return( get_keyandcert( ssip, pRetCert, pRetKey, NULL ));
}
static int
get_keyandcert( LDAPSSLSessionInfo *ssip,
CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey,
char **errmsgp )
{
CERTCertificate *cert;
SECKEYPrivateKey *key;
if (( cert = PK11_FindCertFromNickname( ssip->lssei_certnickname, NULL ))
== NULL ) {
if ( errmsgp != NULL ) {
*errmsgp = dgettext(TEXT_DOMAIN, "unable to find certificate");
}
return( -1 );
}
{
PK11_SetPasswordFunc( get_keypassword );
}
if (( key = PK11_FindKeyByAnyCert( cert, (void *)ssip )) == NULL ) {
CERT_DestroyCertificate( cert );
if ( errmsgp != NULL ) {
*errmsgp = dgettext(TEXT_DOMAIN, "bad key or key password");
}
return( -1 );
}
*pRetCert = cert;
*pRetKey = key;
return( 0 );
}
static char *
get_keypassword( PK11SlotInfo *slot, PRBool retry, void *sessionarg )
{
LDAPSSLSessionInfo *ssip;
if ( retry)
return (NULL);
ssip = (LDAPSSLSessionInfo *)sessionarg;
if ( NULL == ssip ) {
return( NULL );
}
return( ssip->lssei_keypasswd );
}
static int
check_clientauth_nicknames_and_passwd( LDAP *ld, LDAPSSLSessionInfo *ssip )
{
char *errmsg = NULL;
CERTCertificate *cert = NULL;
SECKEYPrivateKey *key = NULL;
int rv;
rv = get_keyandcert( ssip, &cert, &key, &errmsg );
if ( rv != 0 ) {
if ( errmsg != NULL ) {
errmsg = strdup( errmsg );
}
ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, errmsg );
return( -1 );
}
if ( cert != NULL ) {
CERT_DestroyCertificate( cert );
}
if ( key != NULL ) {
SECKEY_DestroyPrivateKey( key );
}
return( 0 );
}
#if 0
int stubs_o_stuff( void )
{
PRExplodedTime exploded;
PLArenaPool pool;
const char *name ="t";
PRUint32 size = 0, align = 0;
PR_ImplodeTime( &exploded );
PL_InitArenaPool( &pool, name, size, align);
PR_Cleanup();
PR_fprintf((PRFileDesc*)stderr, "Bad IDEA!!");
return 0;
}
#endif
int ldapssl_import_fd ( LDAP *ld, int secure )
{
PRLDAPSessionInfo sei;
PRLDAPSocketInfo soi;
LDAPSSLSocketInfo *ssoip = NULL;
LDAPSSLSessionInfo *sseip;
PRFileDesc *sslfd = NULL;
memset( &sei, 0, sizeof(sei));
sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
if ( prldap_get_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
return( -1 );
}
sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
memset( &soi, 0, sizeof(soi));
soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
if ( prldap_get_default_socket_info( ld, &soi ) != LDAP_SUCCESS ) {
return( -1 );
}
if ( NULL == ( ssoip = PR_Calloc( 1, sizeof( LDAPSSLSocketInfo )))) {
goto reset_socket_and_exit_with_error;
}
ssoip->soi_sessioninfo = sseip;
if (( sslfd = SSL_ImportFD( NULL, soi.soinfo_prfd )) == NULL ) {
goto reset_socket_and_exit_with_error;
}
if ( SSL_OptionSet( sslfd, SSL_SECURITY, secure ) != SECSuccess ||
SSL_OptionSet( sslfd, SSL_HANDSHAKE_AS_CLIENT, secure )
!= SECSuccess || ( secure && SSL_ResetHandshake( sslfd,
PR_FALSE ) != SECSuccess )) {
goto reset_socket_and_exit_with_error;
}
soi.soinfo_prfd = sslfd;
soi.soinfo_appdata = (void *)ssoip;
if ( prldap_set_default_socket_info( ld, &soi ) != LDAP_SUCCESS ) {
goto reset_socket_and_exit_with_error;
}
if ( SSL_AuthCertificateHook( soi.soinfo_prfd,
(SSLAuthCertificate)ldapssl_AuthCertificate,
(void *)CERT_GetDefaultCertDB()) != 0 ) {
goto reset_socket_and_exit_with_error;
}
if ( SSL_GetClientAuthDataHook( soi.soinfo_prfd,
get_clientauth_data, sseip->lssei_certnickname ? sseip : NULL )
!= 0 ) {
goto reset_socket_and_exit_with_error;
}
return 0;
reset_socket_and_exit_with_error:
if ( NULL != sslfd ) {
soi.soinfo_prfd = sslfd;
sslfd = PR_PopIOLayer( soi.soinfo_prfd, PR_TOP_IO_LAYER );
sslfd->dtor( sslfd );
}
if ( NULL != ssoip ) {
ldapssl_free_socket_info( &ssoip );
soi.soinfo_appdata = NULL;
}
prldap_set_default_socket_info( ld, &soi );
return( -1 );
}
int ldapssl_reset_to_nonsecure ( LDAP *ld )
{
PRLDAPSessionInfo sei;
LDAPSSLSessionInfo *sseip;
struct ldap_x_ext_io_fns iofns;
int rc = 0;
memset( &sei, 0, sizeof(sei));
sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
if ( prldap_get_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
return( -1 );
}
sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
if ( sseip != NULL ) {
memset( &iofns, 0, sizeof(iofns));
iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns )
< 0) {
rc = -1;
goto free_session_info;
}
iofns.lextiof_connect = sseip->lssei_std_functions.lssf_connect_fn;
iofns.lextiof_close = sseip->lssei_std_functions.lssf_close_fn;
iofns.lextiof_disposehandle =
sseip->lssei_std_functions.lssf_disposehdl_fn;
if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns )
< 0) {
rc = -1;
goto free_session_info;
}
free_session_info:
ldapssl_free_session_info( &sseip );
sei.seinfo_appdata = NULL;
if ( prldap_set_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
rc = -1;
}
}
if ( ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_OFF ) < 0 ) {
return (-1);
}
return rc;
}
#ifdef _SOLARIS_SDK
static void
_nss_initf_ipnodes(nss_db_params_t *p)
{
static char *no_service = "";
p->name = NSS_DBNAM_IPNODES;
p->flags |= NSS_USE_DEFAULT_CONFIG;
p->default_config = host_service == NULL ? no_service : host_service;
}
static void
_nss_initf_hosts(nss_db_params_t *p)
{
static char *no_service = "";
p->name = NSS_DBNAM_HOSTS;
p->flags |= NSS_USE_DEFAULT_CONFIG;
p->default_config = host_service == NULL ? no_service : host_service;
}
static struct hostent *
_switch_gethostbyaddr_r(const char *addr, int len, int type,
struct hostent *result, char *buffer, int buflen,
int *h_errnop)
{
nss_XbyY_args_t arg;
nss_status_t res;
int (*str2ent)();
void (*nss_initf)();
nss_db_root_t *nss_db_root;
if (AF_INET == type) {
str2ent = str2hostent;
nss_initf = _nss_initf_hosts;
nss_db_root = &db_root_hosts;
} else if (AF_INET6 == type) {
str2ent = str2hostent6;
nss_initf = _nss_initf_ipnodes;
nss_db_root = &db_root_ipnodes;
} else {
return NULL;
}
NSS_XbyY_INIT(&arg, result, buffer, buflen, str2ent);
arg.key.hostaddr.addr = addr;
arg.key.hostaddr.len = len;
arg.key.hostaddr.type = type;
arg.stayopen = 0;
res = nss_search(nss_db_root, nss_initf,
NSS_DBOP_HOSTS_BYADDR, &arg);
arg.status = res;
*h_errnop = arg.h_errno;
return (struct hostent *)NSS_XbyY_FINI(&arg);
}
static LDAPHostEnt *
ns_gethostbyaddr(const char *addr, int len, int type,
LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
void *extradata)
{
LDAPHostEnt *ldap_hent;
int h_errno;
struct hostent h_ent;
struct hostent *h_e = NULL;
struct in_addr a;
struct in6_addr a6;
int inet_error;
if (addr == NULL || result == NULL || buffer == NULL ||
(type != AF_INET && type != AF_INET6))
return (NULL);
(void) memset(&h_ent, 0, sizeof (h_ent));
if (AF_INET == type) {
if (inet_pton(type, addr, &a.s_addr) == 1) {
h_e = _switch_gethostbyaddr_r((char *)&a,
sizeof (a.s_addr), type, &h_ent,
buffer, buflen, &h_errno);
}
} else if (AF_INET6 == type) {
if (inet_pton(type, addr, &a6.s6_addr) == 1) {
h_e = _switch_gethostbyaddr_r((char *)&a6,
sizeof (a6.s6_addr), type, &h_ent,
buffer, buflen, &h_errno);
}
}
if (h_e == NULL) {
ldap_hent = NULL;
} else {
(void) memset(result, 0, sizeof (LDAPHostEnt));
ldap_hent = result;
result->ldaphe_name = h_e->h_name;
result->ldaphe_aliases = h_e->h_aliases;
result->ldaphe_addrtype = h_e->h_addrtype;
result->ldaphe_length = h_e->h_length;
result->ldaphe_addr_list = h_e->h_addr_list;
}
return (ldap_hent);
}
int
ldapssl_install_gethostbyaddr(LDAP *ld, const char *skip)
{
enum __nsw_parse_err pserr;
struct __nsw_switchconfig *conf;
struct __nsw_lookup *lkp;
struct ldap_dns_fns dns_fns;
char *name_list = NULL;
char *tmp;
const char *name;
int len;
boolean_t got_skip = B_FALSE;
(void) mutex_lock(&db_root_hosts.lock);
conf = __nsw_getconfig("hosts", &pserr);
if (conf == NULL) {
(void) mutex_unlock(&db_root_hosts.lock);
return (0);
}
for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) {
name = lkp->service_name;
if (strcmp(name, skip) == 0) {
got_skip = B_TRUE;
continue;
}
if (name_list == NULL)
name_list = strdup(name);
else {
len = strlen(name_list);
tmp = realloc(name_list, len + strlen(name) + 2);
if (tmp == NULL) {
free(name_list);
name_list = NULL;
} else {
name_list = tmp;
name_list[len++] = ' ';
(void) strcpy(name_list+len, name);
}
}
if (name_list == NULL) {
(void) mutex_unlock(&db_root_hosts.lock);
__nsw_freeconfig(conf);
return (-1);
}
}
__nsw_freeconfig(conf);
if (!got_skip) {
(void) mutex_unlock(&db_root_hosts.lock);
if (name_list != NULL)
free(name_list);
return (0);
}
if (host_service != NULL)
free(host_service);
host_service = name_list;
(void) mutex_unlock(&db_root_hosts.lock);
if (ldap_get_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
return (-1);
dns_fns.lddnsfn_gethostbyaddr = ns_gethostbyaddr;
if (ldap_set_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
return (-1);
return (0);
}
#endif
#endif