]> granicus.if.org Git - apache/commitdiff
Add Configuration for trusted OCSP responder certificates
authorJean-Frederic Clere <jfclere@apache.org>
Fri, 3 Feb 2017 16:19:17 +0000 (16:19 +0000)
committerJean-Frederic Clere <jfclere@apache.org>
Fri, 3 Feb 2017 16:19:17 +0000 (16:19 +0000)
Fix for PR 46037

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1781575 13f79535-47bb-0310-9956-ffa450edef68

build/PrintPath [deleted file]
modules/ssl/mod_ssl.c
modules/ssl/ssl_engine_config.c
modules/ssl/ssl_engine_init.c
modules/ssl/ssl_engine_ocsp.c
modules/ssl/ssl_private.h
modules/ssl/ssl_util_ocsp.c

diff --git a/build/PrintPath b/build/PrintPath
deleted file mode 100755 (executable)
index 2a2b48b..0000000
+++ /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 <<ENDTEST
-#!/bin/sh
-if [ -x / ] || [ -x /bin ] || [ -x /bin/ls ]; then
-    exit 0
-fi
-exit 1
-ENDTEST
-
-    if `/bin/sh $testfile 2>/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
-
index ad2b7880a45ed9f29fc479819bd0b4b975c2083a..99f0c13391a82764b2dc93b8287138311c2534d6 100644 (file)
@@ -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
index f1be77aefeb2b7d68b13dc6b264b34ff902c3fbf..730a6b38fbfbb8263f0f3e28812300faf9862c20 100644 (file)
@@ -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;
index fe37d84bc5a5ba25e33e2f1124c15faa1f0822e2..7b7a52c72e72d585f62ba088c6a063e1669fc95d 100644 (file)
@@ -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
index 0a8315f45c6bd0dde7f08c9105b46df3ab8cae9c..5617b9cf6601c4f6d3e4c2bc0628bcf9065d1f9b 100644 (file)
@@ -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;
+            }
         }
     }
 
index 26a54bb6f77319b8998fb371ea2ce97d19ed9886..a3a1ee1eb28ebf72378db6c5fcadfd5a0dee3af4 100644 (file)
@@ -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
index a00c273d89f9f491ad48597b69519a2081c771f0..2a3e47b5f9444451e28276ea5f6e6304ad6cf1c3 100644 (file)
@@ -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 */