Commit bc1ecd89 authored by Doug MacEachern's avatar Doug MacEachern
Browse files

per-dir SSLCACertificate{File,Path} cannot use SSL_CTX_set_cert_store

as the 1.x based module does, since the function is not thread-safe.
a patch has been submitted to OpenSSL to support SSL_set_cert_store
which is thread safe.  this feature is enabled by default in the
current 1.x based module, we only enable it if the SSL_set_cert_store
function is available.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk/modules/ssl@94179 13f79535-47bb-0310-9956-ffa450edef68
parent b6898259
Loading
Loading
Loading
Loading
+0 −9
Changes for mod_ssl.c: 0 added lines, 9 removed lines.
Original line number Diff line number Diff line
@@ -120,21 +120,12 @@ static const command_rec ssl_config_cmds[] = {
    SSL_CMD_SRV(CertificateChainFile, TAKE1,
                "SSL Server CA Certificate Chain file "
                "(`/path/to/file' - PEM encoded)")
#ifdef SSL_EXPERIMENTAL_PERDIRCA
    SSL_CMD_ALL(CACertificatePath, TAKE1,
                "SSL CA Certificate path "
                "(`/path/to/dir' - contains PEM encoded files)")
    SSL_CMD_ALL(CACertificateFile, TAKE1,
                "SSL CA Certificate file "
                "(`/path/to/file' - PEM encoded)")
#else
    SSL_CMD_SRV(CACertificatePath, TAKE1,
                "SSL CA Certificate path "
                "(`/path/to/dir' - contains PEM encoded files)")
    SSL_CMD_SRV(CACertificateFile, TAKE1,
                "SSL CA Certificate file "
                "(`/path/to/file' - PEM encoded)")
#endif
    SSL_CMD_SRV(CARevocationPath, TAKE1,
                "SSL CA Certificate Revocation List (CRL) path "
                "(`/path/to/dir' - contains PEM encoded files)")
+5 −5
Changes for mod_ssl.h: 5 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -70,9 +70,6 @@
 * CFLAGS="-DSSL_EXPERIMENTAL_xxxx_IGNORE".
 */
#ifdef SSL_EXPERIMENTAL
#ifndef SSL_EXPERIMENTAL_PERDIRCA_IGNORE
#define SSL_EXPERIMENTAL_PERDIRCA
#endif
#ifndef SSL_EXPERIMENTAL_PROXY_IGNORE
#define SSL_EXPERIMENTAL_PROXY
#endif
@@ -83,6 +80,11 @@
#endif
#endif /* SSL_EXPERIMENTAL */

/* XXX: add configure check */
#ifndef MODSSL_HAVE_SSL_SET_CERT_STORE
#define MODSSL_HAVE_SSL_SET_CERT_STORE 0
#endif 

/*
 * Power up our brain...
 */
@@ -567,10 +569,8 @@ typedef struct {
    const char   *szCipherSuite;
    ssl_verify_t  nVerifyClient;
    int           nVerifyDepth;
#ifdef SSL_EXPERIMENTAL_PERDIRCA
    const char   *szCACertificatePath;
    const char   *szCACertificateFile;
#endif
} SSLDirConfigRec;

/*
+14 −28
Changes for ssl_engine_config.c: 14 added lines, 28 removed lines.
Original line number Diff line number Diff line
@@ -252,10 +252,8 @@ void *ssl_config_perdir_create(apr_pool_t *p, char *dir)
    dc->nVerifyClient          = SSL_CVERIFY_UNSET;
    dc->nVerifyDepth           = UNSET;

#ifdef SSL_EXPERIMENTAL_PERDIRCA
    dc->szCACertificatePath    = NULL;
    dc->szCACertificateFile    = NULL;
#endif

    return dc;
}
@@ -290,10 +288,8 @@ void *ssl_config_perdir_merge(apr_pool_t *p, void *basev, void *addv)
    cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET);
    cfgMergeInt(nVerifyDepth);

#ifdef SSL_EXPERIMENTAL_PERDIRCA
    cfgMergeString(szCACertificatePath);
    cfgMergeString(szCACertificateFile);
#endif

    return new;
}
@@ -662,12 +658,22 @@ const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd, void *ctx,
    return NULL;
}

#define NO_PER_DIR_SSL_CA \
    "Your ssl library does not have support for per-directory CA"

#define MODSSL_SET_CA(f) \
    if (cmd->path) \
        if (MODSSL_HAVE_SSL_SET_CERT_STORE) \
            dc->f = arg; \
        else \
            return NO_PER_DIR_SSL_CA; \
    else \
        sc->f = arg \

const char *ssl_cmd_SSLCACertificatePath(cmd_parms *cmd, void *ctx,
                                         const char *arg)
{
#ifdef SSL_EXPERIMENTAL_PERDIRCA
    SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
#endif
    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
    const char *err;

@@ -675,16 +681,7 @@ const char *ssl_cmd_SSLCACertificatePath(cmd_parms *cmd, void *ctx,
        return err;
    }

#ifdef SSL_EXPERIMENTAL_PERDIRCA
    if (cmd->path) {
        dc->szCACertificatePath = arg;
    }
    else {
        sc->szCACertificatePath = arg;
    }
#else
    sc->szCACertificatePath = arg;
#endif
    MODSSL_SET_CA(szCACertificatePath);

    return NULL;
}
@@ -692,9 +689,7 @@ const char *ssl_cmd_SSLCACertificatePath(cmd_parms *cmd, void *ctx,
const char *ssl_cmd_SSLCACertificateFile(cmd_parms *cmd, void *ctx,
                                         const char *arg)
{
#ifdef SSL_EXPERIMENTAL_PERDIRCA
    SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
#endif
    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
    const char *err;

@@ -702,16 +697,7 @@ const char *ssl_cmd_SSLCACertificateFile(cmd_parms *cmd, void *ctx,
        return err;
    }

#ifdef SSL_EXPERIMENTAL_PERDIRCA
    if (cmd->path) {
        dc->szCACertificateFile = arg;
    }
    else {
        sc->szCACertificateFile = arg;
    }
#else
    sc->szCACertificateFile = arg;
#endif
    MODSSL_SET_CA(szCACertificateFile);

    return NULL;
}
+29 −54
Changes for ssl_engine_kernel.c: 29 added lines, 54 removed lines.
Original line number Diff line number Diff line
@@ -322,14 +322,8 @@ int ssl_hook_Access(request_rec *r)
    char *cp;
    int ok, i;
    BOOL renegotiate = FALSE, renegotiate_quick = FALSE;
#ifdef SSL_EXPERIMENTAL_PERDIRCA
    BOOL reconfigured_locations = FALSE;
    STACK_OF(X509_NAME) *ca_list;
    char *ca_path, *ca_file;
#endif
    X509 *cert;
    STACK_OF(X509) *cert_stack;
    X509_STORE *cert_store;
    X509_STORE *cert_store = NULL;
    X509_STORE_CTX cert_store_ctx;
    STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL;
    SSL_CIPHER *cipher = NULL;
@@ -579,16 +573,12 @@ int ssl_hook_Access(request_rec *r)

    /*
     * override SSLCACertificateFile & SSLCACertificatePath
     *  This is tagged experimental because it has to use an ugly kludge: We
     *  have to change the locations inside the SSL_CTX* (per-server global)
     *  instead inside SSL* (per-connection local) and reconfigure it to the
     *  old values later. That's problematic at least for the threaded process
     *  model of Apache under Win32 or when an error occurs. But unless
     *  OpenSSL provides a SSL_load_verify_locations() function we've no other
     *  chance to provide this functionality...
     * This is only enabled if the SSL_set_cert_store() function
     * is available in the ssl library.  the 1.x based mod_ssl
     * used SSL_CTX_set_cert_store which is not thread safe.
     */

#ifdef SSL_EXPERIMENTAL_PERDIRCA
#if MODSSL_HAVE_SSL_SET_CERT_STORE
    /*
     * check if per-dir and per-server config field are not the same.
     * if f is defined in per-dir and not defined in per-server
@@ -597,28 +587,31 @@ int ssl_hook_Access(request_rec *r)
#define MODSSL_CFG_NE(f) \
     (dc->f && (!sc->f || (sc->f && strNE(dc->f, sc->f))))

#define MODSSL_CFG_CA(f) \
     (dc->f ? dc->f : sc->f)

    if (MODSSL_CFG_NE(szCACertificateFile) ||
        MODSSL_CFG_NE(szCACertificatePath))
    {
        ca_file = dc->szCACertificateFile ?
            dc->szCACertificateFile : sc->szCACertificateFile;
        STACK_OF(X509_NAME) *ca_list;
        const char *ca_file = MODSSL_CFG_CA(szCACertificateFile);
        const char *ca_path = MODSSL_CFG_CA(szCACertificatePath);

        ca_path = dc->szCACertificatePath ?
            dc->szCACertificatePath : sc->szCACertificatePath;
        cert_store = X509_STORE_new();

        /*
           FIXME: This should be...
           if (!SSL_load_verify_locations(ssl, ca_file, ca_path)) {
           ...but OpenSSL still doesn't provide this!
         */
        if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) {
        if (!X509_STORE_load_locations(cert_store, ca_file, ca_path)) {
            ssl_log(r->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
                    "Unable to reconfigure verify locations "
                    "for client authentication");

            X509_STORE_free(cert_store);

            return HTTP_FORBIDDEN;
        }

        /* SSL_free will free cert_store */
        SSL_set_cert_store(ssl, cert_store);

        if (!(ca_list = ssl_init_FindCAList(r->server, r->pool,
                                            ca_file, ca_path)))
        {
@@ -631,13 +624,12 @@ int ssl_hook_Access(request_rec *r)

        SSL_set_client_CA_list(ssl, ca_list);
        renegotiate = TRUE;
        reconfigured_locations = TRUE;

        ssl_log(r->server, SSL_LOG_TRACE,
                "Changed client verification locations "
                "will force renegotiation");
    }
#endif /* SSL_EXPERIMENTAL_PERDIRCA */
#endif /* MODSSL_HAVE_SSL_SET_CERT_STORE */

    /* 
     * SSL renegotiations in conjunction with HTTP
@@ -726,23 +718,27 @@ int ssl_hook_Access(request_rec *r)
                "Requesting connection re-negotiation");

        if (renegotiate_quick) {
            STACK_OF(X509) *cert_stack;

            /* perform just a manual re-verification of the peer */
            ssl_log(r->server, SSL_LOG_TRACE,
                    "Performing quick renegotiation: "
                    "just re-verifying the peer");

            if (!(cert_store = SSL_CTX_get_cert_store(ctx))) {
            cert_stack = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl);

            if (!cert_stack || (sk_X509_num(cert_stack) == 0)) {
                ssl_log(r->server, SSL_LOG_ERROR,
                        "Cannot find certificate storage");
                        "Cannot find peer certificate chain");

                return HTTP_FORBIDDEN;
            }

            cert_stack = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl);

            if (!cert_stack || (sk_X509_num(cert_stack) == 0)) {
            if (!(cert_store ||
                  (cert_store = SSL_CTX_get_cert_store(ctx))))
            {
                ssl_log(r->server, SSL_LOG_ERROR,
                        "Cannot find peer certificate chain");
                        "Cannot find certificate storage");

                return HTTP_FORBIDDEN;
            }
@@ -836,27 +832,6 @@ int ssl_hook_Access(request_rec *r)
        }
    }

    /*
     * Under old OpenSSL we had to change the X509_STORE inside the
     * SSL_CTX instead inside the SSL structure, so we have to reconfigure it
     * to the old values. This should be changed with forthcoming OpenSSL
     * versions when better functionality is avaiable.
     */
#ifdef SSL_EXPERIMENTAL_PERDIRCA
    if (renegotiate && reconfigured_locations) {
        if (!SSL_CTX_load_verify_locations(ctx,
                                           sc->szCACertificateFile,
                                           sc->szCACertificatePath))
        {
            ssl_log(r->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
                    "Unable to reconfigure verify locations "
                    "to per-server configuration parameters");

            return HTTP_FORBIDDEN;
        }
    }
#endif /* SSL_EXPERIMENTAL_PERDIRCA */

    /*
     * Check SSLRequire boolean expressions
     */