* 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)
+ return NULL;
}
#endif /* RETRIEVE_PASSWORD_FROM_FILE */
#ifdef READ_PASSWORD_FROM_STDIN
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 && !result; le = le->next) {
+ PK11SlotInfo *slot = le->slot;
+ if (!PK11_IsLoggedIn(slot, NULL))
+ continue;
+
+ result = PK11_FindKeyByDERCert(slot, ctx->tc_certificate, pin_arg);
+ }
+
+ 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;
}
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;
}
-static int
-tlsm_authenticate_to_slot( tlsm_ctx *ctx, PK11SlotInfo *slot )
-{
- int rc = -1;
-
- if ( SECSuccess != PK11_Authenticate( slot, PR_FALSE, ctx ) ) {
- char *token_name = PK11_GetTokenName( slot );
- PRErrorCode errcode = PR_GetError();
- Debug( LDAP_DEBUG_ANY,
- "TLS: could not authenticate to the security token %s - error %d:%s.\n",
- token_name ? token_name : DEFAULT_TOKEN_NAME, errcode,
- PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
- } else {
- rc = 0; /* success */
- }
-
- return rc;
-}
-
static SECStatus
tlsm_nss_shutdown_cb( void *appData, void *nssData )
{
void *pin_arg = SSL_RevealPinArg(ctx->tc_model);
- ctx->tc_private_key = PK11_FindKeyByAnyCert(ctx->tc_certificate, pin_arg);
+ 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);
+
+ /* 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,
}
tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix );
- LDAP_MUTEX_LOCK( &tlsm_init_mutex );
/* initialize only moddb; certdb will be initialized explicitly */
#ifdef HAVE_NSS_INITCONTEXT
rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
#endif
- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
-
if ( rc != SECSuccess ) {
errcode = PORT_GetError();
if ( securitydirs[ii] != lt->lt_cacertdir) {
}
if ( errcode ) { /* no moznss db found, or not using moznss db */
- LDAP_MUTEX_LOCK( &tlsm_init_mutex );
#ifdef HAVE_NSS_INITCONTEXT
int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
#ifdef INITCONTEXT_HACK
#else
rc = NSS_NoDB_Init( NULL );
#endif
- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
if ( rc != SECSuccess ) {
errcode = PORT_GetError();
Debug( LDAP_DEBUG_ANY,
if ( errcode || lt->lt_cacertfile ) {
/* initialize the PEM module */
- LDAP_MUTEX_LOCK( &tlsm_init_mutex );
if ( tlsm_init_pem_module() ) {
- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
int pem_errcode = PORT_GetError();
Debug( LDAP_DEBUG_ANY,
"TLS: could not initialize moznss PEM module - error %d:%s.\n",
} else if ( !errcode ) {
tlsm_init_ca_certs( ctx, lt->lt_cacertfile, NULL );
}
- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
}
if ( errcode ) {
}
if ( ctx->tc_is_server ) {
- LDAP_MUTEX_LOCK( &tlsm_init_mutex );
/* 0 means use the defaults here */
SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL );
- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
}
#ifndef HAVE_NSS_INITCONTEXT
SECCertificateUsage certUsage;
PRBool checkSig;
SECStatus status;
- int errorToIgnore;
void *pin_arg;
if (tlsm_ctx_load_private_key(ctx))
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;
}
LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
if ( refcount )
return;
+
+ LDAP_MUTEX_LOCK( &tlsm_init_mutex );
if ( c->tc_model )
PR_Close( c->tc_model );
if (c->tc_certificate)
tlsm_free_pem_objs( c );
#ifdef HAVE_NSS_INITCONTEXT
if ( c->tc_initctx ) {
- LDAP_MUTEX_LOCK( &tlsm_init_mutex );
if ( NSS_ShutdownContext( c->tc_initctx ) ) {
PRErrorCode errcode = PR_GetError();
Debug( LDAP_DEBUG_ANY,
"TLS: could not shutdown NSS - error %d:%s.\n",
errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
}
- LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
}
c->tc_initctx = NULL;
#endif /* HAVE_NSS_INITCONTEXT */
+ LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
#endif
return -1;
}
+ if ( SSL_SetPKCS11PinArg(ctx->tc_model, ctx) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: could not set pin prompt argument\n", 0, 0, 0);
+ return -1;
+ }
+
if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
Debug( LDAP_DEBUG_ANY,
"TLS: could not set secure mode on.\n",
since a cert has been specified, assume the client wants to do cert auth
*/
if ( ctx->tc_certificate ) {
- if ( tlsm_authenticate_to_slot( ctx, ctx->tc_certificate->slot ) ) {
- Debug( LDAP_DEBUG_ANY,
- "TLS: error: unable to authenticate to the security device for certificate '%s'\n",
- tlsm_ctx_subject_name(ctx), 0, 0 );
- return -1;
- }
if ( tlsm_clientauth_init( ctx ) ) {
Debug( LDAP_DEBUG_ANY,
"TLS: error: unable to set up client certificate authentication using '%s'\n",
return -1;
}
- /* authenticate to the server's token - this will do nothing
- if the key/cert db is not password protected */
- if ( tlsm_authenticate_to_slot( ctx, ctx->tc_certificate->slot ) ) {
- Debug( LDAP_DEBUG_ANY,
- "TLS: error: unable to authenticate to the security device for certificate '%s'\n",
- tlsm_ctx_subject_name(ctx), 0, 0 );
- return -1;
- }
-
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",
int rc;
c->tc_is_server = is_server;
+ LDAP_MUTEX_LOCK( &tlsm_init_mutex );
status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
+ LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
if ( PR_SUCCESS != status ) {
PRErrorCode err = PR_GetError();
Debug( LDAP_DEBUG_ANY,