Index: docs/manual/mod/mod_ssl.xml =================================================================== --- docs/manual/mod/mod_ssl.xml (revision 1782013) +++ docs/manual/mod/mod_ssl.xml (working copy) @@ -2415,6 +2415,37 @@ +SSLOCSPNoverify +skip the OCSP responder certificates verification +SSLOCSPNoverify On/Off +SSLOCSPNoverify Off +server config +virtual host +Available in httpd 2.5 and later, if using OpenSSL 0.9.7 or later + +

Skip the OCSP responder certificates verification, mostly useful when +testing an OCSP server.

+
+
+ + + +SSLOCSPResponderCertificateFile +Set of trusted PEM encoded OCSP responder certificates +SSLOCSPResponderCertificateFile file +server config +virtual host +Available in httpd 2.5 and later, if using OpenSSL 0.9.7 or later + +

This supplies a list of trusted OCSP responder certificates to be used +during OCSP responder certificate validation. The supplied certificates are +implicitly trusted without any further validation. This is typically used +where the OCSP responder certificate is self signed or omitted from the OCSP +response.

+
+
+ + SSLOCSPProxyURL Proxy URL to use for OCSP requests SSLOCSPProxyURL url Index: modules/ssl/mod_ssl.c =================================================================== --- modules/ssl/mod_ssl.c (revision 1782013) +++ modules/ssl/mod_ssl.c (working copy) @@ -251,6 +251,14 @@ SSL_CMD_SRV(OCSPProxyURL, TAKE1, "Proxy URL to use for OCSP requests") +/* Define OCSP Responder Certificate Verification Directive */ + SSL_CMD_SRV(OCSPNoverify, FLAG, + "Do not verify OCSP Responder certificate ('on', 'off')") +/* Define OCSP Responder File Configuration Directive */ + SSL_CMD_SRV(OCSPResponderCertificateFile, TAKE1, + "Trusted OCSP responder certificates" + "(`/path/to/file' - PEM encoded certificates)") + #ifdef HAVE_OCSP_STAPLING /* * OCSP Stapling options Index: modules/ssl/ssl_engine_config.c =================================================================== --- modules/ssl/ssl_engine_config.c (revision 1782013) +++ modules/ssl/ssl_engine_config.c (working copy) @@ -138,6 +138,13 @@ mctx->ocsp_use_request_nonce = UNSET; mctx->proxy_uri = NULL; +/* Set OCSP Responder Certificate Verification variable */ + mctx->ocsp_noverify = FALSE; +/* Set OCSP Responder File variables */ + mctx->ocsp_verify_flags = 0; + mctx->ocsp_certs_file = NULL; + mctx->ocsp_certs = NULL; + #ifdef HAVE_OCSP_STAPLING mctx->stapling_enabled = UNSET; mctx->stapling_resptime_skew = UNSET; @@ -287,6 +294,12 @@ cfgMergeInt(ocsp_responder_timeout); cfgMergeBool(ocsp_use_request_nonce); cfgMerge(proxy_uri, NULL); + +/* Set OCSP Responder Certificate Verification directive */ + cfgMergeBool(ocsp_noverify); +/* Set OCSP Responder File directive for importing */ + cfgMerge(ocsp_certs_file, NULL); + #ifdef HAVE_OCSP_STAPLING cfgMergeBool(stapling_enabled); cfgMergeInt(stapling_resptime_skew); @@ -1699,6 +1712,16 @@ return NULL; } +/* Set OCSP responder certificate verification directive */ +const char *ssl_cmd_SSLOCSPNoverify(cmd_parms *cmd, void *dcfg, int flag) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->server->ocsp_noverify = flag ? TRUE : FALSE; + + return NULL; +} + const char *ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms *cmd, void *dcfg, int flag) { SSLSrvConfigRec *sc = mySrvConfig(cmd->server); @@ -1950,6 +1973,21 @@ #endif /* HAVE_SRP */ +/* OCSP Responder File Function to read in value */ +const char *ssl_cmd_SSLOCSPResponderCertificateFile(cmd_parms *cmd, void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + const char *err; + + if ((err = ssl_cmd_check_file(cmd, &arg))) { + return err; + } + + sc->server->ocsp_certs_file = arg; + return NULL; +} + void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s) { apr_file_t *out = NULL; Index: modules/ssl/ssl_engine_init.c =================================================================== --- modules/ssl/ssl_engine_init.c (revision 1782013) +++ modules/ssl/ssl_engine_init.c (working copy) @@ -1627,6 +1627,12 @@ != APR_SUCCESS) { return rv; } + + /* Initialize OCSP Responder certificate if OCSP enabled */ + #ifndef OPENSSL_NO_OCSP + ssl_init_ocsp_certificates(s, sc->server); + #endif + } if (sc->proxy_enabled) { @@ -1915,6 +1921,12 @@ ssl_init_ctx_cleanup_proxy(sc->proxy); ssl_init_ctx_cleanup(sc->server); + + /* Not Sure but possibly clear X509 trusted cert file */ + #ifndef OPENSSL_NO_OCSP + sk_X509_pop_free(sc->server->ocsp_certs, X509_free); + #endif + } free_dh_params(); Index: modules/ssl/ssl_engine_ocsp.c =================================================================== --- modules/ssl/ssl_engine_ocsp.c (revision 1782013) +++ modules/ssl/ssl_engine_ocsp.c (working copy) @@ -183,12 +183,16 @@ } if (rc == V_OCSP_CERTSTATUS_GOOD) { - /* TODO: allow flags configuration. */ - if (OCSP_basic_verify(basicResponse, NULL, ctx->ctx, 0) != 1) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01925) - "failed to verify the OCSP response"); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); - rc = V_OCSP_CERTSTATUS_UNKNOWN; + /* Check if OCSP certificate verification required */ + if (!sc->server->ocsp_noverify) { + /* Modify OCSP response verification to include OCSP Responder cert */ + if (OCSP_basic_verify(basicResponse, sc->server->ocsp_certs, ctx->ctx, + sc->server->ocsp_verify_flags) != 1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01925) + "failed to verify the OCSP response"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + rc = V_OCSP_CERTSTATUS_UNKNOWN; + } } } Index: modules/ssl/ssl_private.h =================================================================== --- modules/ssl/ssl_private.h (revision 1782013) +++ modules/ssl/ssl_private.h (working copy) @@ -642,6 +642,12 @@ BOOL ocsp_use_request_nonce; apr_uri_t *proxy_uri; + BOOL ocsp_noverify; /* true if skipping OCSP certification verification like openssl -noverify */ + /* Declare variables for using OCSP Responder Certs for OCSP verification */ + int ocsp_verify_flags; /* Flags to use when verifying OCSP response */ + const char *ocsp_certs_file; /* OCSP other certificates filename */ + STACK_OF(X509) *ocsp_certs; /* OCSP other certificates */ + #ifdef HAVE_SSL_CONF_CMD SSL_CONF_CTX *ssl_ctx_config; /* Configuration context */ apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */ @@ -769,6 +775,11 @@ const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag); const char *ssl_cmd_SSLOCSPProxyURL(cmd_parms *cmd, void *dcfg, const char *arg); +/* Declare OCSP Responder Certificate Verification Directive */ +const char *ssl_cmd_SSLOCSPNoverify(cmd_parms *cmd, void *dcfg, int flag); +/* Declare OCSP Responder Certificate File Directive */ +const char *ssl_cmd_SSLOCSPResponderCertificateFile(cmd_parms *cmd, void *dcfg, const char *arg); + #ifdef HAVE_SSL_CONF_CMD const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2); #endif @@ -979,6 +990,10 @@ apr_interval_time_t timeout, OCSP_REQUEST *request, conn_rec *c, apr_pool_t *p); + +/* Initialize OCSP trusted certificate list */ +void ssl_init_ocsp_certificates(server_rec *s, modssl_ctx_t *mctx); + #endif /* Retrieve DH parameters for given key length. Return value should Index: modules/ssl/ssl_util_ocsp.c =================================================================== --- modules/ssl/ssl_util_ocsp.c (revision 1782013) +++ modules/ssl/ssl_util_ocsp.c (working copy) @@ -339,4 +339,81 @@ return response; } +/* _________________________________________________________________ +** +** OCSP other certificate support +** _________________________________________________________________ +*/ + +/* + * Read a file that contains certificates in PEM format and + * return as a STACK. + */ + +static STACK_OF(X509) *modssl_read_ocsp_certificates(const char *file) +{ + BIO *bio; + X509 *x509; + unsigned long err; + STACK_OF(X509) *other_certs = NULL; + + if ((bio = BIO_new(BIO_s_file())) == NULL) + return NULL; + if (BIO_read_filename(bio, file) <= 0) { + BIO_free(bio); + return NULL; + } + /* create new extra chain by loading the certs */ + while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { + if (!other_certs) { + other_certs = sk_X509_new_null(); + if (!other_certs) + return NULL; + } + + if (!sk_X509_push(other_certs, x509)) { + X509_free(x509); + sk_X509_pop_free(other_certs, X509_free); + BIO_free(bio); + return NULL; + } + } + /* Make sure that only the error is just an EOF */ + if ((err = ERR_peek_error()) > 0) { + if (!( ERR_GET_LIB(err) == ERR_LIB_PEM + && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { + BIO_free(bio); + sk_X509_pop_free(other_certs, X509_free); + return NULL; + } + while (ERR_get_error() > 0) ; + } + BIO_free(bio); + return other_certs; +} + +void ssl_init_ocsp_certificates(server_rec *s, modssl_ctx_t *mctx) +{ + /* + * Configure Trusted OCSP certificates. + */ + + if (!mctx->ocsp_certs_file) { + return; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "Configuring Trusted OCSP certificates"); + + mctx->ocsp_certs = modssl_read_ocsp_certificates(mctx->ocsp_certs_file); + + if (!mctx->ocsp_certs) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unable to configure OCSP Trusted Certificates"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + ssl_die(s); + } + mctx->ocsp_verify_flags |= OCSP_TRUSTOTHER; +} + #endif /* HAVE_OCSP */