/*
*/
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
*/
#if defined(NET_SSL)
#if defined( _WINDOWS )
#include <windows.h>
#include "proto-ntutil.h"
#endif
#include <nspr.h>
#include <plstr.h>
#include <synch.h>
#include <cert.h>
#include <key.h>
#include <ssl.h>
#include <sslproto.h>
#include <ldap.h>
#include <ldappr.h>
#include <solaris-int.h>
#include <nss.h>
/* XXX:mhein The following is a workaround for the redefinition of */
/* const problem on OSF. Fix to be provided by NSS */
/* This is a pretty benign workaround for us which */
/* should not cause problems in the future even if */
/* we forget to take it out :-) */
#ifdef OSF1V4D
#ifndef __STDC__
# define __STDC__
#endif /* __STDC__ */
#endif /* OSF1V4D */
#ifndef FILE_PATHSEP
#endif
/*
* StartTls()
*/
static PRStatus local_SSLPLCY_Install(void);
/*
* This little tricky guy keeps us from initializing twice
*/
static int inited = 0;
#ifdef _SOLARIS_SDK
#else
#endif /* _SOLARIS_SDK */
#if 0 /* UNNEEDED BY LIBLDAP */
#endif /* UNNEEDED BY LIBLDAP */
/* IN: */
/* OUT: */
/* prefix: my */
/* key: key3.db */
static int
char *k;
char *s;
char *d = string;
char *l;
int len = 0;
return (-1);
/* goto the end of the string, and walk backwards until */
/* you get to the first pathseparator */
l--;
/* search for the .db */
/* now we are sitting on . of .db */
/* move backward to the first 'c' or 'k' */
/* indicating cert or key */
while (k != l && *k != 'c' && *k != 'k')
k--;
/* move backwards to the first path separator */
if (k != d && k > d)
s = k - 1;
while (s != d && *s != '/' && *s != '\\')
s--;
/* if we are sitting on top of a path */
/* separator there is no prefix */
if (s + 1 == k) {
/* we know there is no prefix */
prefix = '\0';
*k = '\0';
} else {
/* grab the prefix */
*k = '\0';
*s = '\0';
}
} else {
/* neither *key[0-9].db nor *cert[0=9].db found */
return (-1);
}
return (0);
}
{
SECStatus s;
#ifdef NS_DOMESTIC
s = NSS_SetDomesticPolicy();
s = NSS_SetExportPolicy();
#else
s = PR_FAILURE;
#endif
return s?PR_FAILURE:PR_SUCCESS;
}
static void
ldapssl_basic_init( void )
{
#ifndef _SOLARIS_SDK
/*
* NSPR is initialized in .init on SOLARIS
*/
/* PR_Init() must to be called before everything else... */
#endif
}
/*
* Cover functions for malloc(), calloc(), strdup() and free() that are
* compatible with the NSS libraries (they seem to use the C runtime
*/
static void *
{
void *p;
return p;
}
static void *
{
void *p;
return p;
}
static char *
ldapssl_strdup( const char *s )
{
char *scopy;
if ( NULL == s ) {
} else {
}
return scopy;
}
static void
{
}
}
#ifdef _SOLARIS_SDK
/*
* Disable strict fork detection of NSS library to allow safe fork of
* consumers. Otherwise NSS will not work after fork because it was not
* deinitialized before fork and there is no safe way how to do it after fork.
*
* Return values:
* 1 - DISABLED was already set, no modification to environment
* 0 - successfully modified environment, old value saved to enval if there
* was some
* -1 - setenv or strdup failed, the environment was left unchanged
*
*/
static int
{
/* Do not need to set as DISABLED, it is already set. */
return (1);
} else {
return (-1);
}
}
/*
* Reset environment variable NSS_STRICT_NOFORK to value before
* update_nss_strict_fork_env() call or remove it from environment if it did
* not exist.
* NSS_STRICT_NOFORK=DISABLED is needed only during NSS initialization to
* disable activation of atfork handler in NSS which is invalidating
* initialization in child process after fork.
*/
static int
{
} else {
return (unsetenv("NSS_STRICT_NOFORK"));
}
}
#endif
static char *
{
char *result;
if (basename)
{
return (ldapssl_strdup(basename));
}
if ( addslash ) {
++len;
}
if ( addslash ) {
++pathlen;
}
}
}
return result;
}
char *
{
char *source;
if (!source)
{
source = "";
}
}
/*
* return database name by appending "dbname" to "path".
* this code doesn't need to be terribly efficient (not called often).
*/
/* XXXceb this is the old function. To be removed eventually */
static char *
{
char *result;
int addslash;
dbname = "";
}
} else {
if ( addslash ) {
++len;
}
if ( addslash ) {
++pathlen;
}
}
}
return result;
}
/*
* It is safe to call this more than once.
*
* If needkeydb == 0, no key database is opened and SSL server authentication
* is supported but not client authentication.
*
* If "certdbpath" is NULL or "", the default cert. db is used (typically
*
* If "certdbpath" ends with ".db" (case-insensitive compare), then
* it is assumed to be a full path to the cert. db file; otherwise,
* it is assumed to be a directory that contains a file called
* "cert7.db" or "cert.db".
*
* If certdbhandle is non-NULL, it is assumed to be a pointer to a
* SECCertDBHandle structure. It is fine to pass NULL since this
* routine will allocate one for you (CERT_GetDefaultDB() can be
* used to retrieve the cert db handle).
*
* If "keydbpath" is NULL or "", the default key db is used (typically
*
* If "keydbpath" ends with ".db" (case-insensitive compare), then
* it is assumed to be a full path to the key db file; otherwise,
* it is assumed to be a directory that contains a file called
* "key3.db"
*
* If certdbhandle is non-NULL< it is assumed to be a pointed to a
* SECKEYKeyDBHandle structure. It is fine to pass NULL since this
* routine will allocate one for you (SECKEY_GetDefaultDB() can be
* used to retrieve the cert db handle).
*/
int
{
int rc;
#ifdef _SOLARIS_SDK
char *enval;
int rcenv = 0;
#endif
/*
* LDAPDebug(LDAP_DEBUG_TRACE, "ldapssl_clientauth_init\n",0 ,0 ,0);
*/
if ( inited ) {
return( 0 );
}
#ifdef _SOLARIS_SDK
return (-1);
}
#endif
/* Open the certificate database */
#ifdef _SOLARIS_SDK
/* Error from NSS_Init() more important! */
return (-1);
}
#endif
if (rc != 0) {
if ((rc = PR_GetError()) >= 0)
rc = -1;
return (rc);
}
if (( rc = PR_GetError()) >= 0 ) {
rc = -1;
}
return( rc );
}
#if defined(NS_DOMESTIC)
if (local_SSLPLCY_Install() == PR_FAILURE) {
return( -1 );
}
if (local_SSLPLCY_Install() == PR_FAILURE) {
return( -1 );
}
#else
return( -1 );
#endif
inited = 1;
return( 0 );
}
/*
* It is safe to call this more than once.
*
* If needkeydb == 0, no key database is opened and SSL server authentication
* is supported but not client authentication.
*
* If "certdbpath" is NULL or "", the default cert. db is used (typically
*
* If "certdbpath" ends with ".db" (case-insensitive compare), then
* it is assumed to be a full path to the cert. db file; otherwise,
* it is assumed to be a directory that contains a file called
* "cert7.db" or "cert.db".
*
* If certdbhandle is non-NULL, it is assumed to be a pointer to a
* SECCertDBHandle structure. It is fine to pass NULL since this
* routine will allocate one for you (CERT_GetDefaultDB() can be
* used to retrieve the cert db handle).
*
* If "keydbpath" is NULL or "", the default key db is used (typically
*
* If "keydbpath" ends with ".db" (case-insensitive compare), then
* it is assumed to be a full path to the key db file; otherwise,
* it is assumed to be a directory that contains a file called
* "key3.db"
*
* If certdbhandle is non-NULL< it is assumed to be a pointed to a
* SECKEYKeyDBHandle structure. It is fine to pass NULL since this
* routine will allocate one for you (SECKEY_GetDefaultDB() can be
* used to retrieve the cert db handle). */
int
const char *certdbpath, void *certdbhandle,
const int needsecmoddb, const char *secmoddbpath,
const int sslstrength )
{
int rc;
#ifdef _SOLARIS_SDK
char *enval;
int rcenv = 0;
#endif
if ( inited ) {
return( 0 );
}
/*
* LDAPDebug(LDAP_DEBUG_TRACE, "ldapssl_advclientauth_init\n",0 ,0 ,0);
*/
#ifdef _SOLARIS_SDK
return (-1);
}
#endif
#ifdef _SOLARIS_SDK
/* Error from NSS_Init() more important! */
return (-1);
}
#endif
if (rc != 0) {
if ((rc = PR_GetError()) >= 0)
rc = -1;
return (rc);
}
#if defined(NS_DOMESTIC)
if (local_SSLPLCY_Install() == PR_FAILURE) {
return( -1 );
}
if (local_SSLPLCY_Install() == PR_FAILURE) {
return( -1 );
}
#else
return( -1 );
#endif
inited = 1;
}
/*
* It is safe to call this more than once.
*/
/*
* XXXceb This is a hack until the new IO functions are done.
* this function lives in ldapsinit.c
*/
void set_using_pkcs_functions( int val );
int
{
int rc;
#ifdef _SOLARIS_SDK
char *enval;
int rcenv = 0;
#endif
if ( inited ) {
return( 0 );
}
/*
* XXXceb This is a hack until the new IO functions are done.
* this function MUST be called before ldap_enable_clienauth.
*
*/
set_using_pkcs_functions( 1 );
/*
* LDAPDebug(LDAP_DEBUG_TRACE, "ldapssl_pkcs_init\n",0 ,0 ,0);
*/
confDir = ldapssl_strdup( s );
certdbPrefix = ldapssl_strdup( s );
certdbName = ldapssl_strdup( s );
*certdbPrefix = 0;
keydbpath = ldapssl_strdup( s );
keydbPrefix = ldapssl_strdup( s );
keydbName = ldapssl_strdup( s );
*keydbPrefix = 0;
/* verify confDir == keydbpath and adjust as necessary */
ldapssl_free((void **)&certdbName);
ldapssl_free((void **)&keydbName);
ldapssl_free((void **)&keydbpath);
#ifdef _SOLARIS_SDK
return (-1);
}
#endif
ldapssl_free((void **)&certdbPrefix);
ldapssl_free((void **)&keydbPrefix);
ldapssl_free((void **)&confDir);
#ifdef _SOLARIS_SDK
/* Error from NSS_Initialize() more important! */
return (-1);
}
#endif
if (rc != 0) {
if ((rc = PR_GetError()) >= 0)
rc = -1;
return (rc);
}
#if 0 /* UNNEEDED BY LIBLDAP */
/* this is odd */
#endif /* UNNEEDED BY LIBLDAP */
if (( rc = PR_GetError()) >= 0 ) {
rc = -1;
}
return( rc );
}
#if defined(NS_DOMESTIC)
if (local_SSLPLCY_Install() == PR_FAILURE) {
return( -1 );
}
if (local_SSLPLCY_Install() == PR_FAILURE) {
return( -1 );
}
#else
return( -1 );
#endif
inited = 1;
if ( certdbName != NULL ) {
ldapssl_free((void **) &certdbName );
}
}
/*
* ldapssl_client_init() is a server-authentication only version of
* ldapssl_clientauth_init().
*/
int
{
}
/*
* ldapssl_serverauth_init() is a server-authentication only version of
* ldapssl_clientauth_init(). This function allows the sslstrength
* to be passed in. The sslstrength can take one of the following
* values:
* LDAPSSL_AUTH_WEAK: indicate that you accept the server's
* certificate without checking the CA who
* issued the certificate
* LDAPSSL_AUTH_CERT: indicates that you accept the server's
* certificate only if you trust the CA who
* issued the certificate
* LDAPSSL_AUTH_CNCHECK:
indicates that you accept the server's
* certificate only if you trust the CA who
* issued the certificate and if the value
* of the cn attribute in the DNS hostname
* of the server
*/
int
void *certdbhandle,
const int sslstrength )
{
return ( -1 );
}
}
/*
* Function that makes an asynchronous Start TLS extended operation request.
*/
{
/* Start TLS extended operation requires an absent "requestValue" field. */
extreq_data.bv_len = 0;
/* Make sure version is set to LDAPv3 for extended operations to be
supported. */
/* Send the Start TLS request (OID: 1.3.6.1.4.1.1466.20037) */
return rc;
}
/*
* Function that enables SSL on an already open non-secured LDAP connection.
* (i.e. the connection is henceforth secured)
*/
char *certdbpath, char *keydbpath)
{
goto ssl_setup_failure;
}
/*
* Retrieve socket info. so we have the PRFileDesc.
*/
goto ssl_setup_failure;
}
if ( ldapssl_install_routines( ld ) < 0 ) {
goto ssl_setup_failure;
}
int sd;
}
/* set the socket information back into the connection handle,
* because ldapssl_install_routines() resets the socket_arg info in the
* socket buffer. */
goto ssl_setup_failure;
}
goto ssl_setup_failure;
}
goto ssl_setup_failure;
}
return 0;
/* we should here warn the server that we switch back to a non-secure
connection */
return( -1 );
}
/*
* ldapssl_tls_start_s() performs a synchronous Start TLS extended operation
* request.
*
* The function returns the result code of the extended operation response
* sent by the server.
*
* In case of a successfull response (LDAP_SUCCESS returned), by the time
* this function returns the LDAP session designed by ld will have been
* secured, i.e. the connection will have been imported into SSL.
*
* Should the Start TLS request be rejected by the server, the result code
* returned will be one of the following:
* LDAP_OPERATIONS_ERROR,
* LDAP_PROTOCOL_ERROR,
* LDAP_REFERRAL,
* LDAP_UNAVAILABLE.
*
* Any other error code returned will be due to a failure in the course
* of operations done on the client side.
*
* "certdbpath" and "keydbpath" should contain the path to the client's
* certificate and key databases respectively. Either the path to the
* directory containing "default name" databases (i.e. cert7.db and key3.db)
* can be specified or the actual filenames can be included.
* If any of these parameters is NULL, the function will assume the database
* is the same used by Netscape Communicator, which is usually under
* ~/.netsca /)
*
* "referralsp" is a pointer to a list of referrals the server might
* eventually send back with an LDAP_REFERRAL result code.
*
*/
int
char ***referralsp)
{
char *extresp_oid;
if ( rc != LDAP_SUCCESS ) {
return rc;
}
if ( rc != LDAP_RES_EXTENDED ) {
/* the first response received must be an extended response to an
Start TLS request */
ldap_msgfree( res );
return( -1 );
}
if ( rc != LDAP_SUCCESS ) {
ldap_msgfree( res );
return rc;
}
/* the extended response received doesn't correspond to the
Start TLS request */
ldap_msgfree( res );
return -1;
}
/* Analyze the server's response */
switch (resultCode) {
case LDAP_REFERRAL:
{
if ( rc != LDAP_SUCCESS ) {
ldap_msgfree( res );
return rc;
}
}
case LDAP_OPERATIONS_ERROR:
case LDAP_PROTOCOL_ERROR:
case LDAP_UNAVAILABLE:
goto free_msg_and_return;
case LDAP_SUCCESS:
{
/*
* If extended response successfull, get connection ready for
*/
certdbpath, keydbpath ) < 0 ) {
resultCode = -1;
}
} /* case LDAP_SUCCESS */
default:
goto free_msg_and_return;
} /* switch */
ldap_msgfree( res );
return resultCode;
}
#endif /* NET_SSL */