From: Jean-Frederic Clere Date: Fri, 3 Feb 2017 16:19:17 +0000 (+0000) Subject: Add Configuration for trusted OCSP responder certificates X-Git-Tag: 2.5.0-alpha~704 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f6146b725c3d0e7bf6ef487e23231c1e3cfe0658;p=apache Add Configuration for trusted OCSP responder certificates Fix for PR 46037 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1781575 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/build/PrintPath b/build/PrintPath deleted file mode 100755 index 2a2b48b634..0000000000 --- a/build/PrintPath +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# -# Look for program[s] somewhere in $PATH. -# -# Options: -# -s -# Do not print out full pathname. (silent) -# -pPATHNAME -# Look in PATHNAME instead of $PATH -# -# Usage: -# PrintPath [-s] [-pPATHNAME] program [program ...] -# -# Initially written by Jim Jagielski for the Apache configuration mechanism -# (with kudos to Kernighan/Pike) - -## -# Some "constants" -## -pathname=$PATH -echo="yes" - -## -# Find out what OS we are running for later on -## -os=`(uname) 2>/dev/null` - -## -# Parse command line -## -for args in $* -do - case $args in - -s ) echo="no" ;; - -p* ) pathname="`echo $args | sed 's/^..//'`" ;; - * ) programs="$programs $args" ;; - esac -done - -## -# Now we make the adjustments required for OS/2 and everyone -# else :) -# -# First of all, all OS/2 programs have the '.exe' extension. -# Next, we adjust PATH (or what was given to us as PATH) to -# be whitespace separated directories. -# Finally, we try to determine the best flag to use for -# test/[] to look for an executable file. OS/2 just has '-r' -# but with other OSs, we do some funny stuff to check to see -# if test/[] knows about -x, which is the prefered flag. -## - -if [ "x$os" = "xOS/2" ] -then - ext=".exe" - pathname=`echo -E $pathname | - sed 's/^;/.;/ - s/;;/;.;/g - s/;$/;./ - s/;/ /g - s/\\\\/\\//g' ` - test_exec_flag="-r" -else - ext="" # No default extensions - pathname=`echo $pathname | - sed 's/^:/.:/ - s/::/:.:/g - s/:$/:./ - s/:/ /g' ` - # Here is how we test to see if test/[] can handle -x - testfile="pp.t.$$" - - cat > $testfile </dev/null`; then - test_exec_flag="-x" - else - test_exec_flag="-r" - fi - rm -f $testfile -fi - -for program in $programs -do - for path in $pathname - do - if [ $test_exec_flag $path/${program}${ext} ] && \ - [ ! -d $path/${program}${ext} ]; then - if [ "x$echo" = "xyes" ]; then - echo $path/${program}${ext} - fi - exit 0 - fi - -# Next try without extension (if one was used above) - if [ "x$ext" != "x" ]; then - if [ $test_exec_flag $path/${program} ] && \ - [ ! -d $path/${program} ]; then - if [ "x$echo" = "xyes" ]; then - echo $path/${program} - fi - exit 0 - fi - fi - done -done -exit 1 - diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index ad2b7880a4..99f0c13391 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -264,6 +264,14 @@ static const command_rec ssl_config_cmds[] = { 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 diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index f1be77aefe..730a6b38fb 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -146,6 +146,13 @@ static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p) 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; @@ -282,6 +289,12 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p, 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); @@ -1707,6 +1720,16 @@ const char *ssl_cmd_SSLOCSPProxyURL(cmd_parms *cmd, void *dcfg, 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) { SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; @@ -1958,6 +1981,21 @@ const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, #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; diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index fe37d84bc5..7b7a52c72e 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -1762,6 +1762,12 @@ apr_status_t ssl_init_ConfigureServer(server_rec *s, != APR_SUCCESS) { return rv; } + + /* Initialize OCSP Responder certificate if OCSP enabled */ + #ifndef OPENSSL_NO_OCSP + ssl_init_ocsp_certificates(s, sc->server); + #endif + } sdc->proxy->sc = sc; @@ -2061,6 +2067,12 @@ apr_status_t ssl_init_ModuleKill(void *data) sc = mySrvConfig(s); 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 + } #if OPENSSL_VERSION_NUMBER >= 0x10100000L diff --git a/modules/ssl/ssl_engine_ocsp.c b/modules/ssl/ssl_engine_ocsp.c index 0a8315f45c..5617b9cf66 100644 --- a/modules/ssl/ssl_engine_ocsp.c +++ b/modules/ssl/ssl_engine_ocsp.c @@ -183,12 +183,16 @@ static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c, } if (rc == V_OCSP_CERTSTATUS_GOOD) { - /* TODO: allow flags configuration. */ - if (OCSP_basic_verify(basicResponse, NULL, X509_STORE_CTX_get0_store(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, X509_STORE_CTX_get0_store(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; + } } } diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 26a54bb6f7..a3a1ee1eb2 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -678,6 +678,12 @@ typedef struct { 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 */ @@ -808,6 +814,11 @@ const char *ssl_cmd_SSLOCSPUseRequestNonce(cmd_parms *cmd, void *dcfg, int flag) 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 @@ -1022,6 +1033,10 @@ OCSP_RESPONSE *modssl_dispatch_ocsp_request(const apr_uri_t *uri, 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 diff --git a/modules/ssl/ssl_util_ocsp.c b/modules/ssl/ssl_util_ocsp.c index a00c273d89..2a3e47b5f9 100644 --- a/modules/ssl/ssl_util_ocsp.c +++ b/modules/ssl/ssl_util_ocsp.c @@ -339,4 +339,82 @@ OCSP_RESPONSE *modssl_dispatch_ocsp_request(const apr_uri_t *uri, 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 */