#endif
PK11GenericObject **tc_pem_objs; /* array of objects to free */
int tc_n_pem_objs; /* number of objects */
+ PRBool tc_warn_only; /* only warn of errors in validation */
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_t tc_refmutex;
#endif
CERTVerifyLog verifylog;
SECStatus ret = SECSuccess;
const char *name;
+ int debug_level = LDAP_DEBUG_ANY;
+
+ if ( errorToIgnore == -1 ) {
+ debug_level = LDAP_DEBUG_TRACE;
+ }
/* the log captures information about every cert in the chain, so we can tell
which cert caused the problem and what the problem was */
/* it is possible for CERT_VerifyCertificate return with an error with no logging */
if ( ret != SECSuccess ) {
PRErrorCode errcode = PR_GetError();
- Debug( LDAP_DEBUG_ANY,
+ Debug( debug_level,
"TLS: certificate [%s] is not valid - error %d:%s.\n",
name ? name : "(unknown)",
errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
"please fix your certs if possible\n", name, 0, 0 );
} else { /* does not have basicconstraint, or some other error */
ret = SECFailure;
- Debug( LDAP_DEBUG_ANY,
+ Debug( debug_level,
"TLS: certificate [%s] is not valid - CA cert is not valid\n",
name, 0, 0 );
}
} else if ( errorToIgnore && ( node->error == errorToIgnore ) ) {
- Debug( LDAP_DEBUG_ANY,
+ 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 ) );
} else {
ret = SECFailure;
- Debug( LDAP_DEBUG_ANY,
+ Debug( debug_level,
"TLS: certificate [%s] is not valid - 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( (CERTCertDBHandle *)arg, peercert,
+ ret = tlsm_verify_cert( ctx->tc_certdb, peercert,
SSL_RevealPinArg( fd ),
- checksig, certUsage, 0 );
+ checksig, certUsage, errorToIgnore );
CERT_DestroyCertificate( peercert );
return ret;
SECCertificateUsage certUsage;
PRBool checkSig = PR_TRUE;
SECStatus status;
+ /* may not have a CA cert - ok - ignore SEC_ERROR_UNKNOWN_ISSUER */
+ int errorToIgnore = SEC_ERROR_UNKNOWN_ISSUER;
if ( pRetKey ) {
*pRetKey = key; /* caller will deal with this */
} else {
checkSig = PR_FALSE;
}
- /* may not have a CA cert - ok - ignore SEC_ERROR_UNKNOWN_ISSUER */
+ if ( ctx->tc_warn_only ) {
+ errorToIgnore = -1;
+ }
status = tlsm_verify_cert( ctx->tc_certdb, cert, pin_arg,
- checkSig, certUsage, SEC_ERROR_UNKNOWN_ISSUER );
+ checkSig, certUsage, errorToIgnore );
if ( status == SECSuccess ) {
rc = 0;
}
{
tlsm_ctx *ctx = (tlsm_ctx *)arg;
int rc;
+ PRBool saveval;
/* don't need caNames - this function will call CERT_VerifyCertificateNow
which will verify the cert against the known CAs */
+ saveval = ctx->tc_warn_only;
+ ctx->tc_warn_only = PR_TRUE;
rc = tlsm_find_and_verify_cert_key( ctx, fd, ctx->tc_certname, 0, pRetCert, pRetKey );
+ ctx->tc_warn_only = saveval;
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"TLS: error: unable to perform client certificate authentication for "
{
SECStatus status = SECFailure;
int rc;
+ PRBool saveval;
+ saveval = ctx->tc_warn_only;
+ ctx->tc_warn_only = PR_TRUE;
rc = tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, 0, NULL, NULL );
+ ctx->tc_warn_only = saveval;
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"TLS: error: unable to set up client certificate authentication for "
#endif /* HAVE_NSS_INITCONTEXT */
ctx->tc_pem_objs = NULL;
ctx->tc_n_pem_objs = 0;
+ ctx->tc_warn_only = PR_FALSE;
}
return (tls_ctx *)ctx;
}
return -1;
}
- if ( ctx->tc_require_cert ) {
+ if ( !ctx->tc_require_cert ) {
+ ctx->tc_verify_cert = PR_FALSE;
+ } else if ( !ctx->tc_is_server ) {
request_cert = PR_TRUE;
require_cert = SSL_REQUIRE_NO_ERROR;
if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
}
if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
ctx->tc_verify_cert = PR_TRUE;
- } else {
- ctx->tc_verify_cert = PR_FALSE;
+ } else { /* server */
+ /* server does not request certs by default */
+ /* if allow - client may send cert, server will ignore if errors */
+ /* if try - client may send cert, server will error if bad cert */
+ /* if hard or demand - client must send cert, server will error if bad cert */
+ request_cert = PR_TRUE;
+ require_cert = SSL_REQUIRE_NO_ERROR;
+ if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
+ ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
+ require_cert = SSL_REQUIRE_ALWAYS;
+ }
+ if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) {
+ ctx->tc_verify_cert = PR_TRUE;
+ } else {
+ ctx->tc_warn_only = PR_TRUE;
+ }
}
if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
/* Callback for authenticating certificate */
if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
- ctx->tc_certdb ) != SECSuccess ) {
+ ctx ) != SECSuccess ) {
PRErrorCode err = PR_GetError();
Debug( LDAP_DEBUG_ANY,
"TLS: error: could not set auth cert handler for moznss - error %d:%s\n",