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