You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2018/03/26 14:03:36 UTC

svn commit: r1827767 - /httpd/httpd/patches/2.4.x/ssl-policy.patch

Author: icing
Date: Mon Mar 26 14:03:35 2018
New Revision: 1827767

URL: http://svn.apache.org/viewvc?rev=1827767&view=rev
Log:
backport patch for SSLPolicy directive

Added:
    httpd/httpd/patches/2.4.x/ssl-policy.patch

Added: httpd/httpd/patches/2.4.x/ssl-policy.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/patches/2.4.x/ssl-policy.patch?rev=1827767&view=auto
==============================================================================
--- httpd/httpd/patches/2.4.x/ssl-policy.patch (added)
+++ httpd/httpd/patches/2.4.x/ssl-policy.patch Mon Mar 26 14:03:35 2018
@@ -0,0 +1,928 @@
+Index: CHANGES
+===================================================================
+--- CHANGES	(revision 1827760)
++++ CHANGES	(working copy)
+@@ -1,6 +1,10 @@
+                                                          -*- coding: utf-8 -*-
+ Changes with Apache 2.4.34
+ 
++ *) mod_ssl: Add new SSLPolicy directive with flavours "modern", 
++    "intermedate" and "old" as defined by Mozilla Security.
++    [Stefan Eissing]
++    
+  *) core: On ECBDIC platforms, some errors related to oversized headers
+      may be misreported or be logged as ASCII escapes.  PR62200
+      [Hank Ibell <hwibell gmail.com>]
+Index: docs/manual/mod/mod_ssl.xml
+===================================================================
+--- docs/manual/mod/mod_ssl.xml	(revision 1827760)
++++ docs/manual/mod/mod_ssl.xml	(working copy)
+@@ -2820,4 +2820,39 @@
+ </usage>
+ </directivesynopsis>
+ 
++<directivesynopsis>
++<name>SSLPolicy</name>
++<description>Apply a SSLPolicy by name</description>
++<syntax>SSLPolicy <em>name</em></syntax>
++<contextlist><context>server config</context>
++<context>virtual host</context></contextlist>
++<compatibility>Available in httpd 2.4.30 and later</compatibility>
++
++<usage>
++<p>This directive applies the set of SSL* directives defined
++under 'name' (see <directive type="section">SSLPolicyDefine</directive>) as the <em>base</em>
++settings in the current context. Apache comes with the following pre-defined policies from 
++Mozilla, the makers of the Firefox browser 
++(<a href="https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations">see here
++for a detailed description by them.</a>):
++</p>
++<ul>
++    <li><code>modern</code>: recommended when your server is accessible on the open Internet. Works with all modern browsers, but old devices might be unable to connect.</li>
++    <li><code>intermediate</code>: the fallback if you need to support old (but not very old) clients.</li>
++    <li><code>old</code>: when you need to give Windows XP/Internet Explorer 6 access. The last resort.</li>
++</ul>
++<p>SSLPolicy applies configuration settings in place, meaning previous values are
++overwritten. Configuration directives following an SSLPolicy may overwrite it.
++</p> 
++
++<p>You can check the detailed description of all defined policies via the command line:</p>
++<example><title>List all Defined Policies</title>
++<highlight language="sh">
++httpd -t -D DUMP_SSL_POLICIES
++</highlight>
++</example>
++
++</usage>
++</directivesynopsis>
++
+ </modulesynopsis>
+Index: modules/ssl/mod_ssl.c
+===================================================================
+--- modules/ssl/mod_ssl.c	(revision 1827760)
++++ modules/ssl/mod_ssl.c	(working copy)
+@@ -308,6 +308,8 @@
+     AP_INIT_RAW_ARGS("SSLLogLevel", ap_set_deprecated, NULL, OR_ALL,
+       "SSLLogLevel directive is no longer supported - use LogLevel."),
+ 
++    AP_INIT_TAKE1("SSLPolicy", ssl_cmd_SSLPolicyApply, NULL, RSRC_CONF, 
++                "Apply the SSL* (not the SSLProxy*) settings from the policy with the given name."),
+     AP_END_CMD
+ };
+ 
+Index: modules/ssl/mod_ssl.dsp
+===================================================================
+--- modules/ssl/mod_ssl.dsp	(revision 1827760)
++++ modules/ssl/mod_ssl.dsp	(working copy)
+@@ -180,6 +180,10 @@
+ # End Source File
+ # Begin Source File
+ 
++SOURCE=.\ssl_policies.h
++# End Source File
++# Begin Source File
++
+ SOURCE=.\ssl_util_ssl.h
+ # End Source File
+ # Begin Source File
+Index: modules/ssl/ssl_engine_config.c
+===================================================================
+--- modules/ssl/ssl_engine_config.c	(revision 1827760)
++++ modules/ssl/ssl_engine_config.c	(working copy)
+@@ -27,6 +27,7 @@
+                                            damned if you don't.''
+                                                -- Unknown        */
+ #include "ssl_private.h"
++#include "ssl_policies.h"
+ #include "util_mutex.h"
+ #include "ap_provider.h"
+ 
+@@ -89,7 +90,7 @@
+ 
+ BOOL ssl_config_global_isfixed(SSLModConfigRec *mc)
+ {
+-    return mc->bFixed;
++    return mc && mc->bFixed;
+ }
+ 
+ /*  _________________________________________________________________
+@@ -526,6 +527,130 @@
+     modssl_ctx_cfg_merge_proxy(p, base->proxy, conf->proxy, conf->proxy);
+ }
+ 
++/*  _________________________________________________________________
++**
++**  Policy handling
++**  _________________________________________________________________
++*/
++
++static void add_policy(apr_hash_t *policies, apr_pool_t *p, const char *name,
++                       int protocols, const char *ciphers, 
++                       int honor_order, int compression, int session_tickets)
++{
++    SSLPolicyRec *policy;
++    
++    policy = apr_pcalloc(p, sizeof(*policy));
++    policy->name = name;
++    policy->sc = ssl_config_server_new(p);
++    
++    if (protocols || ciphers) {
++        policy->sc->server->protocol_set      = 1;
++        policy->sc->server->protocol          = protocols;
++    }
++    
++    if (ciphers) {
++        policy->sc->server->auth.cipher_suite = ciphers;
++    }
++
++#ifndef OPENSSL_NO_COMP
++    policy->sc->compression               = compression ? TRUE : FALSE;
++#endif
++    policy->sc->session_tickets           = session_tickets ? TRUE : FALSE;
++    
++    apr_hash_set(policies, policy->name, APR_HASH_KEY_STRING, policy);
++}
++
++static apr_hash_t *get_policies(apr_pool_t *p, int create)
++{
++    apr_hash_t *policies;
++    void *vp;
++    
++    apr_pool_userdata_get(&vp, SSL_MOD_POLICIES_KEY, p);
++    if (vp) {
++        return vp; /* reused for lifetime of the pool */
++    }
++    if (create) {
++        policies = apr_hash_make(p);
++        
++#if SSL_POLICY_MODERN
++        add_policy(policies, p, "modern", 
++                   SSL_POLICY_MODERN_PROTOCOLS, 
++                   SSL_POLICY_MODERN_CIPHERS, 
++                   SSL_POLICY_HONOR_ORDER, 
++                   SSL_POLICY_COMPRESSION, 
++                   SSL_POLICY_SESSION_TICKETS);
++#endif        
++#if SSL_POLICY_INTERMEDIATE
++        add_policy(policies, p, "intermediate", 
++                   SSL_POLICY_INTERMEDIATE_PROTOCOLS, 
++                   SSL_POLICY_INTERMEDIATE_CIPHERS, 
++                   SSL_POLICY_HONOR_ORDER, 
++                   SSL_POLICY_COMPRESSION, 
++                   SSL_POLICY_SESSION_TICKETS);
++#endif        
++#if SSL_POLICY_OLD
++        add_policy(policies, p, "old", 
++                   SSL_POLICY_OLD_PROTOCOLS, 
++                   SSL_POLICY_OLD_CIPHERS, 
++                   SSL_POLICY_HONOR_ORDER, 
++                   SSL_POLICY_COMPRESSION, 
++                   SSL_POLICY_SESSION_TICKETS);
++#endif        
++        
++        apr_pool_userdata_set(policies, SSL_MOD_POLICIES_KEY,
++                              apr_pool_cleanup_null, p);
++        return policies;
++    }
++    return NULL;
++}
++
++static int policy_collect_names(void *baton, const void *key, apr_ssize_t klen, const void *val)
++{
++    apr_array_header_t *names = baton;
++    APR_ARRAY_PUSH(names, const char *) = (const char*)key;
++    return 1;
++}
++
++static int qstrcmp(const void *v1, const void *v2)
++{
++    return strcmp(*(const char**)v1, *(const char**)v2);
++}
++
++static apr_array_header_t *get_policy_names(apr_pool_t *p, int create)
++{
++    apr_array_header_t *names = apr_array_make(p, 10, sizeof(const char*));
++    apr_hash_t *policies = get_policies(p, create);
++    
++    if (policies) {
++        apr_hash_do(policy_collect_names, names, policies);
++        qsort(names->elts, names->nelts, sizeof(const char*), qstrcmp);
++    }
++    return names;
++}
++
++SSLPolicyRec *ssl_policy_lookup(apr_pool_t *pool, const char *name)
++{
++    apr_hash_t *policies = get_policies(pool, 1);
++    return apr_hash_get(policies, name, APR_HASH_KEY_STRING);
++}
++
++const char *ssl_cmd_SSLPolicyApply(cmd_parms *cmd, void *mconfig, const char *arg)
++{
++    SSLSrvConfigRec *mrg, *sc = mySrvConfig(cmd->server);
++    SSLPolicyRec *policy;
++    
++    policy = ssl_policy_lookup(cmd->pool, arg);
++    if (policy) {
++        mrg = ssl_config_server_merge(cmd->pool, policy->sc, sc);
++        /* apply in place */
++        memcpy(sc, mrg, sizeof(*sc));
++        return NULL;
++    }
++    return apr_pstrcat(cmd->pool,
++                       "An SSLPolicy with the name '", arg,
++                       "' does not exist", NULL);
++}
++
+ /*
+  *  Configuration functions for particular directives
+  */
+@@ -2034,34 +2159,404 @@
+     return NULL;
+ }
+ 
++static void ssl_srv_dump(SSLSrvConfigRec *sc, apr_pool_t *p, 
++                            apr_file_t *out, const char *indent, const char **psep);
++static void ssl_policy_dump(SSLPolicyRec *policy, apr_pool_t *p, 
++                            apr_file_t *out, const char *indent);
++
+ void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s)
+ {
+     apr_file_t *out = NULL;
+-    if (!ap_exists_config_define("DUMP_CERTS")) {
++    if (ap_exists_config_define("DUMP_CERTS")) {
++        apr_file_open_stdout(&out, pconf);
++        apr_file_printf(out, "Server certificates:\n");
++        
++        /* Dump the filenames of all configured server certificates to
++         * stdout. */
++        while (s) {
++            SSLSrvConfigRec *sc = mySrvConfig(s);
++            
++            if (sc && sc->server && sc->server->pks) {
++                modssl_pk_server_t *const pks = sc->server->pks;
++                int i;
++                
++                for (i = 0; (i < pks->cert_files->nelts) &&
++                     APR_ARRAY_IDX(pks->cert_files, i, const char *);
++                     i++) {
++                    apr_file_printf(out, "  %s\n",
++                                    APR_ARRAY_IDX(pks->cert_files,
++                                                  i, const char *));
++                }
++            }
++            
++            s = s->next;
++        }
+         return;
+     }
+-    apr_file_open_stdout(&out, pconf);
+-    apr_file_printf(out, "Server certificates:\n");
+ 
+-    /* Dump the filenames of all configured server certificates to
+-     * stdout. */
+-    while (s) {
+-        SSLSrvConfigRec *sc = mySrvConfig(s);
++    if (ap_exists_config_define("DUMP_SSL_POLICIES")) {
++        apr_array_header_t *names = get_policy_names(pconf, 1);
++        SSLPolicyRec *policy;
++        const char *name, *sep = "";
++        int i;
++        
++        apr_file_open_stdout(&out, pconf);
++        apr_file_printf(out, "SSLPolicies: {");
++        for (i = 0; i < names->nelts; ++i) {
++            name = APR_ARRAY_IDX(names, i, const char*);
++            policy = ssl_policy_lookup(pconf, name);
++            if (policy) {
++                apr_file_printf(out, "%s\n  \"%s\": {", sep, name);
++                sep = ", ";
++                ssl_policy_dump(policy, pconf, out, "    ");
++                apr_file_printf(out, "\n  }");
++            }
++        }
++        apr_file_printf(out, "\n}\n");
++        return;
++    }
++}
+ 
+-        if (sc && sc->server && sc->server->pks) {
+-            modssl_pk_server_t *const pks = sc->server->pks;
+-            int i;
++/*  _________________________________________________________________
++**
++**  Dump Config Data
++**  _________________________________________________________________
++*/
+ 
+-            for (i = 0; (i < pks->cert_files->nelts) &&
+-                        APR_ARRAY_IDX(pks->cert_files, i, const char *);
+-                 i++) {
+-                apr_file_printf(out, "  %s\n",
+-                                APR_ARRAY_IDX(pks->cert_files,
+-                                              i, const char *));
++static const char *json_quote(const char *s, apr_pool_t *p)
++{
++    const char *src, *dq = s;
++    int n = 0;
++    
++    while ((dq = ap_strchr_c(dq, '\"'))) {
++        ++n;
++        ++dq;
++    }
++    if (n > 0) {
++        char *dst, c;
++        src = s;
++        s = dst = apr_pcalloc(p, strlen(s) + n + 1);
++        while ((c = *src++)) {
++            if (c == '\"') {
++                *dst++ = '\\';
+             }
++            *dst++ = c;
+         }
++    }
++    return s;
++}
+ 
+-        s = s->next;
++static void val_str_dump(apr_file_t *out, const char *key, const char *val, 
++                         apr_pool_t *p, const char *indent, const char **psep)
++{
++    if (val) {
++        /* TODO: JSON quite string val */
++        apr_file_printf(out, "%s\n%s\"%s\": \"%s\"", *psep, indent, key, json_quote(val, p));
++        *psep = ", ";
+     }
++}
+ 
++static void val_str_array_dump(apr_file_t *out, const char *key, apr_array_header_t *val, 
++                               apr_pool_t *p, const char *indent, const char **psep)
++{
++    if (val && val->nelts > 0) {
++        const char *s; 
++        int i;
++        
++        for (i = 0; i < val->nelts; ++i) {
++            s = APR_ARRAY_IDX(val, i, const char*);
++            val_str_dump(out, key, s, p, indent, psep);
++        }
++    }
+ }
++
++static void val_long_dump(apr_file_t *out, const char *key, long val, 
++                          apr_pool_t *p, const char *indent, const char **psep)
++{
++    if (val != UNSET) {
++        apr_file_printf(out, "%s\n%s\"%s\": %ld", *psep, indent, key, val);
++        *psep = ", ";
++    }
++}
++
++static void val_itime_dump(apr_file_t *out, const char *key, apr_interval_time_t val, 
++                           apr_pool_t *p, const char *indent, const char **psep)
++{
++    if (val != UNSET) {
++        apr_file_printf(out, "%s\n%s\"%s\": %f", *psep, indent, key, 
++                        ((double)val/APR_USEC_PER_SEC));
++        *psep = ", ";
++    }
++}
++
++static void val_onoff_dump(apr_file_t *out, const char *key, BOOL val, 
++                           apr_pool_t *p, const char *indent, const char **psep)
++{
++    if (val != UNSET) {
++        val_str_dump(out, key, val? "on" : "off", p, indent, psep);
++    }
++}
++
++static void val_uri_dump(apr_file_t *out, const char *key, apr_uri_t *val, 
++                         apr_pool_t *p, const char *indent, const char **psep)
++{
++    if (val) {
++        val_str_dump(out, key, apr_uri_unparse(p, val, 0), p, indent, psep);
++    }
++}
++
++static void val_verify_dump(apr_file_t *out, const char *key, ssl_verify_t mode, 
++                            apr_pool_t *p, const char *indent, const char **psep)
++{
++    switch (mode) {
++        case SSL_CVERIFY_NONE:
++            val_str_dump(out, key, "none", p, indent, psep);
++            return;
++        case SSL_CVERIFY_OPTIONAL:
++            val_str_dump(out, key, "optional", p, indent, psep);
++            return;
++        case SSL_CVERIFY_REQUIRE:
++            val_str_dump(out, key, "require", p, indent, psep);
++            return;
++        case SSL_CVERIFY_OPTIONAL_NO_CA:
++            val_str_dump(out, key, "optional_no_ca", p, indent, psep);
++            return;
++        default:
++            return;
++    }
++}
++
++static void val_enabled_dump(apr_file_t *out, const char *key, ssl_enabled_t val, 
++                             apr_pool_t *p, const char *indent, const char **psep)
++{
++    switch (val) {
++        case SSL_ENABLED_FALSE:
++            val_str_dump(out, key, "off", p, indent, psep);
++            return;
++        case SSL_ENABLED_TRUE:
++            val_str_dump(out, key, "on", p, indent, psep);
++            return;
++        case SSL_ENABLED_OPTIONAL:
++            val_str_dump(out, key, "optional", p, indent, psep);
++            return;
++        default:                   
++            return;
++    }
++}
++
++static void val_pphrase_dump(apr_file_t *out, const char *key, 
++                             ssl_pphrase_t pphrase_type, const char *path, 
++                             apr_pool_t *p, const char *indent, const char **psep)
++{
++    switch (pphrase_type) {
++        case SSL_PPTYPE_BUILTIN: 
++            val_str_dump(out, key, "builtin", p, indent, psep);
++            return;
++        case SSL_PPTYPE_FILTER: 
++            val_str_dump(out, key, apr_pstrcat(p, "|", path, NULL), p, indent, psep);
++            return;
++        case SSL_PPTYPE_PIPE: 
++            val_str_dump(out, key, apr_pstrcat(p, "exec:", path, NULL), p, indent, psep);
++            return;
++        default:
++            return;
++    }
++}
++
++static void val_crl_check_dump(apr_file_t *out, const char *key, int mask, 
++                               apr_pool_t *p, const char *indent, const char **psep)
++{
++    if (mask != UNSET) {
++        if (mask == SSL_CRLCHECK_NONE) {
++            val_str_dump(out, key, "none", p, indent, psep);
++        }
++        else if (mask == SSL_CRLCHECK_LEAF) {
++            val_str_dump(out, key, "leaf", p, indent, psep);
++        }
++        else if (mask == SSL_CRLCHECK_CHAIN) {
++            val_str_dump(out, key, "chain", p, indent, psep);
++        }
++        else if (mask == (SSL_CRLCHECK_CHAIN|SSL_CRLCHECK_NO_CRL_FOR_CERT_OK)) {
++            val_str_dump(out, key, "chain no_crl_for_cert_ok", p, indent, psep);
++        }
++        else {
++            val_str_dump(out, key, "???", p, indent, psep);
++        }
++    }
++}
++
++static const char *protocol_str(ssl_proto_t proto, apr_pool_t *p)
++{
++    if (SSL_PROTOCOL_NONE == proto) {
++        return "none";
++    }
++    else if (SSL_PROTOCOL_ALL == proto) {
++        return "all";
++    }
++    else {
++        /* icing: I think it is nuts that we define our own IETF protocol constants
++         * only whent the linked *SSL lib supports them. */
++        apr_array_header_t *names = apr_array_make(p, 5, sizeof(const char*));
++        if ((1<<4) & proto) {
++            APR_ARRAY_PUSH(names, const char*) = "+TLSv1.2";
++        }
++        if ((1<<3) & proto) {
++            APR_ARRAY_PUSH(names, const char*) = "+TLSv1.1";
++        }
++        if ((1<<2) & proto) {
++            APR_ARRAY_PUSH(names, const char*) = "+TLSv1.0";
++        }
++        if ((1<<1) & proto) {
++            APR_ARRAY_PUSH(names, const char*) = "+SSLv3";
++        }
++        return apr_array_pstrcat(p, names, ' ');
++    }
++}
++
++#define DMP_STRING(k,v) \
++    val_str_dump(out, k, v, p, indent, psep)
++#define DMP_LONG(k,v) \
++    val_long_dump(out, k, v, p, indent, psep)
++#define DMP_ITIME(k,v) \
++    val_itime_dump(out, k, v, p, indent, psep)
++#define DMP_STRARR(k,v) \
++    val_str_array_dump(out, k, v, p, indent, psep)
++#define DMP_VERIFY(k,v) \
++    val_verify_dump(out, k, v, p, indent, psep)
++#define DMP_ON_OFF(k,v) \
++    val_onoff_dump(out, k, v, p, indent, psep)
++#define DMP_URI(k,v) \
++    val_uri_dump(out, k, v, p, indent, psep)
++#define DMP_CRLCHK(k,v) \
++    val_crl_check_dump(out, k, v, p, indent, psep)
++#define DMP_PHRASE(k,v, v2) \
++    val_pphrase_dump(out, k, v, v2, p, indent, psep)
++#define DMP_ENABLD(k,v) \
++    val_enabled_dump(out, k, v, p, indent, psep)
++#define DMP_OPTION(n,v) \
++    val_option_dump(out, "SSLOption", n, v, \
++                    dc->nOptions, dc->nOptionsAdd, dc->nOptionsDel, p, indent, psep);
++
++static void modssl_auth_ctx_dump(modssl_auth_ctx_t *auth, apr_pool_t *p, int proxy,
++                                 apr_file_t *out, const char *indent, const char **psep)
++{
++    DMP_STRING(proxy? "SSLProxyCipherSuite" : "SSLCipherSuite", auth->cipher_suite);
++    DMP_VERIFY(proxy? "SSLProxyVerify" : "SSLVerifyClient", auth->verify_mode);
++    DMP_LONG(  proxy? "SSLProxyVerify" : "SSLVerifyDepth", auth->verify_depth);
++    DMP_STRING(proxy? "SSLProxyCACertificateFile" : "SSLCACertificateFile", auth->ca_cert_file);
++    DMP_STRING(proxy? "SSLProxyCACertificatePath" : "SSLCACertificatePath", auth->ca_cert_path);
++}
++
++static void modssl_ctx_dump(modssl_ctx_t *ctx, apr_pool_t *p, int proxy,
++                            apr_file_t *out, const char *indent, const char **psep)
++{
++#ifdef HAVE_SSL_CONF_CMD
++    int i;
++#endif
++
++    if (ctx->protocol_set) {
++        DMP_STRING(proxy? "SSLProxyProtocol" : "SSLProtocol", protocol_str(ctx->protocol, p));
++    }
++
++    modssl_auth_ctx_dump(&ctx->auth, p, proxy, out, indent, psep);
++
++    DMP_STRING(proxy? "SSLProxyCARevocationFile" : "SSLCARevocationFile", ctx->crl_file);
++    DMP_STRING(proxy? "SSLProxyCARevocationPath" : "SSLCARevocationPath", ctx->crl_path);
++    DMP_CRLCHK(proxy? "SSLProxyCARevocationCheck" : "SSLCARevocationCheck", ctx->crl_check_mask);
++    if (!proxy) {
++        DMP_PHRASE("SSLPassPhraseDialog", ctx->pphrase_dialog_type, ctx->pphrase_dialog_path);
++        if (ctx->pks) {
++            DMP_STRING("SSLCADNRequestFile", ctx->pks->ca_name_file);
++            DMP_STRING("SSLCADNRequestPath", ctx->pks->ca_name_path);
++            DMP_STRARR("SSLCertificateFile", ctx->pks->cert_files);
++            DMP_STRARR("SSLCertificateKeyFile", ctx->pks->key_files);
++        }
++#ifdef HAVE_OCSP_STAPLING
++        DMP_ON_OFF("SSLUseStapling", ctx->stapling_enabled);
++        DMP_LONG(  "SSLStaplingResponseTimeSkew", ctx->stapling_resptime_skew);
++        DMP_LONG(  "SSLStaplingResponseMaxAge", ctx->stapling_resp_maxage);
++        DMP_LONG(  "SSLStaplingStandardCacheTimeout", ctx->stapling_cache_timeout);
++        DMP_ON_OFF("SSLStaplingReturnResponderErrors", ctx->stapling_return_errors);
++        DMP_ON_OFF("SSLStaplingFakeTryLater", ctx->stapling_fake_trylater);
++        DMP_LONG(  "SSLStaplingErrorCacheTimeout", ctx->stapling_errcache_timeout);
++        DMP_ITIME( "SSLStaplingResponderTimeout", ctx->stapling_responder_timeout);
++        DMP_STRING("SSLStaplingForceURL", ctx->stapling_force_url);
++#endif /* if HAVE_OCSP_STAPLING */ 
++
++#ifdef HAVE_SRP
++        DMP_STRING("SSLSRPUnknownUserSeed", ctx->srp_unknown_user_seed);
++        DMP_STRING("SSLSRPVerifierFile", ctx->srp_vfile);
++#endif
++        DMP_ON_OFF("SSLOCSPEnable", ctx->ocsp_enabled);
++        DMP_ON_OFF("SSLOCSPOverrideResponder", ctx->ocsp_force_default);
++        DMP_STRING("SSLOCSPDefaultResponder", ctx->ocsp_responder);
++        DMP_LONG(  "SSLOCSPResponseTimeSkew", ctx->ocsp_resptime_skew);
++        DMP_LONG(  "SSLOCSPResponseMaxAge", ctx->ocsp_resp_maxage);
++        DMP_ITIME( "SSLOCSPResponderTimeout", ctx->ocsp_responder_timeout);
++        DMP_ON_OFF("SSLOCSPUseRequestNonce", ctx->ocsp_use_request_nonce);
++        DMP_URI(   "SSLOCSPProxyURL", ctx->proxy_uri);
++        DMP_ON_OFF("SSLOCSPNoVerify", ctx->ocsp_noverify);
++        DMP_STRING("SSLOCSPResponderCertificateFile", ctx->ocsp_certs_file);
++
++#ifdef HAVE_SSL_CONF_CMD
++        if (ctx->ssl_ctx_param && ctx->ssl_ctx_param->nelts > 0) {
++            ssl_ctx_param_t *param = (ssl_ctx_param_t *)ctx->ssl_ctx_param->elts;
++            for (i = 0; i < ctx->ssl_ctx_param->nelts; ++i, ++param) {
++                apr_file_printf(out, "%s\n%s\"%s\": \"%s %s\"", *psep, indent, 
++                                "SSLOpenSSLConfCmd", json_quote(param->name, p), 
++                                json_quote(param->value, p));
++                *psep = ", ";
++            }
++        }
++#endif
++
++#ifdef HAVE_TLS_SESSION_TICKETS
++        if (ctx->ticket_key) {
++            DMP_STRING("SSLSessionTicketKeyFile", ctx->ticket_key->file_path);
++        }
++#endif
++    }
++    else { /* proxy */
++        if (ctx->pkp) {
++            DMP_STRING("SSLProxyMachineCertificateFile", ctx->pkp->cert_file);
++            DMP_STRING("SSLProxyMachineCertificatePath", ctx->pkp->cert_path);
++            DMP_STRING("SSLProxyMachineCertificateChainFile", ctx->pkp->ca_cert_file);
++        }
++        DMP_ON_OFF("SSLProxyCheckPeerCN", ctx->ssl_check_peer_cn);
++        DMP_ON_OFF("SSLProxyCheckPeerName", ctx->ssl_check_peer_cn);
++        DMP_ON_OFF("SSLProxyCheckPeerExpire", ctx->ssl_check_peer_expire);
++    }
++}
++
++static void ssl_srv_dump(SSLSrvConfigRec *sc, apr_pool_t *p, 
++                            apr_file_t *out, const char *indent, const char **psep)
++{
++    DMP_ENABLD("SSLEngine", sc->enabled);
++    DMP_ON_OFF("SSLHonorCipherOrder", sc->cipher_server_pref);
++
++#ifndef OPENSSL_NO_COMP
++    DMP_ON_OFF("SSLCompression", sc->compression);
++#endif
++
++    modssl_ctx_dump(sc->server, p, 0, out, indent, psep);
++
++    DMP_LONG(  "SSLSessionCacheTimeout", sc->session_cache_timeout);
++    DMP_ON_OFF("SSLInsecureRenegotiation", sc->insecure_reneg);
++    DMP_ON_OFF("SSLStrictSNIVHostCheck", sc->strict_sni_vhost_check);
++#ifdef HAVE_FIPS
++    DMP_ON_OFF("SSLFIPS", sc->fips);
++#endif
++    DMP_ON_OFF("SSLSessionTickets", sc->session_tickets);
++}
++
++static void ssl_policy_dump(SSLPolicyRec *policy, apr_pool_t *p, 
++                            apr_file_t *out, const char *indent)
++{
++    const char *sep = "";
++    if (policy->sc) {
++        ssl_srv_dump(policy->sc, p, out, indent, &sep);
++    }
++}
++
++
++
+Index: modules/ssl/ssl_policies.h
+===================================================================
+--- modules/ssl/ssl_policies.h	(nonexistent)
++++ modules/ssl/ssl_policies.h	(working copy)
+@@ -0,0 +1,85 @@
++/* 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.
++ */
++
++/**
++ * @verbatim
++                        _             _
++    _ __ ___   ___   __| |    ___ ___| |  mod_ssl
++   | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
++   | | | | | | (_) | (_| |   \__ \__ \ |
++   |_| |_| |_|\___/ \__,_|___|___/___/_|
++                        |_____|
++   @endverbatim
++ * @file  ssl_policies.h
++ * @brief Additional Utility Functions for OpenSSL
++ *
++ * @defgroup MOD_SSL_UTIL Utilities
++ * @ingroup MOD_SSL
++ * @{
++ */
++
++#ifndef __SSL_POLICIES_H__
++#define __SSL_POLICIES_H__
++
++#define SSL_MOD_POLICIES_KEY "ssl_module_policies"
++
++#ifndef OPENSSL_NO_SSL3
++#define SSL_PROTOCOL_CONSTANTS_SSLV3        SSL_PROTOCOL_SSLV3
++#else
++#define SSL_PROTOCOL_CONSTANTS_SSLV3        0
++#endif
++
++#ifdef HAVE_TLSV1_X
++#define SSL_POLICY_LEGACY_PROTOCOLS  \
++    (SSL_PROTOCOL_CONSTANTS_SSLV3|SSL_PROTOCOL_TLSV1|SSL_PROTOCOL_TLSV1_1)
++#endif
++
++/* Settings for all policies */
++#define SSL_POLICY_HONOR_ORDER              1
++#define SSL_POLICY_COMPRESSION              0
++#define SSL_POLICY_SESSION_TICKETS          0
++
++/**
++ * Define a core set of policies that are always there:
++ * - 'modern' from https://wiki.mozilla.org/Security/Server_Side_TLS
++ * - 'intermediate' from https://wiki.mozilla.org/Security/Server_Side_TLS
++ * - 'old' from https://wiki.mozilla.org/Security/Server_Side_TLS
++ * The JSON version can be retrieved here:
++ * https://statics.tls.security.mozilla.org/server-side-tls-conf.json
++ */
++
++#define SSL_POLICY_MOZILLA_VERSION 4.0
++
++#ifdef HAVE_TLSV1_X
++#define SSL_POLICY_MODERN    1
++#define SSL_POLICY_MODERN_CIPHERS "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
++#define SSL_POLICY_MODERN_PROTOCOLS SSL_PROTOCOL_TLSV1_2
++#else /* ifdef HAVE_TLSV1_X */
++#define SSL_POLICY_MODERN    0
++#endif /* ifdef HAVE_TLSV1_X, else part */
++
++#define SSL_POLICY_INTERMEDIATE    1
++#define SSL_POLICY_INTERMEDIATE_CIPHERS "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS"
++#define SSL_POLICY_INTERMEDIATE_PROTOCOLS (SSL_PROTOCOL_ALL & ~(SSL_PROTOCOL_CONSTANTS_SSLV3))
++
++#define SSL_POLICY_OLD    1
++#define SSL_POLICY_OLD_CIPHERS "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP"
++#define SSL_POLICY_OLD_PROTOCOLS SSL_PROTOCOL_ALL
++
++
++#endif /* __SSL_POLICIES_H__ */
++/** @} */
++
+Index: modules/ssl/ssl_policies.h.in
+===================================================================
+Index: modules/ssl/ssl_private.h
+===================================================================
+--- modules/ssl/ssl_private.h	(revision 1827760)
++++ modules/ssl/ssl_private.h	(working copy)
+@@ -770,6 +770,14 @@
+     BOOL          proxy_post_config;
+ };
+ 
++typedef struct SSLPolicyRec SSLPolicyRec;
++struct SSLPolicyRec {
++    const char *name;
++    SSLSrvConfigRec *sc;
++};
++
++SSLPolicyRec *ssl_policy_lookup(apr_pool_t *pool, const char *name);
++
+ /**
+  *  function prototypes
+  */
+@@ -787,6 +795,7 @@
+ void        *ssl_config_perdir_merge(apr_pool_t *, void *, void *);
+ void         ssl_config_proxy_merge(apr_pool_t *,
+                                     SSLDirConfigRec *, SSLDirConfigRec *);
++const char  *ssl_cmd_SSLPolicyApply(cmd_parms *, void *, const char *);
+ const char  *ssl_cmd_SSLPassPhraseDialog(cmd_parms *, void *, const char *);
+ const char  *ssl_cmd_SSLCryptoDevice(cmd_parms *, void *, const char *);
+ const char  *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *);
+Index: modules/ssl/update_policies.py
+===================================================================
+--- modules/ssl/update_policies.py	(nonexistent)
++++ modules/ssl/update_policies.py	(working copy)
+@@ -0,0 +1,133 @@
++#!/usr/bin/env python
++
++import json
++import os
++import sys
++
++from httplib import HTTPSConnection
++
++# The location were Mozilla defines the *current* TLS Security in JSON format
++#
++MOZ_TLS_CONF_SERVER = "statics.tls.security.mozilla.org"
++MOZ_TLS_CONF_PATH   = "/server-side-tls-conf.json"
++MOZ_TLS_CONF_URL    = "https://%s%s" % (MOZ_TLS_CONF_SERVER, MOZ_TLS_CONF_PATH)
++
++# The version we already know. Accept nothing less.
++#
++MOZ_TLS_CONF_VERSION_MIN = 4.0
++
++# keys inside the JSON document
++#
++KEY_CONF         = 'configurations'
++KEY_HREF         = 'href'
++KEY_OSSL_CIPHERS = 'openssl_ciphersuites'
++KEY_TLS_VERSIONS = 'tls_versions'
++KEY_VERSION      = 'version'
++
++# TLS Versions we know how to handle
++#
++TLS_VERSIONS     = {
++    'TLSv1.2' : "SSL_PROTOCOL_TLSV1_2",
++    'TLSv1.1' : "SSL_PROTOCOL_TLSV1_1",
++    'TLSv1'   : "SSL_PROTOCOL_TLSV1",
++    'SSLv3'   : "SSL_PROTOCOL_CONSTANTS_SSLV3",
++}
++TLS_1_X_VERSIONS = [ 'TLSv1.2' ]
++
++# the Security configurations to extract
++POLICY_NAMES = [ 'modern', 'intermediate', 'old' ]
++
++
++def fail(msg):
++    sys.stderr.write(msg)
++    sys.exit(1)
++
++
++def proto_string(tls_version):
++    if tls_version in TLS_VERSIONS:
++        return TLS_VERSIONS[tls_version]
++    fail("Unknown TLS protocol '%s'" % tls_version)
++    
++
++def proto_conf(tls_versions):
++    if len(TLS_VERSIONS) < len(tls_versions):
++        fail("more TLS versions used than we know: %s" % tls_versions)
++    if len(tls_versions) == 1:
++        return proto_string(tls_versions[0])
++    missing = []
++    for tls in TLS_VERSIONS:
++        if not tls in tls_versions:
++            missing.append(proto_string(tls))
++    if len(missing):
++        return "(SSL_PROTOCOL_ALL & ~(%s))" % "|".join(missing)
++    return "SSL_PROTOCOL_ALL"
++
++
++# return an #ifdef required for a policy or None
++#
++def required_ifdef(conf):
++    for tlsv in conf[KEY_TLS_VERSIONS]:
++        # if it has a non-1_X protocol, it works without OpenSSL 1.0.2
++        if not tlsv in TLS_1_X_VERSIONS:
++            return None
++    return "HAVE_TLSV1_X"
++    
++
++def getPolicyDef():
++    c = HTTPSConnection(MOZ_TLS_CONF_SERVER)
++    c.request('GET', MOZ_TLS_CONF_PATH)
++    data = c.getresponse().read()
++    c.close()
++    return data
++
++
++def printPolicies(doc):
++    print "#define SSL_POLICY_MOZILLA_VERSION %s" % doc[KEY_VERSION]
++    print ""
++    for pname in POLICY_NAMES:
++        prefix = "SSL_POLICY_%s" % pname.upper()
++        if not pname in doc[KEY_CONF]:
++            vars[prefix] = 0
++            continue
++        p = doc[KEY_CONF][pname]
++        
++        ifdef = required_ifdef(p)
++        if ifdef:
++            print "#ifdef %s" % ifdef
++            
++        print "#define %s    1" % prefix
++        print "#define %s_CIPHERS \"%s\"" % (prefix, p[KEY_OSSL_CIPHERS])
++        print "#define %s_PROTOCOLS %s" % (prefix, proto_conf(p[KEY_TLS_VERSIONS]))
++        
++        if ifdef:
++            print "#else /* ifdef %s */" % ifdef
++            print "#define %s    0" % prefix
++            print "#endif /* ifdef %s, else part */" % ifdef
++        print ""
++
++
++def main(argv):
++    data = getPolicyDef()
++    doc = json.loads(data)
++    
++    if MOZ_TLS_CONF_URL != doc[KEY_HREF]:
++        fail("ERROR: Unexpected href in policy document: %s\n" % doc[KEY_HREF])
++    if doc[KEY_VERSION] < MOZ_TLS_CONF_VERSION_MIN:
++        fail("ERROR: Expected at least version %s, but policy document has %s\n" \
++            % (MOZ_TLS_CONF_VERSION_MIN, doc[KEY_VERSION]))
++    
++    if 1 == len(argv):
++        printPolicies(doc)
++    elif 2 == len(argv):
++        with open(argv[1]) as f:
++            for line in f:
++                if line == "@MOZILLA_SECURITY_POLICIES@\n":
++                    printPolicies(doc)
++                else:
++                    sys.stdout.write(line)
++    else:
++        fail("usage: %s [file] \nDownload and print/replace the Mozilla TLS Security policies" % argv[0])
++    
++    
++if __name__ == "__main__":
++    main(sys.argv)
+Index: .
+===================================================================
+--- .	(revision 1827760)
++++ .	(working copy)
+
+Property changes on: .
+___________________________________________________________________
+Modified: svn:mergeinfo
+## -0,0 +0,1 ##
+   Merged /httpd/httpd/trunk:r1805186,1807709,1808244,1808335,1817381,1817894,1818030,1827561,1827760