1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate /*
7*0Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
8*0Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
9*0Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
10*0Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
11*0Sstevel@tonic-gate  *
12*0Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
13*0Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14*0Sstevel@tonic-gate  * implied. See the License for the specific language governing
15*0Sstevel@tonic-gate  * rights and limitations under the License.
16*0Sstevel@tonic-gate  *
17*0Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
18*0Sstevel@tonic-gate  * March 31, 1998.
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
21*0Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
22*0Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
23*0Sstevel@tonic-gate  * Rights Reserved.
24*0Sstevel@tonic-gate  *
25*0Sstevel@tonic-gate  * Contributor(s):
26*0Sstevel@tonic-gate  */
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate /*
31*0Sstevel@tonic-gate  * clientinit.c
32*0Sstevel@tonic-gate  */
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #if defined(NET_SSL)
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #if defined( _WINDOWS )
38*0Sstevel@tonic-gate #include <windows.h>
39*0Sstevel@tonic-gate #include "proto-ntutil.h"
40*0Sstevel@tonic-gate #endif
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate #include <nspr.h>
43*0Sstevel@tonic-gate #include <plstr.h>
44*0Sstevel@tonic-gate #include <synch.h>
45*0Sstevel@tonic-gate #include <cert.h>
46*0Sstevel@tonic-gate #include <key.h>
47*0Sstevel@tonic-gate #include <ssl.h>
48*0Sstevel@tonic-gate #include <sslproto.h>
49*0Sstevel@tonic-gate #include <ldap.h>
50*0Sstevel@tonic-gate #include <ldappr.h>
51*0Sstevel@tonic-gate #include <solaris-int.h>
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate #include <nss.h>
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate /* XXX:mhein The following is a workaround for the redefinition of */
57*0Sstevel@tonic-gate /*	     const problem on OSF.  Fix to be provided by NSS */
58*0Sstevel@tonic-gate /*	     This is a pretty benign workaround for us which */
59*0Sstevel@tonic-gate /*	     should not cause problems in the future even if */
60*0Sstevel@tonic-gate /*	     we forget to take it out :-) */
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate #ifdef OSF1V4D
63*0Sstevel@tonic-gate #ifndef __STDC__
64*0Sstevel@tonic-gate #  define __STDC__
65*0Sstevel@tonic-gate #endif /* __STDC__ */
66*0Sstevel@tonic-gate #endif /* OSF1V4D */
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate #ifndef FILE_PATHSEP
69*0Sstevel@tonic-gate #define FILE_PATHSEP '/'
70*0Sstevel@tonic-gate #endif
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate /*
73*0Sstevel@tonic-gate  * StartTls()
74*0Sstevel@tonic-gate  */
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate #define START_TLS_OID "1.3.6.1.4.1.1466.20037"
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate static PRStatus local_SSLPLCY_Install(void);
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate /*
81*0Sstevel@tonic-gate  * This little tricky guy keeps us from initializing twice
82*0Sstevel@tonic-gate  */
83*0Sstevel@tonic-gate static int		inited = 0;
84*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK
85*0Sstevel@tonic-gate mutex_t			inited_mutex = DEFAULTMUTEX;
86*0Sstevel@tonic-gate #else
87*0Sstevel@tonic-gate static mutex_t		inited_mutex = DEFAULTMUTEX;
88*0Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
89*0Sstevel@tonic-gate #if 0	/* UNNEEDED BY LIBLDAP */
90*0Sstevel@tonic-gate static char  tokDes[34] = "Internal (Software) Database     ";
91*0Sstevel@tonic-gate static char ptokDes[34] = "Internal (Software) Token        ";
92*0Sstevel@tonic-gate #endif	/* UNNEEDED BY LIBLDAP */
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate /* IN:					     */
96*0Sstevel@tonic-gate /* string:	/u/mhein/.netscape/mykey3.db */
97*0Sstevel@tonic-gate /* OUT:					     */
98*0Sstevel@tonic-gate /* dir: 	/u/mhein/.netscape/	     */
99*0Sstevel@tonic-gate /* prefix:	my			     */
100*0Sstevel@tonic-gate /* key:		key3.db			     */
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate static int
103*0Sstevel@tonic-gate splitpath(char *string, char *dir, char *prefix, char *key) {
104*0Sstevel@tonic-gate         char *k;
105*0Sstevel@tonic-gate         char *s;
106*0Sstevel@tonic-gate         char *d = string;
107*0Sstevel@tonic-gate         char *l;
108*0Sstevel@tonic-gate         int  len = 0;
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate         if (string == NULL)
112*0Sstevel@tonic-gate                 return (-1);
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate         /* goto the end of the string, and walk backwards until */
115*0Sstevel@tonic-gate         /* you get to the first pathseparator */
116*0Sstevel@tonic-gate         len = PL_strlen(string);
117*0Sstevel@tonic-gate         l = string + len - 1;
118*0Sstevel@tonic-gate         while (l != string && *l != '/' && *l != '\\')
119*0Sstevel@tonic-gate                         l--;
120*0Sstevel@tonic-gate         /* search for the .db */
121*0Sstevel@tonic-gate         if ((k = PL_strstr(l, ".db")) != NULL) {
122*0Sstevel@tonic-gate                 /* now we are sitting on . of .db */
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate                 /* move backward to the first 'c' or 'k' */
125*0Sstevel@tonic-gate                 /* indicating cert or key */
126*0Sstevel@tonic-gate                 while (k != l && *k != 'c' && *k != 'k')
127*0Sstevel@tonic-gate                         k--;
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate                 /* move backwards to the first path separator */
130*0Sstevel@tonic-gate                 if (k != d && k > d)
131*0Sstevel@tonic-gate                         s = k - 1;
132*0Sstevel@tonic-gate                 while (s != d && *s != '/' && *s != '\\')
133*0Sstevel@tonic-gate                         s--;
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate                 /* if we are sitting on top of a path */
136*0Sstevel@tonic-gate                 /* separator there is no prefix */
137*0Sstevel@tonic-gate                 if (s + 1 == k) {
138*0Sstevel@tonic-gate                         /* we know there is no prefix */
139*0Sstevel@tonic-gate                         prefix = '\0';
140*0Sstevel@tonic-gate                         PL_strcpy(key, k);
141*0Sstevel@tonic-gate                         *k = '\0';
142*0Sstevel@tonic-gate                         PL_strcpy(dir, d);
143*0Sstevel@tonic-gate                 } else {
144*0Sstevel@tonic-gate                         /* grab the prefix */
145*0Sstevel@tonic-gate                         PL_strcpy(key, k);
146*0Sstevel@tonic-gate                         *k = '\0';
147*0Sstevel@tonic-gate                         PL_strcpy(prefix, ++s);
148*0Sstevel@tonic-gate                         *s = '\0';
149*0Sstevel@tonic-gate                         PL_strcpy(dir, d);
150*0Sstevel@tonic-gate                 }
151*0Sstevel@tonic-gate         } else {
152*0Sstevel@tonic-gate                 /* neither *key[0-9].db nor *cert[0=9].db found */
153*0Sstevel@tonic-gate                 return (-1);
154*0Sstevel@tonic-gate         }
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 	return (0);
157*0Sstevel@tonic-gate }
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate static PRStatus local_SSLPLCY_Install(void)
161*0Sstevel@tonic-gate {
162*0Sstevel@tonic-gate 	SECStatus s;
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate #ifdef NS_DOMESTIC
165*0Sstevel@tonic-gate 	s = NSS_SetDomesticPolicy();
166*0Sstevel@tonic-gate #elif NS_EXPORT
167*0Sstevel@tonic-gate 	s = NSS_SetExportPolicy();
168*0Sstevel@tonic-gate #else
169*0Sstevel@tonic-gate 	s = PR_FAILURE;
170*0Sstevel@tonic-gate #endif
171*0Sstevel@tonic-gate 	return s?PR_FAILURE:PR_SUCCESS;
172*0Sstevel@tonic-gate }
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate static void
177*0Sstevel@tonic-gate ldapssl_basic_init( void )
178*0Sstevel@tonic-gate {
179*0Sstevel@tonic-gate #ifndef _SOLARIS_SDK
180*0Sstevel@tonic-gate 	/*
181*0Sstevel@tonic-gate 	 * NSPR is initialized in .init on SOLARIS
182*0Sstevel@tonic-gate 	 */
183*0Sstevel@tonic-gate     /* PR_Init() must to be called before everything else... */
184*0Sstevel@tonic-gate     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
185*0Sstevel@tonic-gate #endif
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate     PR_SetConcurrency( 4 );	/* work around for NSPR 3.x I/O hangs */
188*0Sstevel@tonic-gate }
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate /*
193*0Sstevel@tonic-gate  * Cover  functions for malloc(), calloc(), strdup() and free() that are
194*0Sstevel@tonic-gate  * compatible with the NSS libraries (they seem to use the C runtime
195*0Sstevel@tonic-gate  * library malloc/free so these functions are quite simple right now).
196*0Sstevel@tonic-gate  */
197*0Sstevel@tonic-gate static void *
198*0Sstevel@tonic-gate ldapssl_malloc( size_t size )
199*0Sstevel@tonic-gate {
200*0Sstevel@tonic-gate     void	*p;
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate     p = malloc( size );
203*0Sstevel@tonic-gate     return p;
204*0Sstevel@tonic-gate }
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate static void *
208*0Sstevel@tonic-gate ldapssl_calloc( int nelem, size_t elsize )
209*0Sstevel@tonic-gate {
210*0Sstevel@tonic-gate     void	*p;
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate     p = calloc( nelem, elsize );
213*0Sstevel@tonic-gate     return p;
214*0Sstevel@tonic-gate }
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate static char *
218*0Sstevel@tonic-gate ldapssl_strdup( const char *s )
219*0Sstevel@tonic-gate {
220*0Sstevel@tonic-gate     char	*scopy;
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate     if ( NULL == s ) {
223*0Sstevel@tonic-gate 	scopy = NULL;
224*0Sstevel@tonic-gate     } else {
225*0Sstevel@tonic-gate 	scopy = strdup( s );
226*0Sstevel@tonic-gate     }
227*0Sstevel@tonic-gate     return scopy;
228*0Sstevel@tonic-gate }
229*0Sstevel@tonic-gate 
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate static void
232*0Sstevel@tonic-gate ldapssl_free( void **pp )
233*0Sstevel@tonic-gate {
234*0Sstevel@tonic-gate     if ( NULL != pp && NULL != *pp ) {
235*0Sstevel@tonic-gate 	free( (void *)*pp );
236*0Sstevel@tonic-gate 	*pp = NULL;
237*0Sstevel@tonic-gate     }
238*0Sstevel@tonic-gate }
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate static char *
242*0Sstevel@tonic-gate buildDBName(const char *basename, const char *dbname)
243*0Sstevel@tonic-gate {
244*0Sstevel@tonic-gate 	char		*result;
245*0Sstevel@tonic-gate 	PRUint32	len, pathlen, addslash;
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 	if (basename)
248*0Sstevel@tonic-gate 	{
249*0Sstevel@tonic-gate 	    if (( len = PL_strlen( basename )) > 3
250*0Sstevel@tonic-gate 		&& PL_strcasecmp( ".db", basename + len - 3 ) == 0 ) {
251*0Sstevel@tonic-gate 		return (ldapssl_strdup(basename));
252*0Sstevel@tonic-gate 	    }
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	    pathlen = len;
255*0Sstevel@tonic-gate 	    len = pathlen + PL_strlen(dbname) + 1;
256*0Sstevel@tonic-gate 	    addslash = ( pathlen > 0 &&
257*0Sstevel@tonic-gate 		(( *(basename + pathlen - 1) != FILE_PATHSEP ) ||
258*0Sstevel@tonic-gate 		( *(basename + pathlen - 1) != '\\'  )));
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	    if ( addslash ) {
261*0Sstevel@tonic-gate 		++len;
262*0Sstevel@tonic-gate 	    }
263*0Sstevel@tonic-gate 	    if (( result = ldapssl_malloc( len )) != NULL ) {
264*0Sstevel@tonic-gate 		PL_strcpy( result, basename );
265*0Sstevel@tonic-gate 		if ( addslash ) {
266*0Sstevel@tonic-gate 		    *(result+pathlen) = FILE_PATHSEP;  /* replaces '\0' */
267*0Sstevel@tonic-gate 		    ++pathlen;
268*0Sstevel@tonic-gate 		}
269*0Sstevel@tonic-gate 		PL_strcpy(result+pathlen, dbname);
270*0Sstevel@tonic-gate 	    }
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	}
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	return result;
276*0Sstevel@tonic-gate }
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate char *
279*0Sstevel@tonic-gate GetCertDBName(void *alias, int dbVersion)
280*0Sstevel@tonic-gate {
281*0Sstevel@tonic-gate     char		*source;
282*0Sstevel@tonic-gate     char dbname[128];
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate     source = (char *)alias;
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate     if (!source)
287*0Sstevel@tonic-gate     {
288*0Sstevel@tonic-gate 	source = "";
289*0Sstevel@tonic-gate     }
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate     sprintf(dbname, "cert%d.db",dbVersion);
292*0Sstevel@tonic-gate     return(buildDBName(source, dbname));
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate }
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate /*
298*0Sstevel@tonic-gate  * return database name by appending "dbname" to "path".
299*0Sstevel@tonic-gate  * this code doesn't need to be terribly efficient (not called often).
300*0Sstevel@tonic-gate  */
301*0Sstevel@tonic-gate /* XXXceb this is the old function.  To be removed eventually */
302*0Sstevel@tonic-gate static char *
303*0Sstevel@tonic-gate GetDBName(const char *dbname, const char *path)
304*0Sstevel@tonic-gate {
305*0Sstevel@tonic-gate     char		*result;
306*0Sstevel@tonic-gate     PRUint32	len, pathlen;
307*0Sstevel@tonic-gate     int		addslash;
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate     if ( dbname == NULL ) {
310*0Sstevel@tonic-gate 	dbname = "";
311*0Sstevel@tonic-gate     }
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate     if ((path == NULL) || (*path == 0)) {
314*0Sstevel@tonic-gate 	result = ldapssl_strdup(dbname);
315*0Sstevel@tonic-gate     } else {
316*0Sstevel@tonic-gate 	pathlen = PL_strlen(path);
317*0Sstevel@tonic-gate 	len = pathlen + PL_strlen(dbname) + 1;
318*0Sstevel@tonic-gate 	addslash = ( path[pathlen - 1] != '/' );
319*0Sstevel@tonic-gate 	if ( addslash ) {
320*0Sstevel@tonic-gate 	    ++len;
321*0Sstevel@tonic-gate 	}
322*0Sstevel@tonic-gate 	if (( result = ldapssl_malloc( len )) != NULL ) {
323*0Sstevel@tonic-gate 	    PL_strcpy( result, path );
324*0Sstevel@tonic-gate 	    if ( addslash ) {
325*0Sstevel@tonic-gate 		*(result+pathlen) = '/';  /* replaces '\0' */
326*0Sstevel@tonic-gate 		++pathlen;
327*0Sstevel@tonic-gate 	    }
328*0Sstevel@tonic-gate 	    PL_strcpy(result+pathlen, dbname);
329*0Sstevel@tonic-gate 	}
330*0Sstevel@tonic-gate     }
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate     return result;
333*0Sstevel@tonic-gate }
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate /*
336*0Sstevel@tonic-gate  * Initialize ns/security so it can be used for SSL client authentication.
337*0Sstevel@tonic-gate  * It is safe to call this more than once.
338*0Sstevel@tonic-gate  *
339*0Sstevel@tonic-gate  * If needkeydb == 0, no key database is opened and SSL server authentication
340*0Sstevel@tonic-gate  * is supported but not client authentication.
341*0Sstevel@tonic-gate  *
342*0Sstevel@tonic-gate  * If "certdbpath" is NULL or "", the default cert. db is used (typically
343*0Sstevel@tonic-gate  * ~/.netscape/cert7.db).
344*0Sstevel@tonic-gate  *
345*0Sstevel@tonic-gate  * If "certdbpath" ends with ".db" (case-insensitive compare), then
346*0Sstevel@tonic-gate  * it is assumed to be a full path to the cert. db file; otherwise,
347*0Sstevel@tonic-gate  * it is assumed to be a directory that contains a file called
348*0Sstevel@tonic-gate  * "cert7.db" or "cert.db".
349*0Sstevel@tonic-gate  *
350*0Sstevel@tonic-gate  * If certdbhandle is non-NULL, it is assumed to be a pointer to a
351*0Sstevel@tonic-gate  * SECCertDBHandle structure.  It is fine to pass NULL since this
352*0Sstevel@tonic-gate  * routine will allocate one for you (CERT_GetDefaultDB() can be
353*0Sstevel@tonic-gate  * used to retrieve the cert db handle).
354*0Sstevel@tonic-gate  *
355*0Sstevel@tonic-gate  * If "keydbpath" is NULL or "", the default key db is used (typically
356*0Sstevel@tonic-gate  * ~/.netscape/key3.db).
357*0Sstevel@tonic-gate  *
358*0Sstevel@tonic-gate  * If "keydbpath" ends with ".db" (case-insensitive compare), then
359*0Sstevel@tonic-gate  * it is assumed to be a full path to the key db file; otherwise,
360*0Sstevel@tonic-gate  * it is assumed to be a directory that contains a file called
361*0Sstevel@tonic-gate  * "key3.db"
362*0Sstevel@tonic-gate  *
363*0Sstevel@tonic-gate  * If certdbhandle is non-NULL< it is assumed to be a pointed to a
364*0Sstevel@tonic-gate  * SECKEYKeyDBHandle structure.  It is fine to pass NULL since this
365*0Sstevel@tonic-gate  * routine will allocate one for you (SECKEY_GetDefaultDB() can be
366*0Sstevel@tonic-gate  * used to retrieve the cert db handle).
367*0Sstevel@tonic-gate  */
368*0Sstevel@tonic-gate int
369*0Sstevel@tonic-gate LDAP_CALL
370*0Sstevel@tonic-gate ldapssl_clientauth_init( const char *certdbpath, void *certdbhandle,
371*0Sstevel@tonic-gate     const int needkeydb, const char *keydbpath, void *keydbhandle )
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate {
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate     int	rc;
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate     /*
378*0Sstevel@tonic-gate      *     LDAPDebug(LDAP_DEBUG_TRACE, "ldapssl_clientauth_init\n",0 ,0 ,0);
379*0Sstevel@tonic-gate      */
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate     mutex_lock(&inited_mutex);
382*0Sstevel@tonic-gate     if ( inited ) {
383*0Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
384*0Sstevel@tonic-gate 	return( 0 );
385*0Sstevel@tonic-gate     }
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate     ldapssl_basic_init();
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate 
390*0Sstevel@tonic-gate     /* Open the certificate database */
391*0Sstevel@tonic-gate     rc = NSS_Init(certdbpath);
392*0Sstevel@tonic-gate     if (rc != 0) {
393*0Sstevel@tonic-gate 	if ((rc = PR_GetError()) >= 0)
394*0Sstevel@tonic-gate 	    rc = -1;
395*0Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
396*0Sstevel@tonic-gate 	return (rc);
397*0Sstevel@tonic-gate     }
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate     if (SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE)
400*0Sstevel@tonic-gate 	    || SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE)) {
401*0Sstevel@tonic-gate 	if (( rc = PR_GetError()) >= 0 ) {
402*0Sstevel@tonic-gate 	    rc = -1;
403*0Sstevel@tonic-gate 	}
404*0Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
405*0Sstevel@tonic-gate 	return( rc );
406*0Sstevel@tonic-gate     }
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate #if defined(NS_DOMESTIC)
411*0Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
412*0Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
413*0Sstevel@tonic-gate       return( -1 );
414*0Sstevel@tonic-gate     }
415*0Sstevel@tonic-gate #elif(NS_EXPORT)
416*0Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
417*0Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
418*0Sstevel@tonic-gate       return( -1 );
419*0Sstevel@tonic-gate     }
420*0Sstevel@tonic-gate #else
421*0Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
422*0Sstevel@tonic-gate     return( -1 );
423*0Sstevel@tonic-gate #endif
424*0Sstevel@tonic-gate 
425*0Sstevel@tonic-gate     inited = 1;
426*0Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
427*0Sstevel@tonic-gate 
428*0Sstevel@tonic-gate     return( 0 );
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate }
431*0Sstevel@tonic-gate 
432*0Sstevel@tonic-gate /*
433*0Sstevel@tonic-gate  * Initialize ns/security so it can be used for SSL client authentication.
434*0Sstevel@tonic-gate  * It is safe to call this more than once.
435*0Sstevel@tonic-gate  *
436*0Sstevel@tonic-gate  * If needkeydb == 0, no key database is opened and SSL server authentication
437*0Sstevel@tonic-gate  * is supported but not client authentication.
438*0Sstevel@tonic-gate  *
439*0Sstevel@tonic-gate  * If "certdbpath" is NULL or "", the default cert. db is used (typically
440*0Sstevel@tonic-gate  * ~/.netscape/cert7.db).
441*0Sstevel@tonic-gate  *
442*0Sstevel@tonic-gate  * If "certdbpath" ends with ".db" (case-insensitive compare), then
443*0Sstevel@tonic-gate  * it is assumed to be a full path to the cert. db file; otherwise,
444*0Sstevel@tonic-gate  * it is assumed to be a directory that contains a file called
445*0Sstevel@tonic-gate  * "cert7.db" or "cert.db".
446*0Sstevel@tonic-gate  *
447*0Sstevel@tonic-gate  * If certdbhandle is non-NULL, it is assumed to be a pointer to a
448*0Sstevel@tonic-gate  * SECCertDBHandle structure.  It is fine to pass NULL since this
449*0Sstevel@tonic-gate  * routine will allocate one for you (CERT_GetDefaultDB() can be
450*0Sstevel@tonic-gate  * used to retrieve the cert db handle).
451*0Sstevel@tonic-gate  *
452*0Sstevel@tonic-gate  * If "keydbpath" is NULL or "", the default key db is used (typically
453*0Sstevel@tonic-gate  * ~/.netscape/key3.db).
454*0Sstevel@tonic-gate  *
455*0Sstevel@tonic-gate  * If "keydbpath" ends with ".db" (case-insensitive compare), then
456*0Sstevel@tonic-gate  * it is assumed to be a full path to the key db file; otherwise,
457*0Sstevel@tonic-gate  * it is assumed to be a directory that contains a file called
458*0Sstevel@tonic-gate  * "key3.db"
459*0Sstevel@tonic-gate  *
460*0Sstevel@tonic-gate  * If certdbhandle is non-NULL< it is assumed to be a pointed to a
461*0Sstevel@tonic-gate  * SECKEYKeyDBHandle structure.  It is fine to pass NULL since this
462*0Sstevel@tonic-gate  * routine will allocate one for you (SECKEY_GetDefaultDB() can be
463*0Sstevel@tonic-gate  * used to retrieve the cert db handle).  */
464*0Sstevel@tonic-gate int
465*0Sstevel@tonic-gate LDAP_CALL
466*0Sstevel@tonic-gate ldapssl_advclientauth_init(
467*0Sstevel@tonic-gate     const char *certdbpath, void *certdbhandle,
468*0Sstevel@tonic-gate     const int needkeydb, const char *keydbpath, void *keydbhandle,
469*0Sstevel@tonic-gate     const int needsecmoddb, const char *secmoddbpath,
470*0Sstevel@tonic-gate     const int sslstrength )
471*0Sstevel@tonic-gate {
472*0Sstevel@tonic-gate     int	rc;
473*0Sstevel@tonic-gate 
474*0Sstevel@tonic-gate     mutex_lock(&inited_mutex);
475*0Sstevel@tonic-gate     if ( inited ) {
476*0Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
477*0Sstevel@tonic-gate 	return( 0 );
478*0Sstevel@tonic-gate     }
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate     /*
481*0Sstevel@tonic-gate      *    LDAPDebug(LDAP_DEBUG_TRACE, "ldapssl_advclientauth_init\n",0 ,0 ,0);
482*0Sstevel@tonic-gate      */
483*0Sstevel@tonic-gate 
484*0Sstevel@tonic-gate     ldapssl_basic_init();
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate     rc = NSS_Init(certdbpath);
487*0Sstevel@tonic-gate     if (rc != 0) {
488*0Sstevel@tonic-gate 	if ((rc = PR_GetError()) >= 0)
489*0Sstevel@tonic-gate 	    rc = -1;
490*0Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
491*0Sstevel@tonic-gate 	return (rc);
492*0Sstevel@tonic-gate     }
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate #if defined(NS_DOMESTIC)
495*0Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
496*0Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
497*0Sstevel@tonic-gate       return( -1 );
498*0Sstevel@tonic-gate     }
499*0Sstevel@tonic-gate #elif(NS_EXPORT)
500*0Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
501*0Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
502*0Sstevel@tonic-gate       return( -1 );
503*0Sstevel@tonic-gate     }
504*0Sstevel@tonic-gate #else
505*0Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
506*0Sstevel@tonic-gate     return( -1 );
507*0Sstevel@tonic-gate #endif
508*0Sstevel@tonic-gate 
509*0Sstevel@tonic-gate     inited = 1;
510*0Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
511*0Sstevel@tonic-gate 
512*0Sstevel@tonic-gate     return( ldapssl_set_strength( NULL, sslstrength));
513*0Sstevel@tonic-gate 
514*0Sstevel@tonic-gate }
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate /*
518*0Sstevel@tonic-gate  * Initialize ns/security so it can be used for SSL client authentication.
519*0Sstevel@tonic-gate  * It is safe to call this more than once.
520*0Sstevel@tonic-gate   */
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate /*
523*0Sstevel@tonic-gate  * XXXceb  This is a hack until the new IO functions are done.
524*0Sstevel@tonic-gate  * this function lives in ldapsinit.c
525*0Sstevel@tonic-gate  */
526*0Sstevel@tonic-gate void set_using_pkcs_functions( int val );
527*0Sstevel@tonic-gate 
528*0Sstevel@tonic-gate int
529*0Sstevel@tonic-gate LDAP_CALL
530*0Sstevel@tonic-gate ldapssl_pkcs_init( const struct ldapssl_pkcs_fns *pfns )
531*0Sstevel@tonic-gate {
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate     char		*certdbName, *s, *keydbpath;
534*0Sstevel@tonic-gate     char		*certdbPrefix, *keydbPrefix;
535*0Sstevel@tonic-gate     char		*confDir, *keydbName;
536*0Sstevel@tonic-gate     static char         *secmodname =  "secmod.db";
537*0Sstevel@tonic-gate     int			rc;
538*0Sstevel@tonic-gate 
539*0Sstevel@tonic-gate     mutex_lock(&inited_mutex);
540*0Sstevel@tonic-gate     if ( inited ) {
541*0Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
542*0Sstevel@tonic-gate 	return( 0 );
543*0Sstevel@tonic-gate     }
544*0Sstevel@tonic-gate /*
545*0Sstevel@tonic-gate  * XXXceb  This is a hack until the new IO functions are done.
546*0Sstevel@tonic-gate  * this function MUST be called before ldap_enable_clienauth.
547*0Sstevel@tonic-gate  *
548*0Sstevel@tonic-gate  */
549*0Sstevel@tonic-gate     set_using_pkcs_functions( 1 );
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate     /*
552*0Sstevel@tonic-gate      *    LDAPDebug(LDAP_DEBUG_TRACE, "ldapssl_pkcs_init\n",0 ,0 ,0);
553*0Sstevel@tonic-gate      */
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 
556*0Sstevel@tonic-gate     ldapssl_basic_init();
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate     pfns->pkcs_getcertpath( NULL, &s);
559*0Sstevel@tonic-gate     confDir = ldapssl_strdup( s );
560*0Sstevel@tonic-gate     certdbPrefix = ldapssl_strdup( s );
561*0Sstevel@tonic-gate     certdbName = ldapssl_strdup( s );
562*0Sstevel@tonic-gate     *certdbPrefix = 0;
563*0Sstevel@tonic-gate     splitpath(s, confDir, certdbPrefix, certdbName);
564*0Sstevel@tonic-gate 
565*0Sstevel@tonic-gate     pfns->pkcs_getkeypath( NULL, &s);
566*0Sstevel@tonic-gate     keydbpath = ldapssl_strdup( s );
567*0Sstevel@tonic-gate     keydbPrefix = ldapssl_strdup( s );
568*0Sstevel@tonic-gate     keydbName = ldapssl_strdup( s );
569*0Sstevel@tonic-gate     *keydbPrefix = 0;
570*0Sstevel@tonic-gate     splitpath(s, keydbpath, keydbPrefix, keydbName);
571*0Sstevel@tonic-gate 
572*0Sstevel@tonic-gate 
573*0Sstevel@tonic-gate     /* verify confDir == keydbpath and adjust as necessary */
574*0Sstevel@tonic-gate     ldapssl_free((void **)&certdbName);
575*0Sstevel@tonic-gate     ldapssl_free((void **)&keydbName);
576*0Sstevel@tonic-gate     ldapssl_free((void **)&keydbpath);
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate     rc = NSS_Initialize(confDir,certdbPrefix,keydbPrefix,secmodname,
579*0Sstevel@tonic-gate 		NSS_INIT_READONLY);
580*0Sstevel@tonic-gate 
581*0Sstevel@tonic-gate     ldapssl_free((void **)&certdbPrefix);
582*0Sstevel@tonic-gate     ldapssl_free((void **)&keydbPrefix);
583*0Sstevel@tonic-gate     ldapssl_free((void **)&confDir);
584*0Sstevel@tonic-gate 
585*0Sstevel@tonic-gate     if (rc != 0) {
586*0Sstevel@tonic-gate 	if ((rc = PR_GetError()) >= 0)
587*0Sstevel@tonic-gate 	    rc = -1;
588*0Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
589*0Sstevel@tonic-gate 	return (rc);
590*0Sstevel@tonic-gate     }
591*0Sstevel@tonic-gate 
592*0Sstevel@tonic-gate 
593*0Sstevel@tonic-gate #if 0	/* UNNEEDED BY LIBLDAP */
594*0Sstevel@tonic-gate     /* this is odd */
595*0Sstevel@tonic-gate     PK11_ConfigurePKCS11(NULL, NULL, tokDes, ptokDes, NULL, NULL, NULL, NULL, 0, 0 );
596*0Sstevel@tonic-gate #endif	/* UNNEEDED BY LIBLDAP */
597*0Sstevel@tonic-gate 
598*0Sstevel@tonic-gate     if (SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE)
599*0Sstevel@tonic-gate 	|| SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE)) {
600*0Sstevel@tonic-gate 	if (( rc = PR_GetError()) >= 0 ) {
601*0Sstevel@tonic-gate 	    rc = -1;
602*0Sstevel@tonic-gate 	}
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate 	mutex_unlock(&inited_mutex);
605*0Sstevel@tonic-gate 	return( rc );
606*0Sstevel@tonic-gate     }
607*0Sstevel@tonic-gate 
608*0Sstevel@tonic-gate #if defined(NS_DOMESTIC)
609*0Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
610*0Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
611*0Sstevel@tonic-gate       return( -1 );
612*0Sstevel@tonic-gate     }
613*0Sstevel@tonic-gate #elif(NS_EXPORT)
614*0Sstevel@tonic-gate     if (local_SSLPLCY_Install() == PR_FAILURE) {
615*0Sstevel@tonic-gate       mutex_unlock(&inited_mutex);
616*0Sstevel@tonic-gate       return( -1 );
617*0Sstevel@tonic-gate     }
618*0Sstevel@tonic-gate #else
619*0Sstevel@tonic-gate     mutex_unlock(&inited_mutex);
620*0Sstevel@tonic-gate     return( -1 );
621*0Sstevel@tonic-gate #endif
622*0Sstevel@tonic-gate 
623*0Sstevel@tonic-gate     inited = 1;
624*0Sstevel@tonic-gate 
625*0Sstevel@tonic-gate     if ( certdbName != NULL ) {
626*0Sstevel@tonic-gate 	ldapssl_free((void **) &certdbName );
627*0Sstevel@tonic-gate     }
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate     return( ldapssl_set_strength( NULL, LDAPSSL_AUTH_CNCHECK));
630*0Sstevel@tonic-gate }
631*0Sstevel@tonic-gate 
632*0Sstevel@tonic-gate 
633*0Sstevel@tonic-gate /*
634*0Sstevel@tonic-gate  * ldapssl_client_init() is a server-authentication only version of
635*0Sstevel@tonic-gate  * ldapssl_clientauth_init().
636*0Sstevel@tonic-gate  */
637*0Sstevel@tonic-gate int
638*0Sstevel@tonic-gate LDAP_CALL
639*0Sstevel@tonic-gate ldapssl_client_init(const char* certdbpath, void *certdbhandle )
640*0Sstevel@tonic-gate {
641*0Sstevel@tonic-gate     return( ldapssl_clientauth_init( certdbpath, certdbhandle,
642*0Sstevel@tonic-gate 	    0, NULL, NULL ));
643*0Sstevel@tonic-gate }
644*0Sstevel@tonic-gate /*
645*0Sstevel@tonic-gate  * ldapssl_serverauth_init() is a server-authentication only version of
646*0Sstevel@tonic-gate  * ldapssl_clientauth_init().  This function allows the sslstrength
647*0Sstevel@tonic-gate  * to be passed in.  The sslstrength can take one of the following
648*0Sstevel@tonic-gate  * values:
649*0Sstevel@tonic-gate  *      LDAPSSL_AUTH_WEAK: indicate that you accept the server's
650*0Sstevel@tonic-gate  *                         certificate without checking the CA who
651*0Sstevel@tonic-gate  *                         issued the certificate
652*0Sstevel@tonic-gate  *      LDAPSSL_AUTH_CERT: indicates that you accept the server's
653*0Sstevel@tonic-gate  *                         certificate only if you trust the CA who
654*0Sstevel@tonic-gate  *                         issued the certificate
655*0Sstevel@tonic-gate  *      LDAPSSL_AUTH_CNCHECK:
656*0Sstevel@tonic-gate                            indicates that you accept the server's
657*0Sstevel@tonic-gate  *                         certificate only if you trust the CA who
658*0Sstevel@tonic-gate  *                         issued the certificate and if the value
659*0Sstevel@tonic-gate  *                         of the cn attribute in the DNS hostname
660*0Sstevel@tonic-gate  *                         of the server
661*0Sstevel@tonic-gate  */
662*0Sstevel@tonic-gate int
663*0Sstevel@tonic-gate LDAP_CALL
664*0Sstevel@tonic-gate ldapssl_serverauth_init(const char* certdbpath,
665*0Sstevel@tonic-gate                      void *certdbhandle,
666*0Sstevel@tonic-gate                      const int sslstrength )
667*0Sstevel@tonic-gate {
668*0Sstevel@tonic-gate     if ( ldapssl_set_strength( NULL, sslstrength ) != 0) {
669*0Sstevel@tonic-gate         return ( -1 );
670*0Sstevel@tonic-gate     }
671*0Sstevel@tonic-gate 
672*0Sstevel@tonic-gate     return( ldapssl_clientauth_init( certdbpath, certdbhandle,
673*0Sstevel@tonic-gate             0, NULL, NULL ));
674*0Sstevel@tonic-gate }
675*0Sstevel@tonic-gate 
676*0Sstevel@tonic-gate /*
677*0Sstevel@tonic-gate  * Function that makes an asynchronous Start TLS extended operation request.
678*0Sstevel@tonic-gate  */
679*0Sstevel@tonic-gate static int ldapssl_tls_start(LDAP *ld, int *msgidp)
680*0Sstevel@tonic-gate {
681*0Sstevel@tonic-gate     int version, rc;
682*0Sstevel@tonic-gate     BerValue extreq_data;
683*0Sstevel@tonic-gate 
684*0Sstevel@tonic-gate     /* Start TLS extended operation requires an absent "requestValue" field. */
685*0Sstevel@tonic-gate 
686*0Sstevel@tonic-gate     extreq_data.bv_val = NULL;
687*0Sstevel@tonic-gate     extreq_data.bv_len = 0;
688*0Sstevel@tonic-gate 
689*0Sstevel@tonic-gate     /* Make sure version is set to LDAPv3 for extended operations to be
690*0Sstevel@tonic-gate        supported. */
691*0Sstevel@tonic-gate 
692*0Sstevel@tonic-gate     version = LDAP_VERSION3;
693*0Sstevel@tonic-gate     ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
694*0Sstevel@tonic-gate 
695*0Sstevel@tonic-gate     /* Send the Start TLS request (OID: 1.3.6.1.4.1.1466.20037) */
696*0Sstevel@tonic-gate     rc = ldap_extended_operation( ld, START_TLS_OID, &extreq_data,
697*0Sstevel@tonic-gate               NULL, NULL, msgidp );
698*0Sstevel@tonic-gate 
699*0Sstevel@tonic-gate     return rc;
700*0Sstevel@tonic-gate }
701*0Sstevel@tonic-gate 
702*0Sstevel@tonic-gate 
703*0Sstevel@tonic-gate /*
704*0Sstevel@tonic-gate  * Function that enables SSL on an already open non-secured LDAP connection.
705*0Sstevel@tonic-gate  * (i.e. the connection is henceforth secured)
706*0Sstevel@tonic-gate  */
707*0Sstevel@tonic-gate static int ldapssl_enableSSL_on_open_connection(LDAP *ld, int defsecure,
708*0Sstevel@tonic-gate 	char *certdbpath, char *keydbpath)
709*0Sstevel@tonic-gate {
710*0Sstevel@tonic-gate     PRLDAPSocketInfo  soi;
711*0Sstevel@tonic-gate 
712*0Sstevel@tonic-gate 
713*0Sstevel@tonic-gate     if ( ldapssl_clientauth_init( certdbpath, NULL, 1, keydbpath, NULL ) < 0 ) {
714*0Sstevel@tonic-gate 	goto ssl_setup_failure;
715*0Sstevel@tonic-gate     }
716*0Sstevel@tonic-gate 
717*0Sstevel@tonic-gate     /*
718*0Sstevel@tonic-gate      * Retrieve socket info. so we have the PRFileDesc.
719*0Sstevel@tonic-gate      */
720*0Sstevel@tonic-gate     memset( &soi, 0, sizeof(soi));
721*0Sstevel@tonic-gate     soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
722*0Sstevel@tonic-gate     if ( prldap_get_default_socket_info( ld, &soi ) < 0 ) {
723*0Sstevel@tonic-gate         goto ssl_setup_failure;
724*0Sstevel@tonic-gate     }
725*0Sstevel@tonic-gate 
726*0Sstevel@tonic-gate     if ( ldapssl_install_routines( ld ) < 0 ) {
727*0Sstevel@tonic-gate         goto ssl_setup_failure;
728*0Sstevel@tonic-gate     }
729*0Sstevel@tonic-gate 
730*0Sstevel@tonic-gate 
731*0Sstevel@tonic-gate     if (soi.soinfo_prfd == NULL) {
732*0Sstevel@tonic-gate         int sd;
733*0Sstevel@tonic-gate         ldap_get_option( ld, LDAP_OPT_DESC, &sd );
734*0Sstevel@tonic-gate         soi.soinfo_prfd = (PRFileDesc *) PR_ImportTCPSocket( sd );
735*0Sstevel@tonic-gate     }
736*0Sstevel@tonic-gate     /* set the socket information back into the connection handle,
737*0Sstevel@tonic-gate      * because ldapssl_install_routines() resets the socket_arg info in the
738*0Sstevel@tonic-gate      * socket buffer. */
739*0Sstevel@tonic-gate     if ( prldap_set_default_socket_info( ld, &soi ) != LDAP_SUCCESS ) {
740*0Sstevel@tonic-gate       goto ssl_setup_failure;
741*0Sstevel@tonic-gate     }
742*0Sstevel@tonic-gate 
743*0Sstevel@tonic-gate     if ( ldap_set_option( ld, LDAP_OPT_SSL,
744*0Sstevel@tonic-gate 	defsecure ? LDAP_OPT_ON : LDAP_OPT_OFF ) < 0 ) {
745*0Sstevel@tonic-gate         goto ssl_setup_failure;
746*0Sstevel@tonic-gate     }
747*0Sstevel@tonic-gate 
748*0Sstevel@tonic-gate     if ( ldapssl_import_fd( ld, defsecure ) < 0 ) {
749*0Sstevel@tonic-gate         goto ssl_setup_failure;
750*0Sstevel@tonic-gate     }
751*0Sstevel@tonic-gate 
752*0Sstevel@tonic-gate     return 0;
753*0Sstevel@tonic-gate 
754*0Sstevel@tonic-gate ssl_setup_failure:
755*0Sstevel@tonic-gate     ldapssl_reset_to_nonsecure( ld );
756*0Sstevel@tonic-gate 
757*0Sstevel@tonic-gate     /* we should here warn the server that we switch back to a non-secure
758*0Sstevel@tonic-gate        connection */
759*0Sstevel@tonic-gate 
760*0Sstevel@tonic-gate     return( -1 );
761*0Sstevel@tonic-gate }
762*0Sstevel@tonic-gate 
763*0Sstevel@tonic-gate 
764*0Sstevel@tonic-gate /*
765*0Sstevel@tonic-gate  * ldapssl_tls_start_s() performs a synchronous Start TLS extended operation
766*0Sstevel@tonic-gate  * request.
767*0Sstevel@tonic-gate  *
768*0Sstevel@tonic-gate  * The function returns the result code of the extended operation response
769*0Sstevel@tonic-gate  * sent by the server.
770*0Sstevel@tonic-gate  *
771*0Sstevel@tonic-gate  * In case of a successfull response (LDAP_SUCCESS returned), by the time
772*0Sstevel@tonic-gate  * this function returns the LDAP session designed by ld will have been
773*0Sstevel@tonic-gate  * secured, i.e. the connection will have been imported into SSL.
774*0Sstevel@tonic-gate  *
775*0Sstevel@tonic-gate  * Should the Start TLS request be rejected by the server, the result code
776*0Sstevel@tonic-gate  * returned will be one of the following:
777*0Sstevel@tonic-gate  *    LDAP_OPERATIONS_ERROR,
778*0Sstevel@tonic-gate  *    LDAP_PROTOCOL_ERROR,
779*0Sstevel@tonic-gate  *    LDAP_REFERRAL,
780*0Sstevel@tonic-gate  *    LDAP_UNAVAILABLE.
781*0Sstevel@tonic-gate  *
782*0Sstevel@tonic-gate  * Any other error code returned will be due to a failure in the course
783*0Sstevel@tonic-gate  * of operations done on the client side.
784*0Sstevel@tonic-gate  *
785*0Sstevel@tonic-gate  * "certdbpath" and "keydbpath" should contain the path to the client's
786*0Sstevel@tonic-gate  * certificate and key databases respectively. Either the path to the
787*0Sstevel@tonic-gate  * directory containing "default name" databases (i.e. cert7.db and key3.db)
788*0Sstevel@tonic-gate  * can be specified or the actual filenames can be included.
789*0Sstevel@tonic-gate  * If any of these parameters is NULL, the function will assume the database
790*0Sstevel@tonic-gate  * is the same used by Netscape Communicator, which is usually under
791*0Sstevel@tonic-gate  * ~/.netsca /)
792*0Sstevel@tonic-gate  *
793*0Sstevel@tonic-gate  * "referralsp" is a pointer to a list of referrals the server might
794*0Sstevel@tonic-gate  * eventually send back with an LDAP_REFERRAL result code.
795*0Sstevel@tonic-gate  *
796*0Sstevel@tonic-gate  */
797*0Sstevel@tonic-gate 
798*0Sstevel@tonic-gate int
799*0Sstevel@tonic-gate LDAP_CALL
800*0Sstevel@tonic-gate ldapssl_tls_start_s(LDAP *ld,int defsecure, char *certdbpath, char *keydbpath,
801*0Sstevel@tonic-gate 	char ***referralsp)
802*0Sstevel@tonic-gate {
803*0Sstevel@tonic-gate     int             rc, resultCode, msgid;
804*0Sstevel@tonic-gate     char            *extresp_oid;
805*0Sstevel@tonic-gate     BerValue        *extresp_data;
806*0Sstevel@tonic-gate     LDAPMessage     *res;
807*0Sstevel@tonic-gate 
808*0Sstevel@tonic-gate     rc = ldapssl_tls_start( ld, &msgid );
809*0Sstevel@tonic-gate     if ( rc != LDAP_SUCCESS ) {
810*0Sstevel@tonic-gate          return rc;
811*0Sstevel@tonic-gate     }
812*0Sstevel@tonic-gate 
813*0Sstevel@tonic-gate     rc = ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res );
814*0Sstevel@tonic-gate     if ( rc != LDAP_RES_EXTENDED ) {
815*0Sstevel@tonic-gate 
816*0Sstevel@tonic-gate       /* the first response received must be an extended response to an
817*0Sstevel@tonic-gate        Start TLS request */
818*0Sstevel@tonic-gate 
819*0Sstevel@tonic-gate          ldap_msgfree( res );
820*0Sstevel@tonic-gate          return( -1 );
821*0Sstevel@tonic-gate 
822*0Sstevel@tonic-gate     }
823*0Sstevel@tonic-gate 
824*0Sstevel@tonic-gate     rc = ldap_parse_extended_result( ld, res, &extresp_oid, &extresp_data, 0 );
825*0Sstevel@tonic-gate 
826*0Sstevel@tonic-gate     if ( rc != LDAP_SUCCESS ) {
827*0Sstevel@tonic-gate          ldap_msgfree( res );
828*0Sstevel@tonic-gate          return rc;
829*0Sstevel@tonic-gate     }
830*0Sstevel@tonic-gate 
831*0Sstevel@tonic-gate     if ( strcasecmp( extresp_oid, START_TLS_OID ) != 0 ) {
832*0Sstevel@tonic-gate 
833*0Sstevel@tonic-gate          /* the extended response received doesn't correspond to the
834*0Sstevel@tonic-gate           Start TLS request */
835*0Sstevel@tonic-gate 
836*0Sstevel@tonic-gate          ldap_msgfree( res );
837*0Sstevel@tonic-gate          return -1;
838*0Sstevel@tonic-gate     }
839*0Sstevel@tonic-gate 
840*0Sstevel@tonic-gate     resultCode = ldap_get_lderrno( ld, NULL, NULL );
841*0Sstevel@tonic-gate 
842*0Sstevel@tonic-gate     /* Analyze the server's response */
843*0Sstevel@tonic-gate     switch (resultCode) {
844*0Sstevel@tonic-gate     case LDAP_REFERRAL:
845*0Sstevel@tonic-gate       {
846*0Sstevel@tonic-gate       rc = ldap_parse_result( ld, res, NULL, NULL, NULL, referralsp, NULL, 0 );
847*0Sstevel@tonic-gate       if ( rc != LDAP_SUCCESS ) {
848*0Sstevel@tonic-gate           ldap_msgfree( res );
849*0Sstevel@tonic-gate           return rc;
850*0Sstevel@tonic-gate       }
851*0Sstevel@tonic-gate     }
852*0Sstevel@tonic-gate     case LDAP_OPERATIONS_ERROR:
853*0Sstevel@tonic-gate 
854*0Sstevel@tonic-gate     case LDAP_PROTOCOL_ERROR:
855*0Sstevel@tonic-gate 
856*0Sstevel@tonic-gate     case LDAP_UNAVAILABLE:
857*0Sstevel@tonic-gate         goto free_msg_and_return;
858*0Sstevel@tonic-gate     case LDAP_SUCCESS:
859*0Sstevel@tonic-gate       {
860*0Sstevel@tonic-gate       /*
861*0Sstevel@tonic-gate        * If extended response successfull, get connection ready for
862*0Sstevel@tonic-gate        * communicating with the server over SSL/TLS.
863*0Sstevel@tonic-gate        */
864*0Sstevel@tonic-gate 
865*0Sstevel@tonic-gate       if ( ldapssl_enableSSL_on_open_connection( ld, defsecure,
866*0Sstevel@tonic-gate                                          certdbpath, keydbpath ) < 0 ) {
867*0Sstevel@tonic-gate           resultCode = -1;
868*0Sstevel@tonic-gate       }
869*0Sstevel@tonic-gate 
870*0Sstevel@tonic-gate     } /* case LDAP_SUCCESS */
871*0Sstevel@tonic-gate     default:
872*0Sstevel@tonic-gate         goto free_msg_and_return;
873*0Sstevel@tonic-gate     } /* switch */
874*0Sstevel@tonic-gate 
875*0Sstevel@tonic-gate free_msg_and_return:
876*0Sstevel@tonic-gate     ldap_msgfree( res );
877*0Sstevel@tonic-gate     return resultCode;
878*0Sstevel@tonic-gate }
879*0Sstevel@tonic-gate 
880*0Sstevel@tonic-gate #endif /* NET_SSL */
881