xref: /onnv-gate/usr/src/lib/libldap5/sources/ldap/ssldap/clientinit.c (revision 12646:6faf82030b5c)
10Sstevel@tonic-gate /*
2*12646SMilan.Jurik@Sun.COM  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
30Sstevel@tonic-gate  */
40Sstevel@tonic-gate 
50Sstevel@tonic-gate /*
60Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
70Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
80Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
90Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
100Sstevel@tonic-gate  *
110Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
120Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
130Sstevel@tonic-gate  * implied. See the License for the specific language governing
140Sstevel@tonic-gate  * rights and limitations under the License.
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
170Sstevel@tonic-gate  * March 31, 1998.
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
200Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
210Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
220Sstevel@tonic-gate  * Rights Reserved.
230Sstevel@tonic-gate  *
240Sstevel@tonic-gate  * Contributor(s):
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate  * clientinit.c
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #if defined(NET_SSL)
320Sstevel@tonic-gate 
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #if defined( _WINDOWS )
350Sstevel@tonic-gate #include <windows.h>
360Sstevel@tonic-gate #include "proto-ntutil.h"
370Sstevel@tonic-gate #endif
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #include <nspr.h>
400Sstevel@tonic-gate #include <plstr.h>
410Sstevel@tonic-gate #include <synch.h>
420Sstevel@tonic-gate #include <cert.h>
430Sstevel@tonic-gate #include <key.h>
440Sstevel@tonic-gate #include <ssl.h>
450Sstevel@tonic-gate #include <sslproto.h>
460Sstevel@tonic-gate #include <ldap.h>
470Sstevel@tonic-gate #include <ldappr.h>
480Sstevel@tonic-gate #include <solaris-int.h>
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #include <nss.h>
520Sstevel@tonic-gate 
530Sstevel@tonic-gate /* XXX:mhein The following is a workaround for the redefinition of */
540Sstevel@tonic-gate /*	     const problem on OSF.  Fix to be provided by NSS */
550Sstevel@tonic-gate /*	     This is a pretty benign workaround for us which */
560Sstevel@tonic-gate /*	     should not cause problems in the future even if */
570Sstevel@tonic-gate /*	     we forget to take it out :-) */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #ifdef OSF1V4D
600Sstevel@tonic-gate #ifndef __STDC__
610Sstevel@tonic-gate #  define __STDC__
620Sstevel@tonic-gate #endif /* __STDC__ */
630Sstevel@tonic-gate #endif /* OSF1V4D */
640Sstevel@tonic-gate 
650Sstevel@tonic-gate #ifndef FILE_PATHSEP
660Sstevel@tonic-gate #define FILE_PATHSEP '/'
670Sstevel@tonic-gate #endif
680Sstevel@tonic-gate 
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate  * StartTls()
710Sstevel@tonic-gate  */
720Sstevel@tonic-gate 
730Sstevel@tonic-gate #define START_TLS_OID "1.3.6.1.4.1.1466.20037"
740Sstevel@tonic-gate 
750Sstevel@tonic-gate static PRStatus local_SSLPLCY_Install(void);
760Sstevel@tonic-gate 
770Sstevel@tonic-gate /*
780Sstevel@tonic-gate  * This little tricky guy keeps us from initializing twice
790Sstevel@tonic-gate  */
800Sstevel@tonic-gate static int		inited = 0;
810Sstevel@tonic-gate #ifdef _SOLARIS_SDK
820Sstevel@tonic-gate mutex_t			inited_mutex = DEFAULTMUTEX;
830Sstevel@tonic-gate #else
840Sstevel@tonic-gate static mutex_t		inited_mutex = DEFAULTMUTEX;
850Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
860Sstevel@tonic-gate #if 0	/* UNNEEDED BY LIBLDAP */
870Sstevel@tonic-gate static char  tokDes[34] = "Internal (Software) Database     ";
880Sstevel@tonic-gate static char ptokDes[34] = "Internal (Software) Token        ";
890Sstevel@tonic-gate #endif	/* UNNEEDED BY LIBLDAP */
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 
920Sstevel@tonic-gate /* IN:					     */
930Sstevel@tonic-gate /* string:	/u/mhein/.netscape/mykey3.db */
940Sstevel@tonic-gate /* OUT:					     */
950Sstevel@tonic-gate /* dir: 	/u/mhein/.netscape/	     */
960Sstevel@tonic-gate /* prefix:	my			     */
970Sstevel@tonic-gate /* key:		key3.db			     */
980Sstevel@tonic-gate 
990Sstevel@tonic-gate static int
splitpath(char * string,char * dir,char * prefix,char * key)1000Sstevel@tonic-gate splitpath(char *string, char *dir, char *prefix, char *key) {
1010Sstevel@tonic-gate         char *k;
1020Sstevel@tonic-gate         char *s;
1030Sstevel@tonic-gate         char *d = string;
1040Sstevel@tonic-gate         char *l;
1050Sstevel@tonic-gate         int  len = 0;
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate         if (string == NULL)
1090Sstevel@tonic-gate                 return (-1);
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate         /* goto the end of the string, and walk backwards until */
1120Sstevel@tonic-gate         /* you get to the first pathseparator */
1130Sstevel@tonic-gate         len = PL_strlen(string);
1140Sstevel@tonic-gate         l = string + len - 1;
1150Sstevel@tonic-gate         while (l != string && *l != '/' && *l != '\\')
1160Sstevel@tonic-gate                         l--;
1170Sstevel@tonic-gate         /* search for the .db */
1180Sstevel@tonic-gate         if ((k = PL_strstr(l, ".db")) != NULL) {
1190Sstevel@tonic-gate                 /* now we are sitting on . of .db */
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate                 /* move backward to the first 'c' or 'k' */
1220Sstevel@tonic-gate                 /* indicating cert or key */
1230Sstevel@tonic-gate                 while (k != l && *k != 'c' && *k != 'k')
1240Sstevel@tonic-gate                         k--;
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate                 /* move backwards to the first path separator */
1270Sstevel@tonic-gate                 if (k != d && k > d)
1280Sstevel@tonic-gate                         s = k - 1;
1290Sstevel@tonic-gate                 while (s != d && *s != '/' && *s != '\\')
1300Sstevel@tonic-gate                         s--;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate                 /* if we are sitting on top of a path */
1330Sstevel@tonic-gate                 /* separator there is no prefix */
1340Sstevel@tonic-gate                 if (s + 1 == k) {
1350Sstevel@tonic-gate                         /* we know there is no prefix */
1360Sstevel@tonic-gate                         prefix = '\0';
1370Sstevel@tonic-gate                         PL_strcpy(key, k);
1380Sstevel@tonic-gate                         *k = '\0';
1390Sstevel@tonic-gate                         PL_strcpy(dir, d);
1400Sstevel@tonic-gate                 } else {
1410Sstevel@tonic-gate                         /* grab the prefix */
1420Sstevel@tonic-gate                         PL_strcpy(key, k);
1430Sstevel@tonic-gate                         *k = '\0';
1440Sstevel@tonic-gate                         PL_strcpy(prefix, ++s);
1450Sstevel@tonic-gate                         *s = '\0';
1460Sstevel@tonic-gate                         PL_strcpy(dir, d);
1470Sstevel@tonic-gate                 }
1480Sstevel@tonic-gate         } else {
1490Sstevel@tonic-gate                 /* neither *key[0-9].db nor *cert[0=9].db found */
1500Sstevel@tonic-gate                 return (-1);
1510Sstevel@tonic-gate         }
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	return (0);
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 
local_SSLPLCY_Install(void)1570Sstevel@tonic-gate static PRStatus local_SSLPLCY_Install(void)
1580Sstevel@tonic-gate {
1590Sstevel@tonic-gate 	SECStatus s;
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate #ifdef NS_DOMESTIC
1620Sstevel@tonic-gate 	s = NSS_SetDomesticPolicy();
1630Sstevel@tonic-gate #elif NS_EXPORT
1640Sstevel@tonic-gate 	s = NSS_SetExportPolicy();
1650Sstevel@tonic-gate #else
1660Sstevel@tonic-gate 	s = PR_FAILURE;
1670Sstevel@tonic-gate #endif
1680Sstevel@tonic-gate 	return s?PR_FAILURE:PR_SUCCESS;
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate static void
ldapssl_basic_init(void)1740Sstevel@tonic-gate ldapssl_basic_init( void )
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate #ifndef _SOLARIS_SDK
1770Sstevel@tonic-gate 	/*
1780Sstevel@tonic-gate 	 * NSPR is initialized in .init on SOLARIS
1790Sstevel@tonic-gate 	 */
1800Sstevel@tonic-gate     /* PR_Init() must to be called before everything else... */
1810Sstevel@tonic-gate     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
1820Sstevel@tonic-gate #endif
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate     PR_SetConcurrency( 4 );	/* work around for NSPR 3.x I/O hangs */
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate /*
1900Sstevel@tonic-gate  * Cover  functions for malloc(), calloc(), strdup() and free() that are
1910Sstevel@tonic-gate  * compatible with the NSS libraries (they seem to use the C runtime
1920Sstevel@tonic-gate  * library malloc/free so these functions are quite simple right now).
1930Sstevel@tonic-gate  */
1940Sstevel@tonic-gate static void *
ldapssl_malloc(size_t size)1950Sstevel@tonic-gate ldapssl_malloc( size_t size )
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate     void	*p;
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate     p = malloc( size );
2000Sstevel@tonic-gate     return p;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate static void *
ldapssl_calloc(int nelem,size_t elsize)2050Sstevel@tonic-gate ldapssl_calloc( int nelem, size_t elsize )
2060Sstevel@tonic-gate {
2070Sstevel@tonic-gate     void	*p;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate     p = calloc( nelem, elsize );
2100Sstevel@tonic-gate     return p;
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate static char *
ldapssl_strdup(const char * s)2150Sstevel@tonic-gate ldapssl_strdup( const char *s )
2160Sstevel@tonic-gate {
2170Sstevel@tonic-gate     char	*scopy;
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate     if ( NULL == s ) {
2200Sstevel@tonic-gate 	scopy = NULL;
2210Sstevel@tonic-gate     } else {
2220Sstevel@tonic-gate 	scopy = strdup( s );
2230Sstevel@tonic-gate     }
2240Sstevel@tonic-gate     return scopy;
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate static void
ldapssl_free(void ** pp)2290Sstevel@tonic-gate ldapssl_free( void **pp )
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate     if ( NULL != pp && NULL != *pp ) {
2320Sstevel@tonic-gate 	free( (void *)*pp );
2330Sstevel@tonic-gate 	*pp = NULL;
2340Sstevel@tonic-gate     }
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 
238*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
239*12646SMilan.Jurik@Sun.COM /*
240*12646SMilan.Jurik@Sun.COM  * Disable strict fork detection of NSS library to allow safe fork of
241*12646SMilan.Jurik@Sun.COM  * consumers. Otherwise NSS will not work after fork because it was not
242*12646SMilan.Jurik@Sun.COM  * deinitialized before fork and there is no safe way how to do it after fork.
243*12646SMilan.Jurik@Sun.COM  *
244*12646SMilan.Jurik@Sun.COM  * Return values:
245*12646SMilan.Jurik@Sun.COM  *     1 - DISABLED was already set, no modification to environment
246*12646SMilan.Jurik@Sun.COM  *     0 - successfully modified environment, old value saved to enval if there
247*12646SMilan.Jurik@Sun.COM  *         was some
248*12646SMilan.Jurik@Sun.COM  *    -1 - setenv or strdup failed, the environment was left unchanged
249*12646SMilan.Jurik@Sun.COM  *
250*12646SMilan.Jurik@Sun.COM  */
251*12646SMilan.Jurik@Sun.COM static int
update_nss_strict_fork_env(char ** enval)252*12646SMilan.Jurik@Sun.COM update_nss_strict_fork_env(char **enval)
253*12646SMilan.Jurik@Sun.COM {
254*12646SMilan.Jurik@Sun.COM 	char *temps = getenv("NSS_STRICT_NOFORK");
255*12646SMilan.Jurik@Sun.COM 	if (temps == NULL) {
256*12646SMilan.Jurik@Sun.COM 		*enval = NULL;
257*12646SMilan.Jurik@Sun.COM 	} else if (strncmp(temps, "DISABLED", 9) == 0) {
258*12646SMilan.Jurik@Sun.COM 		/* Do not need to set as DISABLED, it is already set. */
259*12646SMilan.Jurik@Sun.COM 		*enval = NULL;
260*12646SMilan.Jurik@Sun.COM 		return (1);
261*12646SMilan.Jurik@Sun.COM 	} else {
262*12646SMilan.Jurik@Sun.COM 		if ((*enval = ldapssl_strdup(temps)) == NULL)
263*12646SMilan.Jurik@Sun.COM 			return (-1);
264*12646SMilan.Jurik@Sun.COM 	}
265*12646SMilan.Jurik@Sun.COM 	return (setenv("NSS_STRICT_NOFORK", "DISABLED", 1));
266*12646SMilan.Jurik@Sun.COM }
267*12646SMilan.Jurik@Sun.COM 
268*12646SMilan.Jurik@Sun.COM /*
269*12646SMilan.Jurik@Sun.COM  * Reset environment variable NSS_STRICT_NOFORK to value before
270*12646SMilan.Jurik@Sun.COM  * update_nss_strict_fork_env() call or remove it from environment if it did
271*12646SMilan.Jurik@Sun.COM  * not exist.
272*12646SMilan.Jurik@Sun.COM  * NSS_STRICT_NOFORK=DISABLED is needed only during NSS initialization to
273*12646SMilan.Jurik@Sun.COM  * disable activation of atfork handler in NSS which is invalidating
274*12646SMilan.Jurik@Sun.COM  * initialization in child process after fork.
275*12646SMilan.Jurik@Sun.COM  */
276*12646SMilan.Jurik@Sun.COM static int
reset_nss_strict_fork_env(char * enval)277*12646SMilan.Jurik@Sun.COM reset_nss_strict_fork_env(char *enval)
278*12646SMilan.Jurik@Sun.COM {
279*12646SMilan.Jurik@Sun.COM 	if (enval != NULL) {
280*12646SMilan.Jurik@Sun.COM 		return (setenv("NSS_STRICT_NOFORK", enval, 1));
281*12646SMilan.Jurik@Sun.COM 	} else {
282*12646SMilan.Jurik@Sun.COM 		return (unsetenv("NSS_STRICT_NOFORK"));
283*12646SMilan.Jurik@Sun.COM 	}
284*12646SMilan.Jurik@Sun.COM }
285*12646SMilan.Jurik@Sun.COM #endif
286*12646SMilan.Jurik@Sun.COM 
287*12646SMilan.Jurik@Sun.COM 
2880Sstevel@tonic-gate static char *
buildDBName(const char * basename,const char * dbname)2890Sstevel@tonic-gate buildDBName(const char *basename, const char *dbname)
2900Sstevel@tonic-gate {
2910Sstevel@tonic-gate 	char		*result;
2920Sstevel@tonic-gate 	PRUint32	len, pathlen, addslash;
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	if (basename)
2950Sstevel@tonic-gate 	{
2960Sstevel@tonic-gate 	    if (( len = PL_strlen( basename )) > 3
2970Sstevel@tonic-gate 		&& PL_strcasecmp( ".db", basename + len - 3 ) == 0 ) {
2980Sstevel@tonic-gate 		return (ldapssl_strdup(basename));
2990Sstevel@tonic-gate 	    }
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	    pathlen = len;
3020Sstevel@tonic-gate 	    len = pathlen + PL_strlen(dbname) + 1;
3030Sstevel@tonic-gate 	    addslash = ( pathlen > 0 &&
3040Sstevel@tonic-gate 		(( *(basename + pathlen - 1) != FILE_PATHSEP ) ||
3050Sstevel@tonic-gate 		( *(basename + pathlen - 1) != '\\'  )));
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	    if ( addslash ) {
3080Sstevel@tonic-gate 		++len;
3090Sstevel@tonic-gate 	    }
3100Sstevel@tonic-gate 	    if (( result = ldapssl_malloc( len )) != NULL ) {
3110Sstevel@tonic-gate 		PL_strcpy( result, basename );
3120Sstevel@tonic-gate 		if ( addslash ) {
3130Sstevel@tonic-gate 		    *(result+pathlen) = FILE_PATHSEP;  /* replaces '\0' */
3140Sstevel@tonic-gate 		    ++pathlen;
3150Sstevel@tonic-gate 		}
3160Sstevel@tonic-gate 		PL_strcpy(result+pathlen, dbname);
3170Sstevel@tonic-gate 	    }
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	}
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	return result;
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate char *
GetCertDBName(void * alias,int dbVersion)3260Sstevel@tonic-gate GetCertDBName(void *alias, int dbVersion)
3270Sstevel@tonic-gate {
3280Sstevel@tonic-gate     char		*source;
3290Sstevel@tonic-gate     char dbname[128];
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate     source = (char *)alias;
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate     if (!source)
3340Sstevel@tonic-gate     {
3350Sstevel@tonic-gate 	source = "";
3360Sstevel@tonic-gate     }
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate     sprintf(dbname, "cert%d.db",dbVersion);
3390Sstevel@tonic-gate     return(buildDBName(source, dbname));
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate  * return database name by appending "dbname" to "path".
3460Sstevel@tonic-gate  * this code doesn't need to be terribly efficient (not called often).
3470Sstevel@tonic-gate  */
3480Sstevel@tonic-gate /* XXXceb this is the old function.  To be removed eventually */
3490Sstevel@tonic-gate static char *
GetDBName(const char * dbname,const char * path)3500Sstevel@tonic-gate GetDBName(const char *dbname, const char *path)
3510Sstevel@tonic-gate {
3520Sstevel@tonic-gate     char		*result;
3530Sstevel@tonic-gate     PRUint32	len, pathlen;
3540Sstevel@tonic-gate     int		addslash;
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate     if ( dbname == NULL ) {
3570Sstevel@tonic-gate 	dbname = "";
3580Sstevel@tonic-gate     }
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate     if ((path == NULL) || (*path == 0)) {
3610Sstevel@tonic-gate 	result = ldapssl_strdup(dbname);
3620Sstevel@tonic-gate     } else {
3630Sstevel@tonic-gate 	pathlen = PL_strlen(path);
3640Sstevel@tonic-gate 	len = pathlen + PL_strlen(dbname) + 1;
3650Sstevel@tonic-gate 	addslash = ( path[pathlen - 1] != '/' );
3660Sstevel@tonic-gate 	if ( addslash ) {
3670Sstevel@tonic-gate 	    ++len;
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 	if (( result = ldapssl_malloc( len )) != NULL ) {
3700Sstevel@tonic-gate 	    PL_strcpy( result, path );
3710Sstevel@tonic-gate 	    if ( addslash ) {
3720Sstevel@tonic-gate 		*(result+pathlen) = '/';  /* replaces '\0' */
3730Sstevel@tonic-gate 		++pathlen;
3740Sstevel@tonic-gate 	    }
3750Sstevel@tonic-gate 	    PL_strcpy(result+pathlen, dbname);
3760Sstevel@tonic-gate 	}
3770Sstevel@tonic-gate     }
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate     return result;
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate /*
3830Sstevel@tonic-gate  * Initialize ns/security so it can be used for SSL client authentication.
3840Sstevel@tonic-gate  * It is safe to call this more than once.
3850Sstevel@tonic-gate  *
3860Sstevel@tonic-gate  * If needkeydb == 0, no key database is opened and SSL server authentication
3870Sstevel@tonic-gate  * is supported but not client authentication.
3880Sstevel@tonic-gate  *
3890Sstevel@tonic-gate  * If "certdbpath" is NULL or "", the default cert. db is used (typically
3900Sstevel@tonic-gate  * ~/.netscape/cert7.db).
3910Sstevel@tonic-gate  *
3920Sstevel@tonic-gate  * If "certdbpath" ends with ".db" (case-insensitive compare), then
3930Sstevel@tonic-gate  * it is assumed to be a full path to the cert. db file; otherwise,
3940Sstevel@tonic-gate  * it is assumed to be a directory that contains a file called
3950Sstevel@tonic-gate  * "cert7.db" or "cert.db".
3960Sstevel@tonic-gate  *
3970Sstevel@tonic-gate  * If certdbhandle is non-NULL, it is assumed to be a pointer to a
3980Sstevel@tonic-gate  * SECCertDBHandle structure.  It is fine to pass NULL since this
3990Sstevel@tonic-gate  * routine will allocate one for you (CERT_GetDefaultDB() can be
4000Sstevel@tonic-gate  * used to retrieve the cert db handle).
4010Sstevel@tonic-gate  *
4020Sstevel@tonic-gate  * If "keydbpath" is NULL or "", the default key db is used (typically
4030Sstevel@tonic-gate  * ~/.netscape/key3.db).
4040Sstevel@tonic-gate  *
4050Sstevel@tonic-gate  * If "keydbpath" ends with ".db" (case-insensitive compare), then
4060Sstevel@tonic-gate  * it is assumed to be a full path to the key db file; otherwise,
4070Sstevel@tonic-gate  * it is assumed to be a directory that contains a file called
4080Sstevel@tonic-gate  * "key3.db"
4090Sstevel@tonic-gate  *
4100Sstevel@tonic-gate  * If certdbhandle is non-NULL< it is assumed to be a pointed to a
4110Sstevel@tonic-gate  * SECKEYKeyDBHandle structure.  It is fine to pass NULL since this
4120Sstevel@tonic-gate  * routine will allocate one for you (SECKEY_GetDefaultDB() can be
4130Sstevel@tonic-gate  * used to retrieve the cert db handle).
4140Sstevel@tonic-gate  */
4150Sstevel@tonic-gate int
4160Sstevel@tonic-gate LDAP_CALL
ldapssl_clientauth_init(const char * certdbpath,void * certdbhandle,const int needkeydb,const char * keydbpath,void * keydbhandle)4170Sstevel@tonic-gate ldapssl_clientauth_init( const char *certdbpath, void *certdbhandle,
4180Sstevel@tonic-gate     const int needkeydb, const char *keydbpath, void *keydbhandle )
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate {
4210Sstevel@tonic-gate     int	rc;
422*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
423*12646SMilan.Jurik@Sun.COM     char *enval;
424*12646SMilan.Jurik@Sun.COM     int rcenv = 0;
425*12646SMilan.Jurik@Sun.COM #endif
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate     /*
4280Sstevel@tonic-gate      *     LDAPDebug(LDAP_DEBUG_TRACE, "ldapssl_clientauth_init\n",0 ,0 ,0);
4290Sstevel@tonic-gate      */
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate     mutex_lock(&inited_mutex);
4320Sstevel@tonic-gate     if ( inited ) {
4330Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
4340Sstevel@tonic-gate 	return( 0 );
4350Sstevel@tonic-gate     }
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate     ldapssl_basic_init();
4380Sstevel@tonic-gate 
439*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
440*12646SMilan.Jurik@Sun.COM     if ((rcenv = update_nss_strict_fork_env(&enval)) == -1) {
441*12646SMilan.Jurik@Sun.COM 	mutex_unlock(&inited_mutex);
442*12646SMilan.Jurik@Sun.COM 	return (-1);
443*12646SMilan.Jurik@Sun.COM     }
444*12646SMilan.Jurik@Sun.COM #endif
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate     /* Open the certificate database */
4470Sstevel@tonic-gate     rc = NSS_Init(certdbpath);
448*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
449*12646SMilan.Jurik@Sun.COM     /* Error from NSS_Init() more important! */
450*12646SMilan.Jurik@Sun.COM     if ((rcenv != 1) && (reset_nss_strict_fork_env(enval) != 0) && (rc == 0)) {
451*12646SMilan.Jurik@Sun.COM 	ldapssl_free(&enval);
452*12646SMilan.Jurik@Sun.COM 	mutex_unlock(&inited_mutex);
453*12646SMilan.Jurik@Sun.COM 	return (-1);
454*12646SMilan.Jurik@Sun.COM     }
455*12646SMilan.Jurik@Sun.COM     ldapssl_free(&enval);
456*12646SMilan.Jurik@Sun.COM #endif
4570Sstevel@tonic-gate     if (rc != 0) {
4580Sstevel@tonic-gate 	if ((rc = PR_GetError()) >= 0)
4590Sstevel@tonic-gate 	    rc = -1;
4600Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
4610Sstevel@tonic-gate 	return (rc);
4620Sstevel@tonic-gate     }
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate     if (SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE)
4650Sstevel@tonic-gate 	    || SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE)) {
4660Sstevel@tonic-gate 	if (( rc = PR_GetError()) >= 0 ) {
4670Sstevel@tonic-gate 	    rc = -1;
4680Sstevel@tonic-gate 	}
4690Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
4700Sstevel@tonic-gate 	return( rc );
4710Sstevel@tonic-gate     }
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate #if defined(NS_DOMESTIC)
4760Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
4770Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
4780Sstevel@tonic-gate       return( -1 );
4790Sstevel@tonic-gate     }
4800Sstevel@tonic-gate #elif(NS_EXPORT)
4810Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
4820Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
4830Sstevel@tonic-gate       return( -1 );
4840Sstevel@tonic-gate     }
4850Sstevel@tonic-gate #else
4860Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
4870Sstevel@tonic-gate     return( -1 );
4880Sstevel@tonic-gate #endif
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate     inited = 1;
4910Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate     return( 0 );
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate }
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate /*
4980Sstevel@tonic-gate  * Initialize ns/security so it can be used for SSL client authentication.
4990Sstevel@tonic-gate  * It is safe to call this more than once.
5000Sstevel@tonic-gate  *
5010Sstevel@tonic-gate  * If needkeydb == 0, no key database is opened and SSL server authentication
5020Sstevel@tonic-gate  * is supported but not client authentication.
5030Sstevel@tonic-gate  *
5040Sstevel@tonic-gate  * If "certdbpath" is NULL or "", the default cert. db is used (typically
5050Sstevel@tonic-gate  * ~/.netscape/cert7.db).
5060Sstevel@tonic-gate  *
5070Sstevel@tonic-gate  * If "certdbpath" ends with ".db" (case-insensitive compare), then
5080Sstevel@tonic-gate  * it is assumed to be a full path to the cert. db file; otherwise,
5090Sstevel@tonic-gate  * it is assumed to be a directory that contains a file called
5100Sstevel@tonic-gate  * "cert7.db" or "cert.db".
5110Sstevel@tonic-gate  *
5120Sstevel@tonic-gate  * If certdbhandle is non-NULL, it is assumed to be a pointer to a
5130Sstevel@tonic-gate  * SECCertDBHandle structure.  It is fine to pass NULL since this
5140Sstevel@tonic-gate  * routine will allocate one for you (CERT_GetDefaultDB() can be
5150Sstevel@tonic-gate  * used to retrieve the cert db handle).
5160Sstevel@tonic-gate  *
5170Sstevel@tonic-gate  * If "keydbpath" is NULL or "", the default key db is used (typically
5180Sstevel@tonic-gate  * ~/.netscape/key3.db).
5190Sstevel@tonic-gate  *
5200Sstevel@tonic-gate  * If "keydbpath" ends with ".db" (case-insensitive compare), then
5210Sstevel@tonic-gate  * it is assumed to be a full path to the key db file; otherwise,
5220Sstevel@tonic-gate  * it is assumed to be a directory that contains a file called
5230Sstevel@tonic-gate  * "key3.db"
5240Sstevel@tonic-gate  *
5250Sstevel@tonic-gate  * If certdbhandle is non-NULL< it is assumed to be a pointed to a
5260Sstevel@tonic-gate  * SECKEYKeyDBHandle structure.  It is fine to pass NULL since this
5270Sstevel@tonic-gate  * routine will allocate one for you (SECKEY_GetDefaultDB() can be
5280Sstevel@tonic-gate  * used to retrieve the cert db handle).  */
5290Sstevel@tonic-gate int
5300Sstevel@tonic-gate LDAP_CALL
ldapssl_advclientauth_init(const char * certdbpath,void * certdbhandle,const int needkeydb,const char * keydbpath,void * keydbhandle,const int needsecmoddb,const char * secmoddbpath,const int sslstrength)5310Sstevel@tonic-gate ldapssl_advclientauth_init(
5320Sstevel@tonic-gate     const char *certdbpath, void *certdbhandle,
5330Sstevel@tonic-gate     const int needkeydb, const char *keydbpath, void *keydbhandle,
5340Sstevel@tonic-gate     const int needsecmoddb, const char *secmoddbpath,
5350Sstevel@tonic-gate     const int sslstrength )
5360Sstevel@tonic-gate {
5370Sstevel@tonic-gate     int	rc;
538*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
539*12646SMilan.Jurik@Sun.COM     char *enval;
540*12646SMilan.Jurik@Sun.COM     int rcenv = 0;
541*12646SMilan.Jurik@Sun.COM #endif
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate     mutex_lock(&inited_mutex);
5440Sstevel@tonic-gate     if ( inited ) {
5450Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
5460Sstevel@tonic-gate 	return( 0 );
5470Sstevel@tonic-gate     }
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate     /*
5500Sstevel@tonic-gate      *    LDAPDebug(LDAP_DEBUG_TRACE, "ldapssl_advclientauth_init\n",0 ,0 ,0);
5510Sstevel@tonic-gate      */
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate     ldapssl_basic_init();
5540Sstevel@tonic-gate 
555*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
556*12646SMilan.Jurik@Sun.COM     if ((rcenv = update_nss_strict_fork_env(&enval)) == -1) {
557*12646SMilan.Jurik@Sun.COM 	mutex_unlock(&inited_mutex);
558*12646SMilan.Jurik@Sun.COM 	return (-1);
559*12646SMilan.Jurik@Sun.COM     }
560*12646SMilan.Jurik@Sun.COM #endif
561*12646SMilan.Jurik@Sun.COM 
5620Sstevel@tonic-gate     rc = NSS_Init(certdbpath);
563*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
564*12646SMilan.Jurik@Sun.COM     /* Error from NSS_Init() more important! */
565*12646SMilan.Jurik@Sun.COM     if ((rcenv != 1) && (reset_nss_strict_fork_env(enval) != 0) && (rc == 0)) {
566*12646SMilan.Jurik@Sun.COM 	ldapssl_free(&enval);
567*12646SMilan.Jurik@Sun.COM 	mutex_unlock(&inited_mutex);
568*12646SMilan.Jurik@Sun.COM 	return (-1);
569*12646SMilan.Jurik@Sun.COM     }
570*12646SMilan.Jurik@Sun.COM     ldapssl_free(&enval);
571*12646SMilan.Jurik@Sun.COM #endif
5720Sstevel@tonic-gate     if (rc != 0) {
5730Sstevel@tonic-gate 	if ((rc = PR_GetError()) >= 0)
5740Sstevel@tonic-gate 	    rc = -1;
5750Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
5760Sstevel@tonic-gate 	return (rc);
5770Sstevel@tonic-gate     }
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate #if defined(NS_DOMESTIC)
5800Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
5810Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
5820Sstevel@tonic-gate       return( -1 );
5830Sstevel@tonic-gate     }
5840Sstevel@tonic-gate #elif(NS_EXPORT)
5850Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
5860Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
5870Sstevel@tonic-gate       return( -1 );
5880Sstevel@tonic-gate     }
5890Sstevel@tonic-gate #else
5900Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
5910Sstevel@tonic-gate     return( -1 );
5920Sstevel@tonic-gate #endif
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate     inited = 1;
5950Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate     return( ldapssl_set_strength( NULL, sslstrength));
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate /*
6030Sstevel@tonic-gate  * Initialize ns/security so it can be used for SSL client authentication.
6040Sstevel@tonic-gate  * It is safe to call this more than once.
6050Sstevel@tonic-gate   */
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate /*
6080Sstevel@tonic-gate  * XXXceb  This is a hack until the new IO functions are done.
6090Sstevel@tonic-gate  * this function lives in ldapsinit.c
6100Sstevel@tonic-gate  */
6110Sstevel@tonic-gate void set_using_pkcs_functions( int val );
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate int
6140Sstevel@tonic-gate LDAP_CALL
ldapssl_pkcs_init(const struct ldapssl_pkcs_fns * pfns)6150Sstevel@tonic-gate ldapssl_pkcs_init( const struct ldapssl_pkcs_fns *pfns )
6160Sstevel@tonic-gate {
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate     char		*certdbName, *s, *keydbpath;
6190Sstevel@tonic-gate     char		*certdbPrefix, *keydbPrefix;
6200Sstevel@tonic-gate     char		*confDir, *keydbName;
6210Sstevel@tonic-gate     static char         *secmodname =  "secmod.db";
6220Sstevel@tonic-gate     int			rc;
623*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
624*12646SMilan.Jurik@Sun.COM     char *enval;
625*12646SMilan.Jurik@Sun.COM     int rcenv = 0;
626*12646SMilan.Jurik@Sun.COM #endif
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate     mutex_lock(&inited_mutex);
6290Sstevel@tonic-gate     if ( inited ) {
6300Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
6310Sstevel@tonic-gate 	return( 0 );
6320Sstevel@tonic-gate     }
6330Sstevel@tonic-gate /*
6340Sstevel@tonic-gate  * XXXceb  This is a hack until the new IO functions are done.
6350Sstevel@tonic-gate  * this function MUST be called before ldap_enable_clienauth.
6360Sstevel@tonic-gate  *
6370Sstevel@tonic-gate  */
6380Sstevel@tonic-gate     set_using_pkcs_functions( 1 );
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate     /*
6410Sstevel@tonic-gate      *    LDAPDebug(LDAP_DEBUG_TRACE, "ldapssl_pkcs_init\n",0 ,0 ,0);
6420Sstevel@tonic-gate      */
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate     ldapssl_basic_init();
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate     pfns->pkcs_getcertpath( NULL, &s);
6480Sstevel@tonic-gate     confDir = ldapssl_strdup( s );
6490Sstevel@tonic-gate     certdbPrefix = ldapssl_strdup( s );
6500Sstevel@tonic-gate     certdbName = ldapssl_strdup( s );
6510Sstevel@tonic-gate     *certdbPrefix = 0;
6520Sstevel@tonic-gate     splitpath(s, confDir, certdbPrefix, certdbName);
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate     pfns->pkcs_getkeypath( NULL, &s);
6550Sstevel@tonic-gate     keydbpath = ldapssl_strdup( s );
6560Sstevel@tonic-gate     keydbPrefix = ldapssl_strdup( s );
6570Sstevel@tonic-gate     keydbName = ldapssl_strdup( s );
6580Sstevel@tonic-gate     *keydbPrefix = 0;
6590Sstevel@tonic-gate     splitpath(s, keydbpath, keydbPrefix, keydbName);
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate     /* verify confDir == keydbpath and adjust as necessary */
6630Sstevel@tonic-gate     ldapssl_free((void **)&certdbName);
6640Sstevel@tonic-gate     ldapssl_free((void **)&keydbName);
6650Sstevel@tonic-gate     ldapssl_free((void **)&keydbpath);
6660Sstevel@tonic-gate 
667*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
668*12646SMilan.Jurik@Sun.COM     if ((rcenv = update_nss_strict_fork_env(&enval)) == -1) {
669*12646SMilan.Jurik@Sun.COM 	mutex_unlock(&inited_mutex);
670*12646SMilan.Jurik@Sun.COM 	return (-1);
671*12646SMilan.Jurik@Sun.COM     }
672*12646SMilan.Jurik@Sun.COM #endif
673*12646SMilan.Jurik@Sun.COM 
6740Sstevel@tonic-gate     rc = NSS_Initialize(confDir,certdbPrefix,keydbPrefix,secmodname,
6750Sstevel@tonic-gate 		NSS_INIT_READONLY);
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate     ldapssl_free((void **)&certdbPrefix);
6780Sstevel@tonic-gate     ldapssl_free((void **)&keydbPrefix);
6790Sstevel@tonic-gate     ldapssl_free((void **)&confDir);
680*12646SMilan.Jurik@Sun.COM 
681*12646SMilan.Jurik@Sun.COM #ifdef _SOLARIS_SDK
682*12646SMilan.Jurik@Sun.COM     /* Error from NSS_Initialize() more important! */
683*12646SMilan.Jurik@Sun.COM     if ((rcenv != 1) && (reset_nss_strict_fork_env(enval) != 0) && (rc == 0)) {
684*12646SMilan.Jurik@Sun.COM 	ldapssl_free(&enval);
685*12646SMilan.Jurik@Sun.COM 	mutex_unlock(&inited_mutex);
686*12646SMilan.Jurik@Sun.COM 	return (-1);
687*12646SMilan.Jurik@Sun.COM     }
688*12646SMilan.Jurik@Sun.COM     ldapssl_free(&enval);
689*12646SMilan.Jurik@Sun.COM #endif
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate     if (rc != 0) {
6920Sstevel@tonic-gate 	if ((rc = PR_GetError()) >= 0)
6930Sstevel@tonic-gate 	    rc = -1;
6940Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
6950Sstevel@tonic-gate 	return (rc);
6960Sstevel@tonic-gate     }
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate #if 0	/* UNNEEDED BY LIBLDAP */
7000Sstevel@tonic-gate     /* this is odd */
7010Sstevel@tonic-gate     PK11_ConfigurePKCS11(NULL, NULL, tokDes, ptokDes, NULL, NULL, NULL, NULL, 0, 0 );
7020Sstevel@tonic-gate #endif	/* UNNEEDED BY LIBLDAP */
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate     if (SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE)
7050Sstevel@tonic-gate 	|| SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE)) {
7060Sstevel@tonic-gate 	if (( rc = PR_GetError()) >= 0 ) {
7070Sstevel@tonic-gate 	    rc = -1;
7080Sstevel@tonic-gate 	}
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
7110Sstevel@tonic-gate 	return( rc );
7120Sstevel@tonic-gate     }
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate #if defined(NS_DOMESTIC)
7150Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
7160Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
7170Sstevel@tonic-gate       return( -1 );
7180Sstevel@tonic-gate     }
7190Sstevel@tonic-gate #elif(NS_EXPORT)
7200Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
7210Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
7220Sstevel@tonic-gate       return( -1 );
7230Sstevel@tonic-gate     }
7240Sstevel@tonic-gate #else
7250Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
7260Sstevel@tonic-gate     return( -1 );
7270Sstevel@tonic-gate #endif
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate     inited = 1;
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate     if ( certdbName != NULL ) {
7320Sstevel@tonic-gate 	ldapssl_free((void **) &certdbName );
7330Sstevel@tonic-gate     }
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate     return( ldapssl_set_strength( NULL, LDAPSSL_AUTH_CNCHECK));
7360Sstevel@tonic-gate }
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate /*
7400Sstevel@tonic-gate  * ldapssl_client_init() is a server-authentication only version of
7410Sstevel@tonic-gate  * ldapssl_clientauth_init().
7420Sstevel@tonic-gate  */
7430Sstevel@tonic-gate int
7440Sstevel@tonic-gate LDAP_CALL
ldapssl_client_init(const char * certdbpath,void * certdbhandle)7450Sstevel@tonic-gate ldapssl_client_init(const char* certdbpath, void *certdbhandle )
7460Sstevel@tonic-gate {
7470Sstevel@tonic-gate     return( ldapssl_clientauth_init( certdbpath, certdbhandle,
7480Sstevel@tonic-gate 	    0, NULL, NULL ));
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate /*
7510Sstevel@tonic-gate  * ldapssl_serverauth_init() is a server-authentication only version of
7520Sstevel@tonic-gate  * ldapssl_clientauth_init().  This function allows the sslstrength
7530Sstevel@tonic-gate  * to be passed in.  The sslstrength can take one of the following
7540Sstevel@tonic-gate  * values:
7550Sstevel@tonic-gate  *      LDAPSSL_AUTH_WEAK: indicate that you accept the server's
7560Sstevel@tonic-gate  *                         certificate without checking the CA who
7570Sstevel@tonic-gate  *                         issued the certificate
7580Sstevel@tonic-gate  *      LDAPSSL_AUTH_CERT: indicates that you accept the server's
7590Sstevel@tonic-gate  *                         certificate only if you trust the CA who
7600Sstevel@tonic-gate  *                         issued the certificate
7610Sstevel@tonic-gate  *      LDAPSSL_AUTH_CNCHECK:
7620Sstevel@tonic-gate                            indicates that you accept the server's
7630Sstevel@tonic-gate  *                         certificate only if you trust the CA who
7640Sstevel@tonic-gate  *                         issued the certificate and if the value
7650Sstevel@tonic-gate  *                         of the cn attribute in the DNS hostname
7660Sstevel@tonic-gate  *                         of the server
7670Sstevel@tonic-gate  */
7680Sstevel@tonic-gate int
7690Sstevel@tonic-gate LDAP_CALL
ldapssl_serverauth_init(const char * certdbpath,void * certdbhandle,const int sslstrength)7700Sstevel@tonic-gate ldapssl_serverauth_init(const char* certdbpath,
7710Sstevel@tonic-gate                      void *certdbhandle,
7720Sstevel@tonic-gate                      const int sslstrength )
7730Sstevel@tonic-gate {
7740Sstevel@tonic-gate     if ( ldapssl_set_strength( NULL, sslstrength ) != 0) {
7750Sstevel@tonic-gate         return ( -1 );
7760Sstevel@tonic-gate     }
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate     return( ldapssl_clientauth_init( certdbpath, certdbhandle,
7790Sstevel@tonic-gate             0, NULL, NULL ));
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate /*
7830Sstevel@tonic-gate  * Function that makes an asynchronous Start TLS extended operation request.
7840Sstevel@tonic-gate  */
ldapssl_tls_start(LDAP * ld,int * msgidp)7850Sstevel@tonic-gate static int ldapssl_tls_start(LDAP *ld, int *msgidp)
7860Sstevel@tonic-gate {
7870Sstevel@tonic-gate     int version, rc;
7880Sstevel@tonic-gate     BerValue extreq_data;
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate     /* Start TLS extended operation requires an absent "requestValue" field. */
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate     extreq_data.bv_val = NULL;
7930Sstevel@tonic-gate     extreq_data.bv_len = 0;
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate     /* Make sure version is set to LDAPv3 for extended operations to be
7960Sstevel@tonic-gate        supported. */
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate     version = LDAP_VERSION3;
7990Sstevel@tonic-gate     ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate     /* Send the Start TLS request (OID: 1.3.6.1.4.1.1466.20037) */
8020Sstevel@tonic-gate     rc = ldap_extended_operation( ld, START_TLS_OID, &extreq_data,
8030Sstevel@tonic-gate               NULL, NULL, msgidp );
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate     return rc;
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate /*
8100Sstevel@tonic-gate  * Function that enables SSL on an already open non-secured LDAP connection.
8110Sstevel@tonic-gate  * (i.e. the connection is henceforth secured)
8120Sstevel@tonic-gate  */
ldapssl_enableSSL_on_open_connection(LDAP * ld,int defsecure,char * certdbpath,char * keydbpath)8130Sstevel@tonic-gate static int ldapssl_enableSSL_on_open_connection(LDAP *ld, int defsecure,
8140Sstevel@tonic-gate 	char *certdbpath, char *keydbpath)
8150Sstevel@tonic-gate {
8160Sstevel@tonic-gate     PRLDAPSocketInfo  soi;
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate     if ( ldapssl_clientauth_init( certdbpath, NULL, 1, keydbpath, NULL ) < 0 ) {
8200Sstevel@tonic-gate 	goto ssl_setup_failure;
8210Sstevel@tonic-gate     }
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate     /*
8240Sstevel@tonic-gate      * Retrieve socket info. so we have the PRFileDesc.
8250Sstevel@tonic-gate      */
8260Sstevel@tonic-gate     memset( &soi, 0, sizeof(soi));
8270Sstevel@tonic-gate     soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
8280Sstevel@tonic-gate     if ( prldap_get_default_socket_info( ld, &soi ) < 0 ) {
8290Sstevel@tonic-gate         goto ssl_setup_failure;
8300Sstevel@tonic-gate     }
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate     if ( ldapssl_install_routines( ld ) < 0 ) {
8330Sstevel@tonic-gate         goto ssl_setup_failure;
8340Sstevel@tonic-gate     }
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate     if (soi.soinfo_prfd == NULL) {
8380Sstevel@tonic-gate         int sd;
8390Sstevel@tonic-gate         ldap_get_option( ld, LDAP_OPT_DESC, &sd );
8400Sstevel@tonic-gate         soi.soinfo_prfd = (PRFileDesc *) PR_ImportTCPSocket( sd );
8410Sstevel@tonic-gate     }
8420Sstevel@tonic-gate     /* set the socket information back into the connection handle,
8430Sstevel@tonic-gate      * because ldapssl_install_routines() resets the socket_arg info in the
8440Sstevel@tonic-gate      * socket buffer. */
8450Sstevel@tonic-gate     if ( prldap_set_default_socket_info( ld, &soi ) != LDAP_SUCCESS ) {
8460Sstevel@tonic-gate       goto ssl_setup_failure;
8470Sstevel@tonic-gate     }
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate     if ( ldap_set_option( ld, LDAP_OPT_SSL,
8500Sstevel@tonic-gate 	defsecure ? LDAP_OPT_ON : LDAP_OPT_OFF ) < 0 ) {
8510Sstevel@tonic-gate         goto ssl_setup_failure;
8520Sstevel@tonic-gate     }
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate     if ( ldapssl_import_fd( ld, defsecure ) < 0 ) {
8550Sstevel@tonic-gate         goto ssl_setup_failure;
8560Sstevel@tonic-gate     }
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate     return 0;
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate ssl_setup_failure:
8610Sstevel@tonic-gate     ldapssl_reset_to_nonsecure( ld );
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate     /* we should here warn the server that we switch back to a non-secure
8640Sstevel@tonic-gate        connection */
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate     return( -1 );
8670Sstevel@tonic-gate }
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate /*
8710Sstevel@tonic-gate  * ldapssl_tls_start_s() performs a synchronous Start TLS extended operation
8720Sstevel@tonic-gate  * request.
8730Sstevel@tonic-gate  *
8740Sstevel@tonic-gate  * The function returns the result code of the extended operation response
8750Sstevel@tonic-gate  * sent by the server.
8760Sstevel@tonic-gate  *
8770Sstevel@tonic-gate  * In case of a successfull response (LDAP_SUCCESS returned), by the time
8780Sstevel@tonic-gate  * this function returns the LDAP session designed by ld will have been
8790Sstevel@tonic-gate  * secured, i.e. the connection will have been imported into SSL.
8800Sstevel@tonic-gate  *
8810Sstevel@tonic-gate  * Should the Start TLS request be rejected by the server, the result code
8820Sstevel@tonic-gate  * returned will be one of the following:
8830Sstevel@tonic-gate  *    LDAP_OPERATIONS_ERROR,
8840Sstevel@tonic-gate  *    LDAP_PROTOCOL_ERROR,
8850Sstevel@tonic-gate  *    LDAP_REFERRAL,
8860Sstevel@tonic-gate  *    LDAP_UNAVAILABLE.
8870Sstevel@tonic-gate  *
8880Sstevel@tonic-gate  * Any other error code returned will be due to a failure in the course
8890Sstevel@tonic-gate  * of operations done on the client side.
8900Sstevel@tonic-gate  *
8910Sstevel@tonic-gate  * "certdbpath" and "keydbpath" should contain the path to the client's
8920Sstevel@tonic-gate  * certificate and key databases respectively. Either the path to the
8930Sstevel@tonic-gate  * directory containing "default name" databases (i.e. cert7.db and key3.db)
8940Sstevel@tonic-gate  * can be specified or the actual filenames can be included.
8950Sstevel@tonic-gate  * If any of these parameters is NULL, the function will assume the database
8960Sstevel@tonic-gate  * is the same used by Netscape Communicator, which is usually under
8970Sstevel@tonic-gate  * ~/.netsca /)
8980Sstevel@tonic-gate  *
8990Sstevel@tonic-gate  * "referralsp" is a pointer to a list of referrals the server might
9000Sstevel@tonic-gate  * eventually send back with an LDAP_REFERRAL result code.
9010Sstevel@tonic-gate  *
9020Sstevel@tonic-gate  */
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate int
9050Sstevel@tonic-gate LDAP_CALL
ldapssl_tls_start_s(LDAP * ld,int defsecure,char * certdbpath,char * keydbpath,char *** referralsp)9060Sstevel@tonic-gate ldapssl_tls_start_s(LDAP *ld,int defsecure, char *certdbpath, char *keydbpath,
9070Sstevel@tonic-gate 	char ***referralsp)
9080Sstevel@tonic-gate {
9090Sstevel@tonic-gate     int             rc, resultCode, msgid;
9100Sstevel@tonic-gate     char            *extresp_oid;
9110Sstevel@tonic-gate     BerValue        *extresp_data;
9120Sstevel@tonic-gate     LDAPMessage     *res;
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate     rc = ldapssl_tls_start( ld, &msgid );
9150Sstevel@tonic-gate     if ( rc != LDAP_SUCCESS ) {
9160Sstevel@tonic-gate          return rc;
9170Sstevel@tonic-gate     }
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate     rc = ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res );
9200Sstevel@tonic-gate     if ( rc != LDAP_RES_EXTENDED ) {
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate       /* the first response received must be an extended response to an
9230Sstevel@tonic-gate        Start TLS request */
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate          ldap_msgfree( res );
9260Sstevel@tonic-gate          return( -1 );
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate     }
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate     rc = ldap_parse_extended_result( ld, res, &extresp_oid, &extresp_data, 0 );
9310Sstevel@tonic-gate 
9320Sstevel@tonic-gate     if ( rc != LDAP_SUCCESS ) {
9330Sstevel@tonic-gate          ldap_msgfree( res );
9340Sstevel@tonic-gate          return rc;
9350Sstevel@tonic-gate     }
9360Sstevel@tonic-gate 
9370Sstevel@tonic-gate     if ( strcasecmp( extresp_oid, START_TLS_OID ) != 0 ) {
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate          /* the extended response received doesn't correspond to the
9400Sstevel@tonic-gate           Start TLS request */
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate          ldap_msgfree( res );
9430Sstevel@tonic-gate          return -1;
9440Sstevel@tonic-gate     }
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate     resultCode = ldap_get_lderrno( ld, NULL, NULL );
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate     /* Analyze the server's response */
9490Sstevel@tonic-gate     switch (resultCode) {
9500Sstevel@tonic-gate     case LDAP_REFERRAL:
9510Sstevel@tonic-gate       {
9520Sstevel@tonic-gate       rc = ldap_parse_result( ld, res, NULL, NULL, NULL, referralsp, NULL, 0 );
9530Sstevel@tonic-gate       if ( rc != LDAP_SUCCESS ) {
9540Sstevel@tonic-gate           ldap_msgfree( res );
9550Sstevel@tonic-gate           return rc;
9560Sstevel@tonic-gate       }
9570Sstevel@tonic-gate     }
9580Sstevel@tonic-gate     case LDAP_OPERATIONS_ERROR:
9590Sstevel@tonic-gate 
9600Sstevel@tonic-gate     case LDAP_PROTOCOL_ERROR:
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate     case LDAP_UNAVAILABLE:
9630Sstevel@tonic-gate         goto free_msg_and_return;
9640Sstevel@tonic-gate     case LDAP_SUCCESS:
9650Sstevel@tonic-gate       {
9660Sstevel@tonic-gate       /*
9670Sstevel@tonic-gate        * If extended response successfull, get connection ready for
9680Sstevel@tonic-gate        * communicating with the server over SSL/TLS.
9690Sstevel@tonic-gate        */
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate       if ( ldapssl_enableSSL_on_open_connection( ld, defsecure,
9720Sstevel@tonic-gate                                          certdbpath, keydbpath ) < 0 ) {
9730Sstevel@tonic-gate           resultCode = -1;
9740Sstevel@tonic-gate       }
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate     } /* case LDAP_SUCCESS */
9770Sstevel@tonic-gate     default:
9780Sstevel@tonic-gate         goto free_msg_and_return;
9790Sstevel@tonic-gate     } /* switch */
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate free_msg_and_return:
9820Sstevel@tonic-gate     ldap_msgfree( res );
9830Sstevel@tonic-gate     return resultCode;
9840Sstevel@tonic-gate }
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate #endif /* NET_SSL */
987