17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public
87c478bd9Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file
97c478bd9Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of
107c478bd9Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS
137c478bd9Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
147c478bd9Sstevel@tonic-gate * implied. See the License for the specific language governing
157c478bd9Sstevel@tonic-gate * rights and limitations under the License.
167c478bd9Sstevel@tonic-gate *
177c478bd9Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released
187c478bd9Sstevel@tonic-gate * March 31, 1998.
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape
217c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
227c478bd9Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All
237c478bd9Sstevel@tonic-gate * Rights Reserved.
247c478bd9Sstevel@tonic-gate *
257c478bd9Sstevel@tonic-gate * Contributor(s):
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * ldapsinit.c
307c478bd9Sstevel@tonic-gate */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #if defined(NET_SSL)
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #if defined( _WINDOWS )
357c478bd9Sstevel@tonic-gate #include <windows.h>
367c478bd9Sstevel@tonic-gate #endif
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate /* XXX:mhein The following is a workaround for the redefinition of */
397c478bd9Sstevel@tonic-gate /* const problem on OSF. Fix to be provided by NSS */
407c478bd9Sstevel@tonic-gate /* This is a pretty benign workaround for us which */
417c478bd9Sstevel@tonic-gate /* should not cause problems in the future even if */
427c478bd9Sstevel@tonic-gate /* we forget to take it out :-) */
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate #ifdef OSF1V4D
457c478bd9Sstevel@tonic-gate #ifndef __STDC__
467c478bd9Sstevel@tonic-gate # define __STDC__
477c478bd9Sstevel@tonic-gate #endif /* __STDC__ */
487c478bd9Sstevel@tonic-gate #endif /* OSF1V4D */
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate #include <errno.h>
517c478bd9Sstevel@tonic-gate #include <nspr.h>
527c478bd9Sstevel@tonic-gate #include <cert.h>
537c478bd9Sstevel@tonic-gate #include <key.h>
547c478bd9Sstevel@tonic-gate #include <ssl.h>
557c478bd9Sstevel@tonic-gate #include <sslproto.h>
567c478bd9Sstevel@tonic-gate #include <sslerr.h>
577c478bd9Sstevel@tonic-gate #include <prnetdb.h>
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate #include <ldap.h>
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate #include <ldappr.h>
627c478bd9Sstevel@tonic-gate #include <pk11func.h>
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
657c478bd9Sstevel@tonic-gate #include "solaris-int.h"
667c478bd9Sstevel@tonic-gate #include <libintl.h>
677c478bd9Sstevel@tonic-gate #include <syslog.h>
687c478bd9Sstevel@tonic-gate #include <nsswitch.h>
697c478bd9Sstevel@tonic-gate #include <synch.h>
707c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
717c478bd9Sstevel@tonic-gate #include <netinet/in.h>
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate #define HOST_BUF_SIZE 2048
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate #ifndef INADDR_NONE
767c478bd9Sstevel@tonic-gate #define INADDR_NONE (-1)
777c478bd9Sstevel@tonic-gate #endif
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate extern int
807c478bd9Sstevel@tonic-gate str2hostent(const char *instr, int lenstr, void *ent, char *buffer,
817c478bd9Sstevel@tonic-gate int buflen);
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate extern int
847c478bd9Sstevel@tonic-gate str2hostent6(const char *instr, int lenstr, void *ent, char *buffer,
857c478bd9Sstevel@tonic-gate int buflen);
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate extern LDAPHostEnt *
887c478bd9Sstevel@tonic-gate _ns_gethostbyaddr(LDAP *ld, const char *addr, int length, int type,
897c478bd9Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
907c478bd9Sstevel@tonic-gate void *extradata);
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate static char *host_service = NULL;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root_hosts);
957c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root_ipnodes);
967c478bd9Sstevel@tonic-gate #endif
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate * Data structure to hold the standard NSPR I/O function pointers set by
1007c478bd9Sstevel@tonic-gate * libprldap. We save them in our session data structure so we can call
1017c478bd9Sstevel@tonic-gate * them from our own I/O functions (we add functionality to support SSL
1027c478bd9Sstevel@tonic-gate * while using libprldap's functions as much as possible).
1037c478bd9Sstevel@tonic-gate */
1047c478bd9Sstevel@tonic-gate typedef struct ldapssl_std_functions {
1057c478bd9Sstevel@tonic-gate LDAP_X_EXTIOF_CLOSE_CALLBACK *lssf_close_fn;
1067c478bd9Sstevel@tonic-gate LDAP_X_EXTIOF_CONNECT_CALLBACK *lssf_connect_fn;
1077c478bd9Sstevel@tonic-gate LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *lssf_disposehdl_fn;
1087c478bd9Sstevel@tonic-gate } LDAPSSLStdFunctions;
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate * LDAP session data structure.
1147c478bd9Sstevel@tonic-gate */
1157c478bd9Sstevel@tonic-gate typedef struct ldapssl_session_info {
1167c478bd9Sstevel@tonic-gate int lssei_using_pcks_fns;
1177c478bd9Sstevel@tonic-gate int lssei_ssl_strength;
1187c478bd9Sstevel@tonic-gate char *lssei_certnickname;
1197c478bd9Sstevel@tonic-gate char *lssei_keypasswd;
1207c478bd9Sstevel@tonic-gate LDAPSSLStdFunctions lssei_std_functions;
1217c478bd9Sstevel@tonic-gate CERTCertDBHandle *lssei_certdbh;
1227c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate * This is a hack.
1257c478bd9Sstevel@tonic-gate * ld is used so that we can use libldap's gethostbyaddr
1267c478bd9Sstevel@tonic-gate * resolver. This is needed to prevent recursion with libsldap.
1277c478bd9Sstevel@tonic-gate */
1287c478bd9Sstevel@tonic-gate LDAP *ld;
1297c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
1307c478bd9Sstevel@tonic-gate } LDAPSSLSessionInfo;
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate * LDAP socket data structure.
1357c478bd9Sstevel@tonic-gate */
1367c478bd9Sstevel@tonic-gate typedef struct ldapssl_socket_info {
1377c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *soi_sessioninfo; /* session info */
1387c478bd9Sstevel@tonic-gate } LDAPSSLSocketInfo;
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate
141*1da57d55SToomas Soome /*
1427c478bd9Sstevel@tonic-gate * XXXceb This is a hack until the new IO functions are done.
1437c478bd9Sstevel@tonic-gate * this function MUST be called before ldap_enable_clienauth.
1447c478bd9Sstevel@tonic-gate * right now, this function is called in ldapssl_pkcs_init();
1457c478bd9Sstevel@tonic-gate */
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate static int using_pkcs_functions = 0;
1487c478bd9Sstevel@tonic-gate
set_using_pkcs_functions(int val)1497c478bd9Sstevel@tonic-gate void set_using_pkcs_functions( int val )
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate using_pkcs_functions = val;
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate /*
1567c478bd9Sstevel@tonic-gate * Utility functions:
1577c478bd9Sstevel@tonic-gate */
1587c478bd9Sstevel@tonic-gate static void ldapssl_free_session_info( LDAPSSLSessionInfo **ssipp );
1597c478bd9Sstevel@tonic-gate static void ldapssl_free_socket_info( LDAPSSLSocketInfo **soipp );
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate /*
163*1da57d55SToomas Soome * SSL Stuff
1647c478bd9Sstevel@tonic-gate */
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate static int ldapssl_AuthCertificate(void *sessionarg, PRFileDesc *fd,
1677c478bd9Sstevel@tonic-gate PRBool checkSig, PRBool isServer);
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate /*
1707c478bd9Sstevel@tonic-gate * client auth stuff
1717c478bd9Sstevel@tonic-gate */
1727c478bd9Sstevel@tonic-gate static int get_clientauth_data( void *sessionarg, PRFileDesc *prfd,
1737c478bd9Sstevel@tonic-gate CERTDistNames *caNames, CERTCertificate **pRetCert,
1747c478bd9Sstevel@tonic-gate SECKEYPrivateKey **pRetKey );
1757c478bd9Sstevel@tonic-gate static int get_keyandcert( LDAPSSLSessionInfo *ssip,
1767c478bd9Sstevel@tonic-gate CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey,
1777c478bd9Sstevel@tonic-gate char **errmsgp );
1787c478bd9Sstevel@tonic-gate static int check_clientauth_nicknames_and_passwd( LDAP *ld,
1797c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip );
1807c478bd9Sstevel@tonic-gate static char *get_keypassword( PK11SlotInfo *slot, PRBool retry,
1817c478bd9Sstevel@tonic-gate void *sessionarg );
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate * Static variables.
1857c478bd9Sstevel@tonic-gate */
1867c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
1877c478bd9Sstevel@tonic-gate static int default_ssl_strength = LDAPSSL_AUTH_CNCHECK;
1887c478bd9Sstevel@tonic-gate #else
1897c478bd9Sstevel@tonic-gate static int default_ssl_strength = LDAPSSL_AUTH_CERT;
1907c478bd9Sstevel@tonic-gate #endif
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate * Like ldap_init(), except also install I/O routines from libsec so we
1947c478bd9Sstevel@tonic-gate * can support SSL. If defsecure is non-zero, SSL is enabled for the
1957c478bd9Sstevel@tonic-gate * default connection as well.
1967c478bd9Sstevel@tonic-gate */
1977c478bd9Sstevel@tonic-gate LDAP *
1987c478bd9Sstevel@tonic-gate LDAP_CALL
ldapssl_init(const char * defhost,int defport,int defsecure)1997c478bd9Sstevel@tonic-gate ldapssl_init( const char *defhost, int defport, int defsecure )
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate LDAP *ld;
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate #ifndef LDAP_SSLIO_HOOKS
2057c478bd9Sstevel@tonic-gate return( NULL );
2067c478bd9Sstevel@tonic-gate #else
2077c478bd9Sstevel@tonic-gate if (0 ==defport)
2087c478bd9Sstevel@tonic-gate defport = LDAPS_PORT;
209*1da57d55SToomas Soome
2107c478bd9Sstevel@tonic-gate if (( ld = ldap_init( defhost, defport )) == NULL ) {
2117c478bd9Sstevel@tonic-gate return( NULL );
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate if ( ldapssl_install_routines( ld ) < 0 || ldap_set_option( ld,
2157c478bd9Sstevel@tonic-gate LDAP_OPT_SSL, defsecure ? LDAP_OPT_ON : LDAP_OPT_OFF ) != 0 ) {
2167c478bd9Sstevel@tonic-gate PR_SetError( PR_UNKNOWN_ERROR, EINVAL ); /* XXXmcs: just a guess! */
2177c478bd9Sstevel@tonic-gate ldap_unbind( ld );
2187c478bd9Sstevel@tonic-gate return( NULL );
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate return( ld );
2227c478bd9Sstevel@tonic-gate #endif
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate static int
ldapssl_close(int s,struct lextiof_socket_private * socketarg)2277c478bd9Sstevel@tonic-gate ldapssl_close(int s, struct lextiof_socket_private *socketarg)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate PRLDAPSocketInfo soi;
2307c478bd9Sstevel@tonic-gate LDAPSSLSocketInfo *ssoip;
2317c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip;
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate memset( &soi, 0, sizeof(soi));
2347c478bd9Sstevel@tonic-gate soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
2357c478bd9Sstevel@tonic-gate if ( prldap_get_socket_info( s, socketarg, &soi ) != LDAP_SUCCESS ) {
2367c478bd9Sstevel@tonic-gate return( -1 );
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate ssoip = (LDAPSSLSocketInfo *)soi.soinfo_appdata;
2407c478bd9Sstevel@tonic-gate sseip = ssoip->soi_sessioninfo;
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate ldapssl_free_socket_info( (LDAPSSLSocketInfo **)&soi.soinfo_appdata );
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate return( (*(sseip->lssei_std_functions.lssf_close_fn))( s, socketarg ));
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate 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)2487c478bd9Sstevel@tonic-gate do_ldapssl_connect(const char *hostlist, int defport, int timeout,
2497c478bd9Sstevel@tonic-gate unsigned long options, struct lextiof_session_private *sessionarg,
2507c478bd9Sstevel@tonic-gate struct lextiof_socket_private **socketargp, int clientauth )
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate int intfd = -1;
2537c478bd9Sstevel@tonic-gate PRBool secure;
2547c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei;
2557c478bd9Sstevel@tonic-gate PRLDAPSocketInfo soi;
2567c478bd9Sstevel@tonic-gate LDAPSSLSocketInfo *ssoip = NULL;
2577c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip;
2587c478bd9Sstevel@tonic-gate PRFileDesc *sslfd = NULL;
2597c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
2607c478bd9Sstevel@tonic-gate int port;
2617c478bd9Sstevel@tonic-gate int parse_err;
2627c478bd9Sstevel@tonic-gate char *host = NULL;
2637c478bd9Sstevel@tonic-gate char *name;
2647c478bd9Sstevel@tonic-gate struct ldap_x_hostlist_status
2657c478bd9Sstevel@tonic-gate *status = NULL;
2667c478bd9Sstevel@tonic-gate in_addr_t addr_ipv4;
2677c478bd9Sstevel@tonic-gate in6_addr_t addr_ipv6;
2687c478bd9Sstevel@tonic-gate char *host_buf;
2697c478bd9Sstevel@tonic-gate LDAPHostEnt *hent;
2707c478bd9Sstevel@tonic-gate LDAPHostEnt host_ent;
2717c478bd9Sstevel@tonic-gate int stat;
2727c478bd9Sstevel@tonic-gate int type;
2737c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate /*
2767c478bd9Sstevel@tonic-gate * Determine if secure option is set. Also, clear secure bit in options
2777c478bd9Sstevel@tonic-gate * the we pass to the standard connect() function (since it doesn't know
2787c478bd9Sstevel@tonic-gate * how to handle the secure option).
2797c478bd9Sstevel@tonic-gate */
2807c478bd9Sstevel@tonic-gate if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) {
2817c478bd9Sstevel@tonic-gate secure = PR_TRUE;
2827c478bd9Sstevel@tonic-gate options &= ~LDAP_X_EXTIOF_OPT_SECURE;
2837c478bd9Sstevel@tonic-gate } else {
2847c478bd9Sstevel@tonic-gate secure = PR_FALSE;
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate * Retrieve session info. so we can store a pointer to our session info.
2897c478bd9Sstevel@tonic-gate * in our socket info. later.
2907c478bd9Sstevel@tonic-gate */
2917c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof(sei));
2927c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
2937c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( NULL, sessionarg, &sei ) != LDAP_SUCCESS ) {
2947c478bd9Sstevel@tonic-gate return( -1 );
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
297*1da57d55SToomas Soome
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate * Call the standard connect() callback to make the TCP connection.
3007c478bd9Sstevel@tonic-gate * If it succeeds, *socketargp is set.
3017c478bd9Sstevel@tonic-gate */
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate intfd = (*(sseip->lssei_std_functions.lssf_connect_fn))( hostlist, defport,
3047c478bd9Sstevel@tonic-gate timeout, options, sessionarg, socketargp
3057c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
3067c478bd9Sstevel@tonic-gate , &host );
3077c478bd9Sstevel@tonic-gate #else
3087c478bd9Sstevel@tonic-gate );
3097c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate if ( intfd < 0 ) {
3127c478bd9Sstevel@tonic-gate return( intfd );
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
3167c478bd9Sstevel@tonic-gate /*
3177c478bd9Sstevel@tonic-gate * Determine if the "host name" is an ip address. If so,
3187c478bd9Sstevel@tonic-gate * we must look up the actual host name corresponding to
3197c478bd9Sstevel@tonic-gate * it.
3207c478bd9Sstevel@tonic-gate */
3217c478bd9Sstevel@tonic-gate if ( NULL == host ) {
3227c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate type = AF_UNSPEC;
3257c478bd9Sstevel@tonic-gate if (strlen(host) < INET6_ADDRSTRLEN &&
3267c478bd9Sstevel@tonic-gate inet_pton(AF_INET6, host, &addr_ipv6) == 1) {
3277c478bd9Sstevel@tonic-gate type = AF_INET6;
3287c478bd9Sstevel@tonic-gate } else if (strlen(host) < INET_ADDRSTRLEN &&
3297c478bd9Sstevel@tonic-gate inet_pton(AF_INET, host, &addr_ipv4) == 1) {
3307c478bd9Sstevel@tonic-gate type = AF_INET;
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate if (type == AF_INET || type == AF_INET6) {
3337c478bd9Sstevel@tonic-gate host_buf = malloc(HOST_BUF_SIZE);
3347c478bd9Sstevel@tonic-gate if (host_buf == NULL) {
3357c478bd9Sstevel@tonic-gate /* will free host in close_socket_and_exit_with_error */
3367c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /* Call ldap layer's gethostbyaddr resolver */
3407c478bd9Sstevel@tonic-gate hent = _ns_gethostbyaddr(sseip->ld, host, strlen(host), type,
3417c478bd9Sstevel@tonic-gate &host_ent, host_buf, HOST_BUF_SIZE, &stat, NULL);
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate /* If we are unable to lookup the host addr, we fail! */
3447c478bd9Sstevel@tonic-gate if (hent == NULL) {
3457c478bd9Sstevel@tonic-gate syslog(LOG_WARNING,
3467c478bd9Sstevel@tonic-gate "libldap: do_ldapssl_connect: "
3477c478bd9Sstevel@tonic-gate "Unable to resolve '%s'", host);
3487c478bd9Sstevel@tonic-gate free(host_buf);
3497c478bd9Sstevel@tonic-gate /* will free host in close_socket_and_exit_with_error */
3507c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate /* We support only the primary host name */
3537c478bd9Sstevel@tonic-gate else {
3547c478bd9Sstevel@tonic-gate if (hent->ldaphe_name != NULL)
3557c478bd9Sstevel@tonic-gate name = strdup(hent->ldaphe_name);
3567c478bd9Sstevel@tonic-gate free(host_buf);
3577c478bd9Sstevel@tonic-gate if (name == NULL)
3587c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
3597c478bd9Sstevel@tonic-gate else
3607c478bd9Sstevel@tonic-gate ldap_memfree(host); host = NULL;
3617c478bd9Sstevel@tonic-gate host = name;
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate * Retrieve socket info. so we have the PRFileDesc.
3687c478bd9Sstevel@tonic-gate */
3697c478bd9Sstevel@tonic-gate memset( &soi, 0, sizeof(soi));
3707c478bd9Sstevel@tonic-gate soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
3717c478bd9Sstevel@tonic-gate if ( prldap_get_socket_info( intfd, *socketargp, &soi ) != LDAP_SUCCESS ) {
3727c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate /*
3767c478bd9Sstevel@tonic-gate * Allocate a structure to hold our socket-specific data.
3777c478bd9Sstevel@tonic-gate */
3787c478bd9Sstevel@tonic-gate if ( NULL == ( ssoip = PR_Calloc( 1, sizeof( LDAPSSLSocketInfo )))) {
3797c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate ssoip->soi_sessioninfo = sseip;
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate * Add SSL layer and let the standard NSPR to LDAP layer and enable SSL.
3857c478bd9Sstevel@tonic-gate */
3867c478bd9Sstevel@tonic-gate if (( sslfd = SSL_ImportFD( NULL, soi.soinfo_prfd )) == NULL ) {
3877c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate if ( SSL_OptionSet( sslfd, SSL_SECURITY, secure ) != SECSuccess ||
3917c478bd9Sstevel@tonic-gate SSL_OptionSet( sslfd, SSL_HANDSHAKE_AS_CLIENT, secure )
3927c478bd9Sstevel@tonic-gate != SECSuccess || ( secure && SSL_ResetHandshake( sslfd,
3937c478bd9Sstevel@tonic-gate PR_FALSE ) != SECSuccess )) {
3947c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate /*
3987c478bd9Sstevel@tonic-gate * Let the standard NSPR to LDAP layer know about the new socket and
3997c478bd9Sstevel@tonic-gate * our own socket-specific data.
4007c478bd9Sstevel@tonic-gate */
4017c478bd9Sstevel@tonic-gate soi.soinfo_prfd = sslfd;
4027c478bd9Sstevel@tonic-gate soi.soinfo_appdata = (void *)ssoip;
4037c478bd9Sstevel@tonic-gate if ( prldap_set_socket_info( intfd, *socketargp, &soi ) != LDAP_SUCCESS ) {
4047c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
4087c478bd9Sstevel@tonic-gate /*
4097c478bd9Sstevel@tonic-gate * Set hostname which will be retrieved (depending on ssl strength) when
4107c478bd9Sstevel@tonic-gate * using client or server auth.
4117c478bd9Sstevel@tonic-gate */
4127c478bd9Sstevel@tonic-gate if (SSL_SetURL(sslfd, host) != SECSuccess)
4137c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
4147c478bd9Sstevel@tonic-gate ldap_memfree(host);
4157c478bd9Sstevel@tonic-gate host = NULL;
4167c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate sslfd = NULL; /* so we don't close the socket twice upon error */
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate /*
4217c478bd9Sstevel@tonic-gate * Install certificate hook function.
4227c478bd9Sstevel@tonic-gate */
4237c478bd9Sstevel@tonic-gate SSL_AuthCertificateHook( soi.soinfo_prfd,
424*1da57d55SToomas Soome (SSLAuthCertificate)ldapssl_AuthCertificate,
4257c478bd9Sstevel@tonic-gate (void *)sseip);
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate if ( SSL_GetClientAuthDataHook( soi.soinfo_prfd,
4287c478bd9Sstevel@tonic-gate get_clientauth_data, clientauth ? sseip : NULL ) != 0 ) {
4297c478bd9Sstevel@tonic-gate goto close_socket_and_exit_with_error;
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate return( intfd ); /* success */
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate close_socket_and_exit_with_error:
4357c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
4367c478bd9Sstevel@tonic-gate if ( NULL != host ) ldap_memfree(host);
4377c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
4387c478bd9Sstevel@tonic-gate if ( NULL != sslfd ) {
4397c478bd9Sstevel@tonic-gate PR_Close( sslfd );
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate if ( NULL != ssoip ) {
4427c478bd9Sstevel@tonic-gate ldapssl_free_socket_info( &ssoip );
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate if ( intfd >= 0 && NULL != *socketargp ) {
4457c478bd9Sstevel@tonic-gate (*(sseip->lssei_std_functions.lssf_close_fn))( intfd, *socketargp );
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate return( -1 );
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate static int
ldapssl_connect(const char * hostlist,int defport,int timeout,unsigned long options,struct lextiof_session_private * sessionarg,struct lextiof_socket_private ** socketargp)4527c478bd9Sstevel@tonic-gate ldapssl_connect(const char *hostlist, int defport, int timeout,
4537c478bd9Sstevel@tonic-gate unsigned long options, struct lextiof_session_private *sessionarg,
4547c478bd9Sstevel@tonic-gate struct lextiof_socket_private **socketargp )
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate return( do_ldapssl_connect( hostlist, defport, timeout, options,
4577c478bd9Sstevel@tonic-gate sessionarg, socketargp, 0 ));
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate 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)4627c478bd9Sstevel@tonic-gate ldapssl_clientauth_connect(const char *hostlist, int defport, int timeout,
4637c478bd9Sstevel@tonic-gate unsigned long options, struct lextiof_session_private *sessionarg,
4647c478bd9Sstevel@tonic-gate struct lextiof_socket_private **socketargp )
4657c478bd9Sstevel@tonic-gate {
4667c478bd9Sstevel@tonic-gate return( do_ldapssl_connect( hostlist, defport, timeout, options,
4677c478bd9Sstevel@tonic-gate sessionarg, socketargp, 1 ));
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate static void
ldapssl_disposehandle(LDAP * ld,struct lextiof_session_private * sessionarg)4727c478bd9Sstevel@tonic-gate ldapssl_disposehandle(LDAP *ld, struct lextiof_session_private *sessionarg)
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei;
4757c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip;
4767c478bd9Sstevel@tonic-gate LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *disposehdl_fn;
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof( sei ));
4797c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
4807c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) == LDAP_SUCCESS ) {
4817c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
4827c478bd9Sstevel@tonic-gate disposehdl_fn = sseip->lssei_std_functions.lssf_disposehdl_fn;
4837c478bd9Sstevel@tonic-gate ldapssl_free_session_info( &sseip );
4847c478bd9Sstevel@tonic-gate (*disposehdl_fn)( ld, sessionarg );
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate }
4877c478bd9Sstevel@tonic-gate
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gate /*
4907c478bd9Sstevel@tonic-gate * Install I/O routines from libsec and NSPR into libldap to allow libldap
4917c478bd9Sstevel@tonic-gate * to do SSL.
4927c478bd9Sstevel@tonic-gate *
4937c478bd9Sstevel@tonic-gate * We rely on libprldap to provide most of the functions, and then we override
4947c478bd9Sstevel@tonic-gate * a few of them to support SSL.
4957c478bd9Sstevel@tonic-gate */
4967c478bd9Sstevel@tonic-gate int
4977c478bd9Sstevel@tonic-gate LDAP_CALL
ldapssl_install_routines(LDAP * ld)4987c478bd9Sstevel@tonic-gate ldapssl_install_routines( LDAP *ld )
4997c478bd9Sstevel@tonic-gate {
5007c478bd9Sstevel@tonic-gate #ifndef LDAP_SSLIO_HOOKS
5017c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
5027c478bd9Sstevel@tonic-gate return( -1 );
5037c478bd9Sstevel@tonic-gate #else
5047c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns;
5057c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip;
5067c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei;
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate * This is done within ldap_init() and
5107c478bd9Sstevel@tonic-gate * ldap_init() is called from ldapssl_init()
5117c478bd9Sstevel@tonic-gate */
5127c478bd9Sstevel@tonic-gate #ifndef _SOLARIS_SDK
5137c478bd9Sstevel@tonic-gate if ( prldap_install_routines(
5147c478bd9Sstevel@tonic-gate ld,
5157c478bd9Sstevel@tonic-gate 1 /* shared -- we have to assume it is */ )
5167c478bd9Sstevel@tonic-gate != LDAP_SUCCESS ) {
5177c478bd9Sstevel@tonic-gate return( -1 );
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate #endif /*_SOLARIS_SDK*/
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate /*
5227c478bd9Sstevel@tonic-gate * Allocate our own session information.
5237c478bd9Sstevel@tonic-gate */
5247c478bd9Sstevel@tonic-gate if ( NULL == ( ssip = (LDAPSSLSessionInfo *)PR_Calloc( 1,
5257c478bd9Sstevel@tonic-gate sizeof( LDAPSSLSessionInfo )))) {
5267c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL );
5277c478bd9Sstevel@tonic-gate return( -1 );
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate /*
5307c478bd9Sstevel@tonic-gate * Initialize session info.
5317c478bd9Sstevel@tonic-gate * XXX: it would be nice to be able to set these on a per-session basis:
5327c478bd9Sstevel@tonic-gate * lssei_using_pcks_fns
5337c478bd9Sstevel@tonic-gate * lssei_certdbh
5347c478bd9Sstevel@tonic-gate */
5357c478bd9Sstevel@tonic-gate ssip->lssei_ssl_strength = default_ssl_strength;
5367c478bd9Sstevel@tonic-gate ssip->lssei_using_pcks_fns = using_pkcs_functions;
5377c478bd9Sstevel@tonic-gate ssip->lssei_certdbh = CERT_GetDefaultCertDB();
5387c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
5397c478bd9Sstevel@tonic-gate /*
5407c478bd9Sstevel@tonic-gate * This is part of a hack to allow the ssl portion of the
5417c478bd9Sstevel@tonic-gate * library to call the ldap library gethostbyaddr resolver.
5427c478bd9Sstevel@tonic-gate */
5437c478bd9Sstevel@tonic-gate ssip->ld = ld;
5447c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate /*
5477c478bd9Sstevel@tonic-gate * override a few functions, saving a pointer to the standard function
5487c478bd9Sstevel@tonic-gate * in each case so we can call it from our SSL savvy functions.
5497c478bd9Sstevel@tonic-gate */
5507c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns));
5517c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
5527c478bd9Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) {
5537c478bd9Sstevel@tonic-gate ldapssl_free_session_info( &ssip );
5547c478bd9Sstevel@tonic-gate return( -1 );
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate /* override socket, connect, and ioctl */
5587c478bd9Sstevel@tonic-gate ssip->lssei_std_functions.lssf_connect_fn = iofns.lextiof_connect;
5597c478bd9Sstevel@tonic-gate iofns.lextiof_connect = ldapssl_connect;
5607c478bd9Sstevel@tonic-gate ssip->lssei_std_functions.lssf_close_fn = iofns.lextiof_close;
5617c478bd9Sstevel@tonic-gate iofns.lextiof_close = ldapssl_close;
5627c478bd9Sstevel@tonic-gate ssip->lssei_std_functions.lssf_disposehdl_fn = iofns.lextiof_disposehandle;
5637c478bd9Sstevel@tonic-gate iofns.lextiof_disposehandle = ldapssl_disposehandle;
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) {
5667c478bd9Sstevel@tonic-gate ldapssl_free_session_info( &ssip );
5677c478bd9Sstevel@tonic-gate return( -1 );
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate /*
5717c478bd9Sstevel@tonic-gate * Store session info. for later retrieval.
5727c478bd9Sstevel@tonic-gate */
5737c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
5747c478bd9Sstevel@tonic-gate sei.seinfo_appdata = (void *)ssip;
5757c478bd9Sstevel@tonic-gate if ( prldap_set_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
5767c478bd9Sstevel@tonic-gate return( -1 );
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate
5797c478bd9Sstevel@tonic-gate return( 0 );
5807c478bd9Sstevel@tonic-gate #endif
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate /*
5857c478bd9Sstevel@tonic-gate * Set the SSL strength for an existing SSL-enabled LDAP session handle.
5867c478bd9Sstevel@tonic-gate *
5877c478bd9Sstevel@tonic-gate * See the description of ldapssl_serverauth_init() above for valid
5887c478bd9Sstevel@tonic-gate * sslstrength values. If ld is NULL, the default for new LDAP session
5897c478bd9Sstevel@tonic-gate * handles is set.
5907c478bd9Sstevel@tonic-gate *
5917c478bd9Sstevel@tonic-gate * Returns 0 if all goes well and -1 if an error occurs.
5927c478bd9Sstevel@tonic-gate */
5937c478bd9Sstevel@tonic-gate int
5947c478bd9Sstevel@tonic-gate LDAP_CALL
ldapssl_set_strength(LDAP * ld,int sslstrength)5957c478bd9Sstevel@tonic-gate ldapssl_set_strength( LDAP *ld, int sslstrength )
5967c478bd9Sstevel@tonic-gate {
5977c478bd9Sstevel@tonic-gate int rc = 0; /* assume success */
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate if ( sslstrength != LDAPSSL_AUTH_WEAK &&
6007c478bd9Sstevel@tonic-gate sslstrength != LDAPSSL_AUTH_CERT &&
6017c478bd9Sstevel@tonic-gate sslstrength != LDAPSSL_AUTH_CNCHECK ) {
6027c478bd9Sstevel@tonic-gate rc = -1;
6037c478bd9Sstevel@tonic-gate } else {
6047c478bd9Sstevel@tonic-gate if ( NULL == ld ) { /* set default strength */
6057c478bd9Sstevel@tonic-gate default_ssl_strength = sslstrength;
6067c478bd9Sstevel@tonic-gate } else { /* set session-specific strength */
6077c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei;
6087c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip;
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof( sei ));
6117c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
6127c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) == LDAP_SUCCESS )
6137c478bd9Sstevel@tonic-gate {
6147c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
6157c478bd9Sstevel@tonic-gate sseip->lssei_ssl_strength = sslstrength;
6167c478bd9Sstevel@tonic-gate } else {
6177c478bd9Sstevel@tonic-gate rc = -1;
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate }
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate return( rc );
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate int
6267c478bd9Sstevel@tonic-gate LDAP_CALL
ldapssl_enable_clientauth(LDAP * ld,char * keynickname,char * keypasswd,char * certnickname)6277c478bd9Sstevel@tonic-gate ldapssl_enable_clientauth( LDAP *ld, char *keynickname,
6287c478bd9Sstevel@tonic-gate char *keypasswd, char *certnickname )
6297c478bd9Sstevel@tonic-gate {
6307c478bd9Sstevel@tonic-gate #ifndef LDAP_SSLIO_HOOKS
6317c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
6327c478bd9Sstevel@tonic-gate return( -1 );
6337c478bd9Sstevel@tonic-gate #else
6347c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns;
6357c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip;
6367c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei;
6377c478bd9Sstevel@tonic-gate
6387c478bd9Sstevel@tonic-gate /*
6397c478bd9Sstevel@tonic-gate * Check parameters
6407c478bd9Sstevel@tonic-gate */
6417c478bd9Sstevel@tonic-gate if ( certnickname == NULL || keypasswd == NULL ) {
6427c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
6437c478bd9Sstevel@tonic-gate return( -1 );
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate /*
6477c478bd9Sstevel@tonic-gate * Update session info. data structure.
6487c478bd9Sstevel@tonic-gate */
6497c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
6507c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
6517c478bd9Sstevel@tonic-gate return( -1 );
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate ssip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
6547c478bd9Sstevel@tonic-gate if ( NULL == ssip ) {
6557c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
6567c478bd9Sstevel@tonic-gate return( -1 );
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate ssip->lssei_certnickname = PL_strdup( certnickname );
6597c478bd9Sstevel@tonic-gate ssip->lssei_keypasswd = PL_strdup( keypasswd );
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate if ( NULL == ssip->lssei_certnickname || NULL == ssip->lssei_keypasswd ) {
6627c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL );
6637c478bd9Sstevel@tonic-gate return( -1 );
6647c478bd9Sstevel@tonic-gate }
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate if ( check_clientauth_nicknames_and_passwd( ld, ssip ) != 0 ) {
6677c478bd9Sstevel@tonic-gate return( -1 );
6687c478bd9Sstevel@tonic-gate }
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate /*
6717c478bd9Sstevel@tonic-gate * replace standard SSL CONNECT function with client auth aware one
6727c478bd9Sstevel@tonic-gate */
6737c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns));
6747c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
6757c478bd9Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns )
6767c478bd9Sstevel@tonic-gate != 0 ) {
6777c478bd9Sstevel@tonic-gate return( -1 );
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate if ( iofns.lextiof_connect != ldapssl_connect ) {
6817c478bd9Sstevel@tonic-gate /* standard SSL setup has not done */
6827c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
6837c478bd9Sstevel@tonic-gate return( -1 );
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate iofns.lextiof_connect = ldapssl_clientauth_connect;
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns )
6897c478bd9Sstevel@tonic-gate != 0 ) {
6907c478bd9Sstevel@tonic-gate return( -1 );
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate
6937c478bd9Sstevel@tonic-gate return( 0 );
6947c478bd9Sstevel@tonic-gate #endif
6957c478bd9Sstevel@tonic-gate }
6967c478bd9Sstevel@tonic-gate
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate static void
ldapssl_free_session_info(LDAPSSLSessionInfo ** ssipp)6997c478bd9Sstevel@tonic-gate ldapssl_free_session_info( LDAPSSLSessionInfo **ssipp )
7007c478bd9Sstevel@tonic-gate {
7017c478bd9Sstevel@tonic-gate if ( NULL != ssipp && NULL != *ssipp ) {
7027c478bd9Sstevel@tonic-gate if ( NULL != (*ssipp)->lssei_certnickname ) {
7037c478bd9Sstevel@tonic-gate PL_strfree( (*ssipp)->lssei_certnickname );
7047c478bd9Sstevel@tonic-gate (*ssipp)->lssei_certnickname = NULL;
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate if ( NULL != (*ssipp)->lssei_keypasswd ) {
7077c478bd9Sstevel@tonic-gate PL_strfree( (*ssipp)->lssei_keypasswd );
7087c478bd9Sstevel@tonic-gate (*ssipp)->lssei_keypasswd = NULL;
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate PR_Free( *ssipp );
7117c478bd9Sstevel@tonic-gate *ssipp = NULL;
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate static void
ldapssl_free_socket_info(LDAPSSLSocketInfo ** soipp)7177c478bd9Sstevel@tonic-gate ldapssl_free_socket_info( LDAPSSLSocketInfo **soipp )
7187c478bd9Sstevel@tonic-gate {
7197c478bd9Sstevel@tonic-gate if ( NULL != soipp && NULL != *soipp ) {
7207c478bd9Sstevel@tonic-gate PR_Free( *soipp );
7217c478bd9Sstevel@tonic-gate *soipp = NULL;
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate
726*1da57d55SToomas Soome /* this function provides cert authentication. This is called during
7277c478bd9Sstevel@tonic-gate * the SSL_Handshake process. Once the cert has been retrieved from
728*1da57d55SToomas Soome * the server, the it is checked, using VerifyCertNow(), then
7297c478bd9Sstevel@tonic-gate * the cn is checked against the host name, set with SSL_SetURL()
7307c478bd9Sstevel@tonic-gate */
7317c478bd9Sstevel@tonic-gate
7327c478bd9Sstevel@tonic-gate static int
ldapssl_AuthCertificate(void * sessionarg,PRFileDesc * fd,PRBool checkSig,PRBool isServer)7337c478bd9Sstevel@tonic-gate ldapssl_AuthCertificate(void *sessionarg, PRFileDesc *fd, PRBool checkSig,
7347c478bd9Sstevel@tonic-gate PRBool isServer)
7357c478bd9Sstevel@tonic-gate {
7367c478bd9Sstevel@tonic-gate SECStatus rv = SECFailure;
7377c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip;
7387c478bd9Sstevel@tonic-gate CERTCertificate *cert;
7397c478bd9Sstevel@tonic-gate SECCertUsage certUsage;
7407c478bd9Sstevel@tonic-gate char *hostname = (char *)0;
741*1da57d55SToomas Soome
7427c478bd9Sstevel@tonic-gate if (!sessionarg || !socket)
7437c478bd9Sstevel@tonic-gate return rv;
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sessionarg;
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate if (LDAPSSL_AUTH_WEAK == sseip->lssei_ssl_strength ) { /* no check */
7487c478bd9Sstevel@tonic-gate return SECSuccess;
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate if ( isServer ) {
7527c478bd9Sstevel@tonic-gate certUsage = certUsageSSLClient;
7537c478bd9Sstevel@tonic-gate } else {
7547c478bd9Sstevel@tonic-gate certUsage = certUsageSSLServer;
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate cert = SSL_PeerCertificate( fd );
757*1da57d55SToomas Soome
7587c478bd9Sstevel@tonic-gate rv = CERT_VerifyCertNow(sseip->lssei_certdbh, cert, checkSig,
7597c478bd9Sstevel@tonic-gate certUsage, NULL);
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate if ( rv != SECSuccess || isServer )
7627c478bd9Sstevel@tonic-gate return rv;
763*1da57d55SToomas Soome
7647c478bd9Sstevel@tonic-gate if ( LDAPSSL_AUTH_CNCHECK == sseip->lssei_ssl_strength )
7657c478bd9Sstevel@tonic-gate {
7667c478bd9Sstevel@tonic-gate /* cert is OK. This is the client side of an SSL connection.
7677c478bd9Sstevel@tonic-gate * Now check the name field in the cert against the desired hostname.
768*1da57d55SToomas Soome * NB: This is our only defense against Man-In-The-Middle (MITM)
7697c478bd9Sstevel@tonic-gate * attacks!
7707c478bd9Sstevel@tonic-gate */
7717c478bd9Sstevel@tonic-gate
7727c478bd9Sstevel@tonic-gate hostname = SSL_RevealURL( fd );
7737c478bd9Sstevel@tonic-gate
7747c478bd9Sstevel@tonic-gate if (hostname && hostname[0]) {
7757c478bd9Sstevel@tonic-gate rv = CERT_VerifyCertName(cert, hostname);
7767c478bd9Sstevel@tonic-gate } else {
7777c478bd9Sstevel@tonic-gate rv = SECFailure;
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate if (hostname)
7807c478bd9Sstevel@tonic-gate PORT_Free(hostname);
7817c478bd9Sstevel@tonic-gate if (rv != SECSuccess)
7827c478bd9Sstevel@tonic-gate PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate return((int)rv);
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate /*
7907c478bd9Sstevel@tonic-gate * called during SSL client auth. when server wants our cert and key.
7917c478bd9Sstevel@tonic-gate * return 0 if we succeeded and set *pRetCert and *pRetKey, -1 otherwise.
7927c478bd9Sstevel@tonic-gate * if -1 is returned SSL will proceed without sending a cert.
7937c478bd9Sstevel@tonic-gate */
7947c478bd9Sstevel@tonic-gate
7957c478bd9Sstevel@tonic-gate static int
get_clientauth_data(void * sessionarg,PRFileDesc * prfd,CERTDistNames * caNames,CERTCertificate ** pRetCert,SECKEYPrivateKey ** pRetKey)7967c478bd9Sstevel@tonic-gate get_clientauth_data( void *sessionarg, PRFileDesc *prfd,
7977c478bd9Sstevel@tonic-gate CERTDistNames *caNames, CERTCertificate **pRetCert,
7987c478bd9Sstevel@tonic-gate SECKEYPrivateKey **pRetKey )
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate {
8017c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip;
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate if (( ssip = (LDAPSSLSessionInfo *)sessionarg ) == NULL ) {
8047c478bd9Sstevel@tonic-gate return( -1 ); /* client auth. not enabled */
8057c478bd9Sstevel@tonic-gate }
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate return( get_keyandcert( ssip, pRetCert, pRetKey, NULL ));
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate static int
get_keyandcert(LDAPSSLSessionInfo * ssip,CERTCertificate ** pRetCert,SECKEYPrivateKey ** pRetKey,char ** errmsgp)8117c478bd9Sstevel@tonic-gate get_keyandcert( LDAPSSLSessionInfo *ssip,
8127c478bd9Sstevel@tonic-gate CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey,
8137c478bd9Sstevel@tonic-gate char **errmsgp )
8147c478bd9Sstevel@tonic-gate {
8157c478bd9Sstevel@tonic-gate CERTCertificate *cert;
8167c478bd9Sstevel@tonic-gate SECKEYPrivateKey *key;
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate if (( cert = PK11_FindCertFromNickname( ssip->lssei_certnickname, NULL ))
8197c478bd9Sstevel@tonic-gate == NULL ) {
8207c478bd9Sstevel@tonic-gate if ( errmsgp != NULL ) {
8217c478bd9Sstevel@tonic-gate *errmsgp = dgettext(TEXT_DOMAIN, "unable to find certificate");
8227c478bd9Sstevel@tonic-gate }
8237c478bd9Sstevel@tonic-gate return( -1 );
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate
8267c478bd9Sstevel@tonic-gate {
8277c478bd9Sstevel@tonic-gate PK11_SetPasswordFunc( get_keypassword );
8287c478bd9Sstevel@tonic-gate }
829*1da57d55SToomas Soome
8307c478bd9Sstevel@tonic-gate
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate if (( key = PK11_FindKeyByAnyCert( cert, (void *)ssip )) == NULL ) {
8337c478bd9Sstevel@tonic-gate CERT_DestroyCertificate( cert );
8347c478bd9Sstevel@tonic-gate if ( errmsgp != NULL ) {
8357c478bd9Sstevel@tonic-gate *errmsgp = dgettext(TEXT_DOMAIN, "bad key or key password");
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate return( -1 );
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate *pRetCert = cert;
8417c478bd9Sstevel@tonic-gate *pRetKey = key;
8427c478bd9Sstevel@tonic-gate return( 0 );
8437c478bd9Sstevel@tonic-gate }
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate
846*1da57d55SToomas Soome /*
8477c478bd9Sstevel@tonic-gate * This function returns the password to NSS.
8487c478bd9Sstevel@tonic-gate * This function is enable through PK11_SetPasswordFunc
8497c478bd9Sstevel@tonic-gate * only if pkcs functions are not being used.
850*1da57d55SToomas Soome */
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate static char *
get_keypassword(PK11SlotInfo * slot,PRBool retry,void * sessionarg)8537c478bd9Sstevel@tonic-gate get_keypassword( PK11SlotInfo *slot, PRBool retry, void *sessionarg )
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *ssip;
8567c478bd9Sstevel@tonic-gate
8577c478bd9Sstevel@tonic-gate if ( retry)
8587c478bd9Sstevel@tonic-gate return (NULL);
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate ssip = (LDAPSSLSessionInfo *)sessionarg;
8617c478bd9Sstevel@tonic-gate if ( NULL == ssip ) {
8627c478bd9Sstevel@tonic-gate return( NULL );
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate
8657c478bd9Sstevel@tonic-gate return( ssip->lssei_keypasswd );
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate
8697c478bd9Sstevel@tonic-gate /*
8707c478bd9Sstevel@tonic-gate * performs some basic checks on clientauth cert and key/password
8717c478bd9Sstevel@tonic-gate *
8727c478bd9Sstevel@tonic-gate * XXXmcs: could perform additional checks... see servers/slapd/ssl.c
8737c478bd9Sstevel@tonic-gate * 1) check expiration
8747c478bd9Sstevel@tonic-gate * 2) check that public key in cert matches private key
8757c478bd9Sstevel@tonic-gate * see ns/netsite/ldap/servers/slapd/ssl.c:slapd_ssl_init() for example code.
8767c478bd9Sstevel@tonic-gate */
8777c478bd9Sstevel@tonic-gate static int
check_clientauth_nicknames_and_passwd(LDAP * ld,LDAPSSLSessionInfo * ssip)8787c478bd9Sstevel@tonic-gate check_clientauth_nicknames_and_passwd( LDAP *ld, LDAPSSLSessionInfo *ssip )
8797c478bd9Sstevel@tonic-gate {
8807c478bd9Sstevel@tonic-gate char *errmsg = NULL;
8817c478bd9Sstevel@tonic-gate CERTCertificate *cert = NULL;
8827c478bd9Sstevel@tonic-gate SECKEYPrivateKey *key = NULL;
8837c478bd9Sstevel@tonic-gate int rv;
8847c478bd9Sstevel@tonic-gate
8857c478bd9Sstevel@tonic-gate rv = get_keyandcert( ssip, &cert, &key, &errmsg );
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate if ( rv != 0 ) {
8887c478bd9Sstevel@tonic-gate if ( errmsg != NULL ) {
8897c478bd9Sstevel@tonic-gate errmsg = strdup( errmsg );
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, errmsg );
8927c478bd9Sstevel@tonic-gate return( -1 );
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate if ( cert != NULL ) {
8967c478bd9Sstevel@tonic-gate CERT_DestroyCertificate( cert );
8977c478bd9Sstevel@tonic-gate }
8987c478bd9Sstevel@tonic-gate if ( key != NULL ) {
8997c478bd9Sstevel@tonic-gate SECKEY_DestroyPrivateKey( key );
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate return( 0 );
9027c478bd9Sstevel@tonic-gate }
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate #if 0 /* NOT_NEEDED_IN_LIBLDAP */
906*1da57d55SToomas Soome /* there are patches and kludges. this is both. force some linkers to
9077c478bd9Sstevel@tonic-gate * link this stuff in
9087c478bd9Sstevel@tonic-gate */
9097c478bd9Sstevel@tonic-gate int stubs_o_stuff( void )
9107c478bd9Sstevel@tonic-gate {
9117c478bd9Sstevel@tonic-gate PRExplodedTime exploded;
9127c478bd9Sstevel@tonic-gate PLArenaPool pool;
913*1da57d55SToomas Soome
9147c478bd9Sstevel@tonic-gate const char *name ="t";
9157c478bd9Sstevel@tonic-gate PRUint32 size = 0, align = 0;
9167c478bd9Sstevel@tonic-gate
9177c478bd9Sstevel@tonic-gate PR_ImplodeTime( &exploded );
9187c478bd9Sstevel@tonic-gate PL_InitArenaPool( &pool, name, size, align);
9197c478bd9Sstevel@tonic-gate PR_Cleanup();
9207c478bd9Sstevel@tonic-gate PR_fprintf((PRFileDesc*)stderr, "Bad IDEA!!");
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate return 0;
9237c478bd9Sstevel@tonic-gate
9247c478bd9Sstevel@tonic-gate }
9257c478bd9Sstevel@tonic-gate #endif /* NOT_NEEDED_IN_LIBLDAP */
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate /*
9297c478bd9Sstevel@tonic-gate * Import the file descriptor corresponding to the socket of an already
9307c478bd9Sstevel@tonic-gate * open LDAP connection into SSL, and update the socket and session
9317c478bd9Sstevel@tonic-gate * information accordingly.
9327c478bd9Sstevel@tonic-gate */
ldapssl_import_fd(LDAP * ld,int secure)9337c478bd9Sstevel@tonic-gate int ldapssl_import_fd ( LDAP *ld, int secure )
9347c478bd9Sstevel@tonic-gate {
9357c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei;
9367c478bd9Sstevel@tonic-gate PRLDAPSocketInfo soi;
9377c478bd9Sstevel@tonic-gate LDAPSSLSocketInfo *ssoip = NULL;
9387c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip;
9397c478bd9Sstevel@tonic-gate PRFileDesc *sslfd = NULL;
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate /*
9437c478bd9Sstevel@tonic-gate * Retrieve session info. so we can store a pointer to our session info.
9447c478bd9Sstevel@tonic-gate * in our socket info. later.
9457c478bd9Sstevel@tonic-gate */
9467c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof(sei));
9477c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
9487c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
9497c478bd9Sstevel@tonic-gate return( -1 );
9507c478bd9Sstevel@tonic-gate }
9517c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
9527c478bd9Sstevel@tonic-gate
9537c478bd9Sstevel@tonic-gate
9547c478bd9Sstevel@tonic-gate /*
9557c478bd9Sstevel@tonic-gate * Retrieve socket info. so we have the PRFileDesc.
9567c478bd9Sstevel@tonic-gate */
9577c478bd9Sstevel@tonic-gate memset( &soi, 0, sizeof(soi));
9587c478bd9Sstevel@tonic-gate soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
9597c478bd9Sstevel@tonic-gate if ( prldap_get_default_socket_info( ld, &soi ) != LDAP_SUCCESS ) {
9607c478bd9Sstevel@tonic-gate return( -1 );
9617c478bd9Sstevel@tonic-gate }
9627c478bd9Sstevel@tonic-gate
9637c478bd9Sstevel@tonic-gate /*
9647c478bd9Sstevel@tonic-gate * Allocate a structure to hold our socket-specific data.
9657c478bd9Sstevel@tonic-gate */
9667c478bd9Sstevel@tonic-gate if ( NULL == ( ssoip = PR_Calloc( 1, sizeof( LDAPSSLSocketInfo )))) {
9677c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error;
9687c478bd9Sstevel@tonic-gate }
9697c478bd9Sstevel@tonic-gate ssoip->soi_sessioninfo = sseip;
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate /*
9727c478bd9Sstevel@tonic-gate * Add SSL layer and let the standard NSPR to LDAP layer and enable SSL.
9737c478bd9Sstevel@tonic-gate */
9747c478bd9Sstevel@tonic-gate if (( sslfd = SSL_ImportFD( NULL, soi.soinfo_prfd )) == NULL ) {
9757c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error;
9767c478bd9Sstevel@tonic-gate }
9777c478bd9Sstevel@tonic-gate
9787c478bd9Sstevel@tonic-gate if ( SSL_OptionSet( sslfd, SSL_SECURITY, secure ) != SECSuccess ||
9797c478bd9Sstevel@tonic-gate SSL_OptionSet( sslfd, SSL_HANDSHAKE_AS_CLIENT, secure )
9807c478bd9Sstevel@tonic-gate != SECSuccess || ( secure && SSL_ResetHandshake( sslfd,
9817c478bd9Sstevel@tonic-gate PR_FALSE ) != SECSuccess )) {
9827c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error;
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate /*
9867c478bd9Sstevel@tonic-gate * Let the standard NSPR to LDAP layer know about the new socket and
9877c478bd9Sstevel@tonic-gate * our own socket-specific data.
9887c478bd9Sstevel@tonic-gate */
9897c478bd9Sstevel@tonic-gate soi.soinfo_prfd = sslfd;
9907c478bd9Sstevel@tonic-gate soi.soinfo_appdata = (void *)ssoip;
9917c478bd9Sstevel@tonic-gate if ( prldap_set_default_socket_info( ld, &soi ) != LDAP_SUCCESS ) {
9927c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error;
9937c478bd9Sstevel@tonic-gate }
9947c478bd9Sstevel@tonic-gate
9957c478bd9Sstevel@tonic-gate /*
9967c478bd9Sstevel@tonic-gate * Install certificate hook function.
9977c478bd9Sstevel@tonic-gate */
9987c478bd9Sstevel@tonic-gate if ( SSL_AuthCertificateHook( soi.soinfo_prfd,
9997c478bd9Sstevel@tonic-gate (SSLAuthCertificate)ldapssl_AuthCertificate,
10007c478bd9Sstevel@tonic-gate (void *)CERT_GetDefaultCertDB()) != 0 ) {
10017c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error;
10027c478bd9Sstevel@tonic-gate }
10037c478bd9Sstevel@tonic-gate
10047c478bd9Sstevel@tonic-gate if ( SSL_GetClientAuthDataHook( soi.soinfo_prfd,
10057c478bd9Sstevel@tonic-gate get_clientauth_data, sseip->lssei_certnickname ? sseip : NULL )
10067c478bd9Sstevel@tonic-gate != 0 ) {
10077c478bd9Sstevel@tonic-gate goto reset_socket_and_exit_with_error;
10087c478bd9Sstevel@tonic-gate }
10097c478bd9Sstevel@tonic-gate
10107c478bd9Sstevel@tonic-gate return 0;
10117c478bd9Sstevel@tonic-gate
10127c478bd9Sstevel@tonic-gate reset_socket_and_exit_with_error:
10137c478bd9Sstevel@tonic-gate if ( NULL != sslfd ) {
10147c478bd9Sstevel@tonic-gate /*
10157c478bd9Sstevel@tonic-gate * "Unimport" the socket from SSL, i.e. get rid of the upper layer of
10167c478bd9Sstevel@tonic-gate * the file descriptor stack, which represents SSL.
10177c478bd9Sstevel@tonic-gate */
10187c478bd9Sstevel@tonic-gate soi.soinfo_prfd = sslfd;
10197c478bd9Sstevel@tonic-gate sslfd = PR_PopIOLayer( soi.soinfo_prfd, PR_TOP_IO_LAYER );
10207c478bd9Sstevel@tonic-gate sslfd->dtor( sslfd );
10217c478bd9Sstevel@tonic-gate }
10227c478bd9Sstevel@tonic-gate if ( NULL != ssoip ) {
10237c478bd9Sstevel@tonic-gate ldapssl_free_socket_info( &ssoip );
10247c478bd9Sstevel@tonic-gate soi.soinfo_appdata = NULL;
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate prldap_set_default_socket_info( ld, &soi );
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate return( -1 );
10297c478bd9Sstevel@tonic-gate }
10307c478bd9Sstevel@tonic-gate
10317c478bd9Sstevel@tonic-gate
10327c478bd9Sstevel@tonic-gate /*
10337c478bd9Sstevel@tonic-gate * Reset an LDAP session from SSL to a non-secure status.
10347c478bd9Sstevel@tonic-gate * Basically, this function undoes the work done by ldapssl_install_routines.
10357c478bd9Sstevel@tonic-gate */
ldapssl_reset_to_nonsecure(LDAP * ld)10367c478bd9Sstevel@tonic-gate int ldapssl_reset_to_nonsecure ( LDAP *ld )
10377c478bd9Sstevel@tonic-gate {
10387c478bd9Sstevel@tonic-gate PRLDAPSessionInfo sei;
10397c478bd9Sstevel@tonic-gate LDAPSSLSessionInfo *sseip;
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns;
10427c478bd9Sstevel@tonic-gate int rc = 0;
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate /*
10457c478bd9Sstevel@tonic-gate * Retrieve session info.
10467c478bd9Sstevel@tonic-gate */
10477c478bd9Sstevel@tonic-gate memset( &sei, 0, sizeof(sei));
10487c478bd9Sstevel@tonic-gate sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
10497c478bd9Sstevel@tonic-gate if ( prldap_get_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
10507c478bd9Sstevel@tonic-gate return( -1 );
10517c478bd9Sstevel@tonic-gate }
10527c478bd9Sstevel@tonic-gate sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
10537c478bd9Sstevel@tonic-gate
10547c478bd9Sstevel@tonic-gate if ( sseip != NULL ) {
10557c478bd9Sstevel@tonic-gate /*
10567c478bd9Sstevel@tonic-gate * Reset the standard extended io functions.
10577c478bd9Sstevel@tonic-gate */
10587c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns));
10597c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
10607c478bd9Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns )
10617c478bd9Sstevel@tonic-gate < 0) {
10627c478bd9Sstevel@tonic-gate rc = -1;
10637c478bd9Sstevel@tonic-gate goto free_session_info;
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate /* reset socket, connect, and ioctl */
10677c478bd9Sstevel@tonic-gate iofns.lextiof_connect = sseip->lssei_std_functions.lssf_connect_fn;
10687c478bd9Sstevel@tonic-gate iofns.lextiof_close = sseip->lssei_std_functions.lssf_close_fn;
10697c478bd9Sstevel@tonic-gate iofns.lextiof_disposehandle =
10707c478bd9Sstevel@tonic-gate sseip->lssei_std_functions.lssf_disposehdl_fn;
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns )
10737c478bd9Sstevel@tonic-gate < 0) {
10747c478bd9Sstevel@tonic-gate rc = -1;
10757c478bd9Sstevel@tonic-gate goto free_session_info;
10767c478bd9Sstevel@tonic-gate }
10777c478bd9Sstevel@tonic-gate
10787c478bd9Sstevel@tonic-gate free_session_info:
10797c478bd9Sstevel@tonic-gate ldapssl_free_session_info( &sseip );
10807c478bd9Sstevel@tonic-gate sei.seinfo_appdata = NULL;
10817c478bd9Sstevel@tonic-gate if ( prldap_set_session_info( ld, NULL, &sei ) != LDAP_SUCCESS ) {
10827c478bd9Sstevel@tonic-gate rc = -1;
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate } /* if ( sseip && *sseip ) */
1085*1da57d55SToomas Soome
10867c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_OFF ) < 0 ) {
10877c478bd9Sstevel@tonic-gate return (-1);
10887c478bd9Sstevel@tonic-gate }
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate return rc;
10917c478bd9Sstevel@tonic-gate }
10927c478bd9Sstevel@tonic-gate
10937c478bd9Sstevel@tonic-gate
10947c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
10957c478bd9Sstevel@tonic-gate static void
_nss_initf_ipnodes(nss_db_params_t * p)10967c478bd9Sstevel@tonic-gate _nss_initf_ipnodes(nss_db_params_t *p)
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate static char *no_service = "";
10997c478bd9Sstevel@tonic-gate
11007c478bd9Sstevel@tonic-gate p->name = NSS_DBNAM_IPNODES;
11017c478bd9Sstevel@tonic-gate p->flags |= NSS_USE_DEFAULT_CONFIG;
11027c478bd9Sstevel@tonic-gate p->default_config = host_service == NULL ? no_service : host_service;
11037c478bd9Sstevel@tonic-gate }
11047c478bd9Sstevel@tonic-gate
11057c478bd9Sstevel@tonic-gate static void
_nss_initf_hosts(nss_db_params_t * p)11067c478bd9Sstevel@tonic-gate _nss_initf_hosts(nss_db_params_t *p)
11077c478bd9Sstevel@tonic-gate {
11087c478bd9Sstevel@tonic-gate static char *no_service = "";
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate p->name = NSS_DBNAM_HOSTS;
11117c478bd9Sstevel@tonic-gate p->flags |= NSS_USE_DEFAULT_CONFIG;
11127c478bd9Sstevel@tonic-gate p->default_config = host_service == NULL ? no_service : host_service;
11137c478bd9Sstevel@tonic-gate }
11147c478bd9Sstevel@tonic-gate
11157c478bd9Sstevel@tonic-gate static struct hostent *
_switch_gethostbyaddr_r(const char * addr,int len,int type,struct hostent * result,char * buffer,int buflen,int * h_errnop)11167c478bd9Sstevel@tonic-gate _switch_gethostbyaddr_r(const char *addr, int len, int type,
11177c478bd9Sstevel@tonic-gate struct hostent *result, char *buffer, int buflen,
11187c478bd9Sstevel@tonic-gate int *h_errnop)
11197c478bd9Sstevel@tonic-gate {
11207c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg;
11217c478bd9Sstevel@tonic-gate nss_status_t res;
11227c478bd9Sstevel@tonic-gate int (*str2ent)();
11237c478bd9Sstevel@tonic-gate void (*nss_initf)();
11247c478bd9Sstevel@tonic-gate nss_db_root_t *nss_db_root;
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate if (AF_INET == type) {
11277c478bd9Sstevel@tonic-gate str2ent = str2hostent;
11287c478bd9Sstevel@tonic-gate nss_initf = _nss_initf_hosts;
1129*1da57d55SToomas Soome nss_db_root = &db_root_hosts;
11307c478bd9Sstevel@tonic-gate } else if (AF_INET6 == type) {
11317c478bd9Sstevel@tonic-gate str2ent = str2hostent6;
11327c478bd9Sstevel@tonic-gate nss_initf = _nss_initf_ipnodes;
11337c478bd9Sstevel@tonic-gate nss_db_root = &db_root_ipnodes;
11347c478bd9Sstevel@tonic-gate } else {
11357c478bd9Sstevel@tonic-gate return NULL;
11367c478bd9Sstevel@tonic-gate }
11377c478bd9Sstevel@tonic-gate
11387c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2ent);
11397c478bd9Sstevel@tonic-gate
11407c478bd9Sstevel@tonic-gate arg.key.hostaddr.addr = addr;
11417c478bd9Sstevel@tonic-gate arg.key.hostaddr.len = len;
11427c478bd9Sstevel@tonic-gate arg.key.hostaddr.type = type;
11437c478bd9Sstevel@tonic-gate arg.stayopen = 0;
11447c478bd9Sstevel@tonic-gate
11457c478bd9Sstevel@tonic-gate res = nss_search(nss_db_root, nss_initf,
11467c478bd9Sstevel@tonic-gate NSS_DBOP_HOSTS_BYADDR, &arg);
11477c478bd9Sstevel@tonic-gate arg.status = res;
11487c478bd9Sstevel@tonic-gate *h_errnop = arg.h_errno;
11497c478bd9Sstevel@tonic-gate return (struct hostent *)NSS_XbyY_FINI(&arg);
11507c478bd9Sstevel@tonic-gate }
11517c478bd9Sstevel@tonic-gate
11527c478bd9Sstevel@tonic-gate /*
11537c478bd9Sstevel@tonic-gate * ns_gethostbyaddr is used to be a substitute gethostbyaddr for
11547c478bd9Sstevel@tonic-gate * libldap when ssl will need to determine the fully qualified
11557c478bd9Sstevel@tonic-gate * host name from an address when it is unsafe to use the normal
11567c478bd9Sstevel@tonic-gate * nameservice functions.
11577c478bd9Sstevel@tonic-gate *
11587c478bd9Sstevel@tonic-gate * Note that the ldap name service resolver calls this with the address as
11597c478bd9Sstevel@tonic-gate * a character string - which we must convert into address form.
11607c478bd9Sstevel@tonic-gate */
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11637c478bd9Sstevel@tonic-gate static LDAPHostEnt *
ns_gethostbyaddr(const char * addr,int len,int type,LDAPHostEnt * result,char * buffer,int buflen,int * statusp,void * extradata)11647c478bd9Sstevel@tonic-gate ns_gethostbyaddr(const char *addr, int len, int type,
11657c478bd9Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
11667c478bd9Sstevel@tonic-gate void *extradata)
11677c478bd9Sstevel@tonic-gate {
11687c478bd9Sstevel@tonic-gate LDAPHostEnt *ldap_hent;
11697c478bd9Sstevel@tonic-gate int h_errno;
11707c478bd9Sstevel@tonic-gate struct hostent h_ent;
11717c478bd9Sstevel@tonic-gate struct hostent *h_e = NULL;
11727c478bd9Sstevel@tonic-gate struct in_addr a;
11737c478bd9Sstevel@tonic-gate struct in6_addr a6;
11747c478bd9Sstevel@tonic-gate int inet_error; /* error returned by inet_pton */
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate
11777c478bd9Sstevel@tonic-gate if (addr == NULL || result == NULL || buffer == NULL ||
11787c478bd9Sstevel@tonic-gate (type != AF_INET && type != AF_INET6))
11797c478bd9Sstevel@tonic-gate return (NULL);
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate
11827c478bd9Sstevel@tonic-gate (void) memset(&h_ent, 0, sizeof (h_ent));
11837c478bd9Sstevel@tonic-gate
11847c478bd9Sstevel@tonic-gate if (AF_INET == type) {
11857c478bd9Sstevel@tonic-gate if (inet_pton(type, addr, &a.s_addr) == 1) {
11867c478bd9Sstevel@tonic-gate h_e = _switch_gethostbyaddr_r((char *)&a,
11877c478bd9Sstevel@tonic-gate sizeof (a.s_addr), type, &h_ent,
11887c478bd9Sstevel@tonic-gate buffer, buflen, &h_errno);
11897c478bd9Sstevel@tonic-gate }
11907c478bd9Sstevel@tonic-gate } else if (AF_INET6 == type) {
11917c478bd9Sstevel@tonic-gate if (inet_pton(type, addr, &a6.s6_addr) == 1) {
11927c478bd9Sstevel@tonic-gate h_e = _switch_gethostbyaddr_r((char *)&a6,
11937c478bd9Sstevel@tonic-gate sizeof (a6.s6_addr), type, &h_ent,
11947c478bd9Sstevel@tonic-gate buffer, buflen, &h_errno);
11957c478bd9Sstevel@tonic-gate }
11967c478bd9Sstevel@tonic-gate }
11977c478bd9Sstevel@tonic-gate
11987c478bd9Sstevel@tonic-gate if (h_e == NULL) {
11997c478bd9Sstevel@tonic-gate ldap_hent = NULL;
12007c478bd9Sstevel@tonic-gate } else {
12017c478bd9Sstevel@tonic-gate (void) memset(result, 0, sizeof (LDAPHostEnt));
12027c478bd9Sstevel@tonic-gate ldap_hent = result;
12037c478bd9Sstevel@tonic-gate result->ldaphe_name = h_e->h_name;
12047c478bd9Sstevel@tonic-gate result->ldaphe_aliases = h_e->h_aliases;
12057c478bd9Sstevel@tonic-gate result->ldaphe_addrtype = h_e->h_addrtype;
12067c478bd9Sstevel@tonic-gate result->ldaphe_length = h_e->h_length;
12077c478bd9Sstevel@tonic-gate result->ldaphe_addr_list = h_e->h_addr_list;
12087c478bd9Sstevel@tonic-gate }
12097c478bd9Sstevel@tonic-gate return (ldap_hent);
12107c478bd9Sstevel@tonic-gate }
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate /*
12137c478bd9Sstevel@tonic-gate * ldapssl_install_gethostbyaddr attempts to prevent recursion in
12147c478bd9Sstevel@tonic-gate * gethostbyaddr calls when an ip address is given to ssl. This ip address
12157c478bd9Sstevel@tonic-gate * must be resolved to a host name.
1216*1da57d55SToomas Soome *
12177c478bd9Sstevel@tonic-gate * For example, libsldap cannot use LDAP to resolve this address to a
12187c478bd9Sstevel@tonic-gate * name because of recursion. The caller is instructing libldap to skip
12197c478bd9Sstevel@tonic-gate * the specified name service when resolving addresses for the specified
12207c478bd9Sstevel@tonic-gate * ldap connection.
12217c478bd9Sstevel@tonic-gate *
12227c478bd9Sstevel@tonic-gate * Currently only ldap and dns name services always return fully qualified
12237c478bd9Sstevel@tonic-gate * names. The other name services (files, nis, and nisplus) will returned
12247c478bd9Sstevel@tonic-gate * fully qualified names if the host names are stored as fully qualified names
12257c478bd9Sstevel@tonic-gate * in these name services.
12267c478bd9Sstevel@tonic-gate *
12277c478bd9Sstevel@tonic-gate * Note:
12287c478bd9Sstevel@tonic-gate *
12297c478bd9Sstevel@tonic-gate * Since host_service applies to all connections, calling
12307c478bd9Sstevel@tonic-gate * ldapssl_install_gethostbyaddr with different name services to
12317c478bd9Sstevel@tonic-gate * skip will lead to unpredictable results.
12327c478bd9Sstevel@tonic-gate *
12337c478bd9Sstevel@tonic-gate * Returns:
12347c478bd9Sstevel@tonic-gate * 0 if success
12357c478bd9Sstevel@tonic-gate * -1 if failure
12367c478bd9Sstevel@tonic-gate */
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate int
ldapssl_install_gethostbyaddr(LDAP * ld,const char * skip)12397c478bd9Sstevel@tonic-gate ldapssl_install_gethostbyaddr(LDAP *ld, const char *skip)
12407c478bd9Sstevel@tonic-gate {
12417c478bd9Sstevel@tonic-gate enum __nsw_parse_err pserr;
12427c478bd9Sstevel@tonic-gate struct __nsw_switchconfig *conf;
12437c478bd9Sstevel@tonic-gate struct __nsw_lookup *lkp;
12447c478bd9Sstevel@tonic-gate struct ldap_dns_fns dns_fns;
12457c478bd9Sstevel@tonic-gate char *name_list = NULL;
12467c478bd9Sstevel@tonic-gate char *tmp;
12477c478bd9Sstevel@tonic-gate const char *name;
12487c478bd9Sstevel@tonic-gate int len;
12497c478bd9Sstevel@tonic-gate boolean_t got_skip = B_FALSE;
12507c478bd9Sstevel@tonic-gate
12517c478bd9Sstevel@tonic-gate /*
12527c478bd9Sstevel@tonic-gate * db_root_hosts.lock mutex is used to ensure that the name list
12537c478bd9Sstevel@tonic-gate * is not in use by the name service switch while we are updating
12547c478bd9Sstevel@tonic-gate * the host_service
12557c478bd9Sstevel@tonic-gate */
12567c478bd9Sstevel@tonic-gate
12577c478bd9Sstevel@tonic-gate (void) mutex_lock(&db_root_hosts.lock);
12587c478bd9Sstevel@tonic-gate conf = __nsw_getconfig("hosts", &pserr);
12597c478bd9Sstevel@tonic-gate if (conf == NULL) {
12607c478bd9Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock);
12617c478bd9Sstevel@tonic-gate return (0);
12627c478bd9Sstevel@tonic-gate }
12637c478bd9Sstevel@tonic-gate
12647c478bd9Sstevel@tonic-gate /* check for ldap and count other backends */
12657c478bd9Sstevel@tonic-gate for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) {
12667c478bd9Sstevel@tonic-gate name = lkp->service_name;
12677c478bd9Sstevel@tonic-gate if (strcmp(name, skip) == 0) {
12687c478bd9Sstevel@tonic-gate got_skip = B_TRUE;
12697c478bd9Sstevel@tonic-gate continue;
12707c478bd9Sstevel@tonic-gate }
12717c478bd9Sstevel@tonic-gate if (name_list == NULL)
12727c478bd9Sstevel@tonic-gate name_list = strdup(name);
12737c478bd9Sstevel@tonic-gate else {
12747c478bd9Sstevel@tonic-gate len = strlen(name_list);
12757c478bd9Sstevel@tonic-gate tmp = realloc(name_list, len + strlen(name) + 2);
12767c478bd9Sstevel@tonic-gate if (tmp == NULL) {
12777c478bd9Sstevel@tonic-gate free(name_list);
12787c478bd9Sstevel@tonic-gate name_list = NULL;
12797c478bd9Sstevel@tonic-gate } else {
12807c478bd9Sstevel@tonic-gate name_list = tmp;
12817c478bd9Sstevel@tonic-gate name_list[len++] = ' ';
12827c478bd9Sstevel@tonic-gate (void) strcpy(name_list+len, name);
12837c478bd9Sstevel@tonic-gate }
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate if (name_list == NULL) { /* alloc error */
12867c478bd9Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock);
12877c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf);
12887c478bd9Sstevel@tonic-gate return (-1);
12897c478bd9Sstevel@tonic-gate }
12907c478bd9Sstevel@tonic-gate }
12917c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf);
12927c478bd9Sstevel@tonic-gate if (!got_skip) {
12937c478bd9Sstevel@tonic-gate /*
12947c478bd9Sstevel@tonic-gate * Since skip name service not used for hosts, we do not need
12957c478bd9Sstevel@tonic-gate * to install our private address resolution function
12967c478bd9Sstevel@tonic-gate */
12977c478bd9Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock);
12987c478bd9Sstevel@tonic-gate if (name_list != NULL)
12997c478bd9Sstevel@tonic-gate free(name_list);
13007c478bd9Sstevel@tonic-gate return (0);
13017c478bd9Sstevel@tonic-gate }
13027c478bd9Sstevel@tonic-gate if (host_service != NULL)
13037c478bd9Sstevel@tonic-gate free(host_service);
13047c478bd9Sstevel@tonic-gate host_service = name_list;
13057c478bd9Sstevel@tonic-gate (void) mutex_unlock(&db_root_hosts.lock);
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate if (ldap_get_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
13087c478bd9Sstevel@tonic-gate return (-1);
13097c478bd9Sstevel@tonic-gate dns_fns.lddnsfn_gethostbyaddr = ns_gethostbyaddr;
13107c478bd9Sstevel@tonic-gate if (ldap_set_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
13117c478bd9Sstevel@tonic-gate return (-1);
13127c478bd9Sstevel@tonic-gate return (0);
13137c478bd9Sstevel@tonic-gate }
13147c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
13157c478bd9Sstevel@tonic-gate #endif /* NET_SSL */
1316