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