/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2008-2012 The OpenLDAP Foundation.
+ * Copyright 2008-2017 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* capability the server would have to be started in foreground mode
* if using an encrypted key.
*/
- if ( ctx->tc_pin_file ) {
+ if ( ctx && ctx->tc_pin_file ) {
pwdstr = tlsm_get_pin_from_file( token_name, ctx );
- if (retry && pwdstr != NULL)
+ if ( retry && pwdstr != NULL )
return NULL;
}
#endif /* RETRIEVE_PASSWORD_FROM_FILE */
int infd = PR_FileDesc2NativeHandle( PR_STDIN );
int isTTY = isatty( infd );
unsigned char phrase[200];
+ char *dummy;
/* Prompt for password */
if ( isTTY ) {
fprintf( stdout,
token_name ? token_name : DEFAULT_TOKEN_NAME );
echoOff( infd );
}
- fgets( (char*)phrase, sizeof(phrase), stdin );
+ dummy = fgets( (char*)phrase, sizeof(phrase), stdin );
+ (void) dummy;
if ( isTTY ) {
fprintf( stdout, "\n" );
echoOn( infd );
static char *
tlsm_ctx_subject_name(tlsm_ctx *ctx)
{
- if (!ctx || !ctx->tc_certificate)
+ if ( !ctx || !ctx->tc_certificate )
return "(unknown)";
return ctx->tc_certificate->subjectName;
return is_self_issued;
}
+/*
+ * The private key for used certificate can be already unlocked by other
+ * thread or library. Find the unlocked key if possible.
+ */
+static SECKEYPrivateKey *
+tlsm_find_unlocked_key( tlsm_ctx *ctx, void *pin_arg )
+{
+ SECKEYPrivateKey *result = NULL;
+
+ PK11SlotList *slots = PK11_GetAllSlotsForCert( ctx->tc_certificate, NULL );
+ if ( !slots ) {
+ PRErrorCode errcode = PR_GetError();
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: cannot get all slots for certificate '%s' (error %d: %s)",
+ tlsm_ctx_subject_name( ctx ), errcode,
+ PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
+ return result;
+ }
+
+ PK11SlotListElement *le;
+ for ( le = slots->head; le; le = le->next ) {
+ PK11SlotInfo *slot = le->slot;
+ if ( PK11_IsLoggedIn( slot, NULL ) ) {
+ result = PK11_FindKeyByDERCert( slot, ctx->tc_certificate, pin_arg );
+ break;
+ }
+ }
+
+ PK11_FreeSlotList( slots );
+ return result;
+}
+
static SECStatus
tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
- PRBool checksig, SECCertificateUsage certUsage, int errorToIgnore )
+ PRBool checksig, SECCertificateUsage certUsage, PRBool warn_only,
+ PRBool ignore_issuer )
{
CERTVerifyLog verifylog;
SECStatus ret = SECSuccess;
const char *name;
int debug_level = LDAP_DEBUG_ANY;
- if ( errorToIgnore == -1 ) {
+ if ( warn_only ) {
debug_level = LDAP_DEBUG_TRACE;
}
name, 0, 0 );
}
- PR_SetError(orig_error, orig_oserror);
+ PR_SetError( orig_error, orig_oserror );
- } else if ( errorToIgnore && ( node->error == errorToIgnore ) ) {
+ } else if ( warn_only || ( ignore_issuer && (
+ node->error == SEC_ERROR_UNKNOWN_ISSUER ||
+ node->error == SEC_ERROR_UNTRUSTED_ISSUER )
+ ) ) {
+ ret = SECSuccess;
Debug( debug_level,
"TLS: Warning: ignoring error for certificate [%s] - error %ld:%s.\n",
name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
if ( ret == SECSuccess ) {
Debug( LDAP_DEBUG_TRACE,
"TLS: certificate [%s] is valid\n", name, 0, 0 );
- } else if ( errorToIgnore == -1 ) {
- ret = SECSuccess;
}
return ret;
SECCertificateUsage certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;
SECStatus ret = SECSuccess;
CERTCertificate *peercert = SSL_PeerCertificate( fd );
- int errorToIgnore = 0;
tlsm_ctx *ctx = (tlsm_ctx *)arg;
- if (ctx && ctx->tc_warn_only )
- errorToIgnore = -1;
-
ret = tlsm_verify_cert( ctx->tc_certdb, peercert,
SSL_RevealPinArg( fd ),
- checksig, certUsage, errorToIgnore );
+ checksig, certUsage, ctx->tc_warn_only, PR_FALSE );
CERT_DestroyCertificate( peercert );
return ret;
return -1;
}
- PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof(objClass) );
- PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) );
- PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 );
- PK11_SETATTRS( attrs[3], CKA_TRUST, isca ? &cktrue : &ckfalse, sizeof(CK_BBOOL) );
+ PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) );
+ PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) );
+ PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *) filename, strlen( filename ) + 1 );
+ PK11_SETATTRS( attrs[3], CKA_TRUST, isca ? &cktrue : &ckfalse, sizeof( CK_BBOOL ) );
cert = PK11_CreateGenericObject( slot, attrs, 4, PR_FALSE /* isPerm */ );
}
static int
-tlsm_ctx_load_private_key(tlsm_ctx *ctx)
+tlsm_ctx_load_private_key( tlsm_ctx *ctx )
{
- if (!ctx->tc_certificate)
+ if ( !ctx->tc_certificate )
return -1;
- if (ctx->tc_private_key)
+ if ( ctx->tc_private_key )
return 0;
- void *pin_arg = SSL_RevealPinArg(ctx->tc_model);
+ void *pin_arg = SSL_RevealPinArg( ctx->tc_model );
+
+ SECKEYPrivateKey *unlocked_key = tlsm_find_unlocked_key( ctx, pin_arg );
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: %s unlocked certificate for certificate '%s'.\n",
+ unlocked_key ? "found" : "no", tlsm_ctx_subject_name( ctx ), 0 );
- ctx->tc_private_key = PK11_FindKeyByAnyCert(ctx->tc_certificate, pin_arg);
- if (!ctx->tc_private_key) {
+ /* prefer unlocked key, then key from opened certdb, then any other */
+ if ( unlocked_key )
+ ctx->tc_private_key = unlocked_key;
+ else if ( ctx->tc_certdb_slot )
+ ctx->tc_private_key = PK11_FindKeyByDERCert( ctx->tc_certdb_slot, ctx->tc_certificate, pin_arg );
+ else
+ ctx->tc_private_key = PK11_FindKeyByAnyCert( ctx->tc_certificate, pin_arg );
+
+ if ( !ctx->tc_private_key ) {
PRErrorCode errcode = PR_GetError();
Debug(LDAP_DEBUG_ANY,
"TLS: cannot find private key for certificate '%s' (error %d: %s)",
- tlsm_ctx_subject_name(ctx), errcode,
- PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT));
+ tlsm_ctx_subject_name( ctx ), errcode,
+ PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
return -1;
}
return -1;
}
- PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof(objClass) );
- PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) );
- PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 );
+ PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) );
+ PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) );
+ PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen( filename ) + 1 );
key = PK11_CreateGenericObject( slot, attrs, 3, PR_FALSE /* isPerm */ );
* which is unique for each context.
*/
static PK11SlotInfo *
-tlsm_init_open_certdb(tlsm_ctx *ctx, const char *dbdir, const char *prefix)
+tlsm_init_open_certdb( tlsm_ctx *ctx, const char *dbdir, const char *prefix )
{
PK11SlotInfo *slot = NULL;
char *token_desc = NULL;
char *config = NULL;
- token_desc = PR_smprintf(TLSM_CERTDB_DESC_FMT, ctx->tc_unique);
- config = PR_smprintf("configDir='%s' tokenDescription='%s' certPrefix='%s' keyPrefix='%s' flags=readOnly",
- dbdir, token_desc, prefix, prefix);
- Debug(LDAP_DEBUG_TRACE, "TLS: certdb config: %s\n", config, 0, 0);
+ token_desc = PR_smprintf( TLSM_CERTDB_DESC_FMT, ctx->tc_unique );
+ config = PR_smprintf( "configDir='%s' tokenDescription='%s' certPrefix='%s' keyPrefix='%s' flags=readOnly",
+ dbdir, token_desc, prefix, prefix );
+ Debug( LDAP_DEBUG_TRACE, "TLS: certdb config: %s\n", config, 0, 0 );
- slot = SECMOD_OpenUserDB(config);
- if (!slot) {
+ slot = SECMOD_OpenUserDB( config );
+ if ( !slot ) {
PRErrorCode errcode = PR_GetError();
- Debug(LDAP_DEBUG_TRACE, "TLS: cannot open certdb '%s', error %d:%s\n", dbdir, errcode,
- PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT));
+ Debug( LDAP_DEBUG_TRACE, "TLS: cannot open certdb '%s', error %d:%s\n", dbdir, errcode,
+ PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
}
- if (token_desc)
- PR_smprintf_free(token_desc);
- if (config)
- PR_smprintf_free(config);
+ if ( token_desc )
+ PR_smprintf_free( token_desc );
+ if ( config )
+ PR_smprintf_free( config );
return slot;
}
NSSInitContext *initctx = NULL;
PK11SlotInfo *certdb_slot = NULL;
#endif
+ SSLVersionRange range;
+ SSLProtocolVariant variant;
SECStatus rc;
int done = 0;
#endif
rc = SECFailure;
- if (initctx != NULL) {
- certdb_slot = tlsm_init_open_certdb(ctx, realcertdir, prefix);
- if (certdb_slot) {
+ if ( initctx != NULL ) {
+ certdb_slot = tlsm_init_open_certdb( ctx, realcertdir, prefix );
+ if ( certdb_slot ) {
rc = SECSuccess;
ctx->tc_initctx = initctx;
ctx->tc_certdb_slot = certdb_slot;
} else {
- NSS_ShutdownContext(initctx);
+ NSS_ShutdownContext( initctx );
initctx = NULL;
}
}
#else
initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB,
&initParams, flags );
- if (initctx) {
+ if ( initctx ) {
ctx->tc_initctx = initctx;
rc = SECSuccess;
} else {
ctx->tc_using_pem = PR_TRUE;
}
+ /*
+ * Set the SSL version range. MozNSS SSL versions are the same as openldap's:
+ *
+ * SSL_LIBRARY_VERSION_TLS_1_* are equivalent to LDAP_OPT_X_TLS_PROTOCOL_TLS1_*
+ */
+ SSL_VersionRangeGetSupported(ssl_variant_stream, &range); /* this sets the max */
+ range.min = lt->lt_protocol_min ? lt->lt_protocol_min : range.min;
+ variant = ssl_variant_stream;
+ SSL_VersionRangeSetDefault(variant, &range);
+
NSS_SetDomesticPolicy();
PK11_SetPasswordFunc( tlsm_pin_prompt );
* The key is loaded and stored in ctx->tc_private_key
*/
static int
-tlsm_find_and_verify_cert_key(tlsm_ctx *ctx)
+tlsm_find_and_verify_cert_key( tlsm_ctx *ctx )
{
SECCertificateUsage certUsage;
PRBool checkSig;
SECStatus status;
- int errorToIgnore;
void *pin_arg;
- if (tlsm_ctx_load_private_key(ctx))
+ if ( tlsm_ctx_load_private_key( ctx ) )
return -1;
- pin_arg = SSL_RevealPinArg(ctx->tc_model);
+ pin_arg = SSL_RevealPinArg( ctx->tc_model );
certUsage = ctx->tc_is_server ? certificateUsageSSLServer : certificateUsageSSLClient;
checkSig = ctx->tc_verify_cert ? PR_TRUE : PR_FALSE;
- if ( ctx->tc_warn_only )
- errorToIgnore = -1;
- else
- errorToIgnore = SEC_ERROR_UNKNOWN_ISSUER; /* may not have a CA cert */
status = tlsm_verify_cert( ctx->tc_certdb, ctx->tc_certificate, pin_arg,
- checkSig, certUsage, errorToIgnore );
+ checkSig, certUsage, ctx->tc_warn_only, PR_TRUE );
return status == SECSuccess ? 0 : -1;
}
{
tlsm_ctx *ctx = (tlsm_ctx *)arg;
- if (pRetCert)
- *pRetCert = CERT_DupCertificate(ctx->tc_certificate);
+ if ( pRetCert )
+ *pRetCert = CERT_DupCertificate( ctx->tc_certificate );
- if (pRetKey)
- *pRetKey = SECKEY_CopyPrivateKey(ctx->tc_private_key);
+ if ( pRetKey )
+ *pRetKey = SECKEY_CopyPrivateKey( ctx->tc_private_key );
return SECSuccess;
}
{
struct ldaptls *copy;
- assert(config);
+ assert( config );
- copy = LDAP_MALLOC(sizeof(*copy));
- if (!copy)
+ copy = LDAP_MALLOC( sizeof( *copy ) );
+ if ( !copy )
return NULL;
- memset(copy, 0, sizeof(*copy));
-
- if (config->lt_certfile)
- copy->lt_certfile = LDAP_STRDUP(config->lt_certfile);
- if (config->lt_keyfile)
- copy->lt_keyfile = LDAP_STRDUP(config->lt_keyfile);
- if (config->lt_dhfile)
- copy->lt_dhfile = LDAP_STRDUP(config->lt_dhfile);
- if (config->lt_cacertfile)
- copy->lt_cacertfile = LDAP_STRDUP(config->lt_cacertfile);
- if (config->lt_cacertdir)
- copy->lt_cacertdir = LDAP_STRDUP(config->lt_cacertdir);
- if (config->lt_ciphersuite)
- copy->lt_ciphersuite = LDAP_STRDUP(config->lt_ciphersuite);
- if (config->lt_crlfile)
- copy->lt_crlfile = LDAP_STRDUP(config->lt_crlfile);
- if (config->lt_randfile)
- copy->lt_randfile = LDAP_STRDUP(config->lt_randfile);
+ memset( copy, 0, sizeof( *copy ) );
+
+ if ( config->lt_certfile )
+ copy->lt_certfile = LDAP_STRDUP( config->lt_certfile );
+ if ( config->lt_keyfile )
+ copy->lt_keyfile = LDAP_STRDUP( config->lt_keyfile );
+ if ( config->lt_dhfile )
+ copy->lt_dhfile = LDAP_STRDUP( config->lt_dhfile );
+ if ( config->lt_cacertfile )
+ copy->lt_cacertfile = LDAP_STRDUP( config->lt_cacertfile );
+ if ( config->lt_cacertdir )
+ copy->lt_cacertdir = LDAP_STRDUP( config->lt_cacertdir );
+ if ( config->lt_ciphersuite )
+ copy->lt_ciphersuite = LDAP_STRDUP( config->lt_ciphersuite );
+ if ( config->lt_crlfile )
+ copy->lt_crlfile = LDAP_STRDUP( config->lt_crlfile );
+ if ( config->lt_randfile )
+ copy->lt_randfile = LDAP_STRDUP( config->lt_randfile );
copy->lt_protocol_min = config->lt_protocol_min;
static void
tlsm_free_config ( struct ldaptls *config )
{
- assert(config);
+ assert( config );
- if (config->lt_certfile)
- LDAP_FREE(config->lt_certfile);
- if (config->lt_keyfile)
- LDAP_FREE(config->lt_keyfile);
- if (config->lt_dhfile)
- LDAP_FREE(config->lt_dhfile);
- if (config->lt_cacertfile)
- LDAP_FREE(config->lt_cacertfile);
- if (config->lt_cacertdir)
- LDAP_FREE(config->lt_cacertdir);
- if (config->lt_ciphersuite)
- LDAP_FREE(config->lt_ciphersuite);
- if (config->lt_crlfile)
- LDAP_FREE(config->lt_crlfile);
- if (config->lt_randfile)
- LDAP_FREE(config->lt_randfile);
+ if ( config->lt_certfile )
+ LDAP_FREE( config->lt_certfile );
+ if ( config->lt_keyfile )
+ LDAP_FREE( config->lt_keyfile );
+ if ( config->lt_dhfile )
+ LDAP_FREE( config->lt_dhfile );
+ if ( config->lt_cacertfile )
+ LDAP_FREE( config->lt_cacertfile );
+ if ( config->lt_cacertdir )
+ LDAP_FREE( config->lt_cacertdir );
+ if ( config->lt_ciphersuite )
+ LDAP_FREE( config->lt_ciphersuite );
+ if ( config->lt_crlfile )
+ LDAP_FREE( config->lt_crlfile );
+ if ( config->lt_randfile )
+ LDAP_FREE( config->lt_randfile );
- LDAP_FREE(config);
+ LDAP_FREE( config );
}
static tls_ctx *
LDAP_MUTEX_LOCK( &tlsm_init_mutex );
if ( c->tc_model )
PR_Close( c->tc_model );
- if (c->tc_certificate)
- CERT_DestroyCertificate(c->tc_certificate);
- if (c->tc_private_key)
- SECKEY_DestroyPrivateKey(c->tc_private_key);
+ if ( c->tc_certificate )
+ CERT_DestroyCertificate( c->tc_certificate );
+ if ( c->tc_private_key )
+ SECKEY_DestroyPrivateKey( c->tc_private_key );
c->tc_certdb = NULL; /* if not the default, may have to clean up */
if ( c->tc_certdb_slot ) {
if ( SECMOD_CloseUserDB( c->tc_certdb_slot ) ) {
errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
}
}
- PL_strfree( c->tc_pin_file );
- c->tc_pin_file = NULL;
+ if ( c->tc_pin_file ) {
+ PL_strfree( c->tc_pin_file );
+ c->tc_pin_file = NULL;
+ }
tlsm_free_pem_objs( c );
#ifdef HAVE_NSS_INITCONTEXT
if ( c->tc_initctx ) {
tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
{
tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
- ctx->tc_config = tlsm_copy_config(lt);
+ ctx->tc_config = tlsm_copy_config( lt );
ctx->tc_is_server = is_server;
return 0;
}
+/* returns true if the given string looks like
+ "tokenname" ":" "certnickname"
+ This is true if there is a ':' colon character
+ in the string and the colon is not the first
+ or the last character in the string
+*/
+static int
+tlsm_is_tokenname_certnick( const char *certfile )
+{
+ if ( certfile ) {
+ const char *ptr = PL_strchr( certfile, ':' );
+ return ptr && (ptr != certfile) && (*(ptr+1));
+ }
+ return 0;
+}
+
static int
tlsm_deferred_ctx_init( void *arg )
{
} else {
char *tmp_certname;
- if (ctx->tc_certdb_slot) {
- tmp_certname = PR_smprintf(TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile);
+ if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) {
+ /* assume already in form tokenname:certnickname */
+ tmp_certname = PL_strdup( lt->lt_certfile );
+ } else if ( ctx->tc_certdb_slot ) {
+ tmp_certname = PR_smprintf( TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile );
} else {
- tmp_certname = PR_smprintf("%s", lt->lt_certfile);
+ tmp_certname = PR_smprintf( "%s", lt->lt_certfile );
}
- ctx->tc_certificate = PK11_FindCertFromNickname(tmp_certname, SSL_RevealPinArg(ctx->tc_model));
- PR_smprintf_free(tmp_certname);
+ ctx->tc_certificate = PK11_FindCertFromNickname( tmp_certname, SSL_RevealPinArg( ctx->tc_model ) );
+ PR_smprintf_free( tmp_certname );
- if (!ctx->tc_certificate) {
+ if ( !ctx->tc_certificate ) {
PRErrorCode errcode = PR_GetError();
Debug( LDAP_DEBUG_ANY,
"TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n",
return rc;
}
} else {
- PL_strfree( ctx->tc_pin_file );
+ if ( ctx->tc_pin_file )
+ PL_strfree( ctx->tc_pin_file );
ctx->tc_pin_file = PL_strdup( lt->lt_keyfile );
}
}
return -1;
}
- if (tlsm_find_and_verify_cert_key(ctx)) {
+ if ( tlsm_find_and_verify_cert_key( ctx ) ) {
Debug( LDAP_DEBUG_ANY,
"TLS: error: unable to find and verify server's cert and key for certificate %s\n",
tlsm_ctx_subject_name(ctx), 0, 0 );
return rc ? 0 : keySize;
}
+static int
+tlsm_session_unique( tls_session *sess, struct berval *buf, int is_server)
+{
+ /* Need upstream support https://bugzilla.mozilla.org/show_bug.cgi?id=563276 */
+ return 0;
+}
+
+/*
+ * Yet again, we're pasting in glue that MozNSS ought to provide itself.
+ *
+ * SSL_LIBRARY_VERSION_TLS_1_* are equivalent to LDAP_OPT_X_TLS_PROTOCOL_TLS1_*
+ */
+static struct {
+ const char *name;
+ int num;
+} pvers[] = {
+ { "SSLv2", SSL_LIBRARY_VERSION_2 },
+ { "SSLv3", SSL_LIBRARY_VERSION_3_0 },
+ { "TLSv1", SSL_LIBRARY_VERSION_TLS_1_0 },
+ { "TLSv1.1", SSL_LIBRARY_VERSION_TLS_1_1 },
+ { "TLSv1.2", SSL_LIBRARY_VERSION_TLS_1_2 },
+ { "TLSv1.3", SSL_LIBRARY_VERSION_TLS_1_3 },
+ { NULL, 0 }
+};
+
+static const char *
+tlsm_session_version( tls_session *sess )
+{
+ tlsm_session *s = (tlsm_session *)sess;
+ SSLChannelInfo info;
+ int rc;
+ rc = SSL_GetChannelInfo( s, &info, sizeof( info ));
+ if ( rc == 0 ) {
+ int i;
+ for (i=0; pvers[i].name; i++)
+ if (pvers[i].num == info.protocolVersion)
+ return pvers[i].name;
+ }
+ return "unknown";
+}
+
+static const char *
+tlsm_session_cipher( tls_session *sess )
+{
+ tlsm_session *s = (tlsm_session *)sess;
+ SSLChannelInfo info;
+ int rc;
+ rc = SSL_GetChannelInfo( s, &info, sizeof( info ));
+ if ( rc == 0 ) {
+ SSLCipherSuiteInfo csinfo;
+ rc = SSL_GetCipherSuiteInfo( info.cipherSuite, &csinfo, sizeof( csinfo ));
+ if ( rc == 0 )
+ return csinfo.cipherSuiteName;
+ }
+ return "unknown";
+}
+
+static int
+tlsm_session_peercert( tls_session *sess, struct berval *der )
+{
+ tlsm_session *s = (tlsm_session *)sess;
+ CERTCertificate *cert;
+ cert = SSL_PeerCertificate( s );
+ if (!cert)
+ return -1;
+ der->bv_len = cert->derCert.len;
+ der->bv_val = LDAP_MALLOC( der->bv_len );
+ if (!der->bv_val)
+ return -1;
+ memcpy( der->bv_val, cert->derCert.data, der->bv_len );
+ return 0;
+}
+
/*
* TLS support for LBER Sockbufs
*/
tlsm_session_peer_dn,
tlsm_session_chkhost,
tlsm_session_strength,
+ tlsm_session_unique,
+ tlsm_session_version,
+ tlsm_session_cipher,
+ tlsm_session_peercert,
&tlsm_sbio,