Index: modules/ssl/mod_ssl.c =================================================================== --- modules/ssl/mod_ssl.c (revision 1616579) +++ modules/ssl/mod_ssl.c (working copy) @@ -227,6 +227,12 @@ "URL of the default OCSP Responder") SSL_CMD_SRV(OCSPOverrideResponder, FLAG, "Force use of the default responder URL ('on', 'off')") + +/* Define OCSP Responder File Configuration Directive */ + SSL_CMD_SRV(OCSPResponderCertificateFile, TAKE1, + "Trusted OCSP responder certificates" + "(`/path/to/file' - PEM encoded certificates)") + SSL_CMD_SRV(OCSPResponseTimeSkew, TAKE1, "Maximum time difference in OCSP responses") SSL_CMD_SRV(OCSPResponseMaxAge, TAKE1, Index: modules/ssl/ssl_engine_config.c =================================================================== --- modules/ssl/ssl_engine_config.c (revision 1616579) +++ modules/ssl/ssl_engine_config.c (working copy) @@ -130,6 +130,13 @@ mctx->ocsp_enabled = FALSE; mctx->ocsp_force_default = FALSE; mctx->ocsp_responder = NULL; + +/* Set OCSP Responder File variables */ + mctx->ocsp_verify_flags = 0; + mctx->ocsp_certs_file = NULL; + mctx->ocsp_certs = NULL; + + mctx->ocsp_resptime_skew = UNSET; mctx->ocsp_resp_maxage = UNSET; mctx->ocsp_responder_timeout = UNSET; @@ -273,6 +280,10 @@ cfgMergeBool(ocsp_enabled); cfgMergeBool(ocsp_force_default); cfgMerge(ocsp_responder, NULL); + +/* Set OCSP Responder File directive for importing */ + cfgMerge(ocsp_certs_file, NULL); + cfgMergeInt(ocsp_resptime_skew); cfgMergeInt(ocsp_resp_maxage); cfgMergeInt(ocsp_responder_timeout); @@ -1882,6 +1893,24 @@ #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 1616579) +++ modules/ssl/ssl_engine_init.c (working copy) @@ -1470,6 +1470,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) { @@ -1758,6 +1764,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 1616579) +++ modules/ssl/ssl_engine_ocsp.c (working copy) @@ -184,9 +184,13 @@ 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"); + +/* 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 1616579) +++ modules/ssl/ssl_private.h (working copy) @@ -606,6 +606,12 @@ BOOL ocsp_force_default; /* true if the default responder URL is * used regardless of per-cert URL */ const char *ocsp_responder; /* default responder URL */ + +/* 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 */ + long ocsp_resptime_skew; long ocsp_resp_maxage; apr_interval_time_t ocsp_responder_timeout; @@ -735,6 +741,9 @@ const char *ssl_cmd_SSLOCSPUseRequestNonce(cmd_parms *cmd, void *dcfg, int flag); const char *ssl_cmd_SSLOCSPEnable(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 @@ -931,6 +940,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 1616579) +++ modules/ssl/ssl_util_ocsp.c (working copy) @@ -316,4 +316,82 @@ 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; + int n; + STACK_OF(X509) *other_certs = NULL; + + if ((bio = BIO_new(BIO_s_file_internal())) == 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 */