Index: modules/ssl/mod_ssl.c
===================================================================
--- modules/ssl/mod_ssl.c	(revision 1804998)
+++ modules/ssl/mod_ssl.c	(working copy)
@@ -312,6 +312,15 @@
     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_SSLPolicyDefine, NULL, RSRC_CONF, 
+                "Define a set of SSL* configurations under a new name. Such a policy may "
+                "be used in any location where the SSL* directives are viable. The policy "
+                "may contain both SSL* and SSLProxy* specific settings. Which one is applied "
+                "depends on the use."),
+    AP_INIT_TAKE1("SSLPolicy", ssl_cmd_SSLPolicyApply, NULL, RSRC_CONF, 
+                "Use the SSL* (not the SSLProxy*) settings from the policy with the given name."),
+    AP_INIT_TAKE1("SSLProxyPolicy", ssl_cmd_SSLProxyPolicyApply, NULL, RSRC_CONF|PROXY_CONF, 
+                "Use the SSLProxy* settings from the policy with the given name."),
     AP_END_CMD
 };
 
Index: modules/ssl/ssl_engine_config.c
===================================================================
--- modules/ssl/ssl_engine_config.c	(revision 1804998)
+++ modules/ssl/ssl_engine_config.c	(working copy)
@@ -226,6 +226,8 @@
     sc->compression            = UNSET;
 #endif
     sc->session_tickets        = UNSET;
+    sc->policies               = NULL;
+    sc->error_policy           = NULL;
 
     modssl_ctx_init_server(sc, p);
 
@@ -339,6 +341,9 @@
 #endif
 }
 
+static void ssl_policy_apply(SSLSrvConfigRec *sc, apr_pool_t *p);
+static void ssl_dir_policy_apply(SSLDirConfigRec *dc, apr_pool_t *p);
+
 void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
 {
     SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev;
@@ -345,6 +350,10 @@
     SSLSrvConfigRec *add  = (SSLSrvConfigRec *)addv;
     SSLSrvConfigRec *mrg  = ssl_config_server_new(p);
 
+    /* This is a NOP, unless a policy has not been applied yet */
+    ssl_policy_apply(base, p);
+    ssl_policy_apply(add, p);
+    
     cfgMerge(mc, NULL);
     cfgMerge(enabled, SSL_ENABLED_UNSET);
     cfgMergeInt(session_cache_timeout);
@@ -361,6 +370,9 @@
 #endif
     cfgMergeBool(session_tickets);
 
+    mrg->policies = NULL;
+    cfgMergeString(error_policy);
+                         
     modssl_ctx_cfg_merge_server(p, base->server, add->server, mrg->server);
 
     return mrg;
@@ -410,6 +422,9 @@
     modssl_ctx_init_proxy(dc, p);
     dc->proxy_post_config = FALSE;
 
+    dc->policies = NULL;
+    dc->error_policy = NULL;
+    
     return dc;
 }
 
@@ -435,6 +450,9 @@
     SSLDirConfigRec *add  = (SSLDirConfigRec *)addv;
     SSLDirConfigRec *mrg  = (SSLDirConfigRec *)apr_palloc(p, sizeof(*mrg));
 
+    ssl_dir_policy_apply(base, p);
+    ssl_dir_policy_apply(add, p);
+    
     cfgMerge(bSSLRequired, FALSE);
     cfgMergeArray(aRequirement);
 
@@ -474,6 +492,9 @@
         mrg->proxy = add->proxy;
     }
 
+    mrg->policies = NULL;
+    cfgMergeString(error_policy);
+
     return mrg;
 }
 
@@ -488,6 +509,306 @@
     modssl_ctx_cfg_merge_proxy(p, base->proxy, conf->proxy, conf->proxy);
 }
 
+/*  _________________________________________________________________
+**
+**  Policy handling
+**  _________________________________________________________________
+*/
+
+#define SSL_MOD_POLICIES_KEY "ssl_module_policies"
+
+/**
+ * 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
+ */
+#ifdef HAVE_TLSV1_X
+    /* Only with OpenSSL > v1.0.2 do we have a chance to implement modern */
+#define SSL_POLICY_LEGACY_PROTOCOLS  \
+    (SSL_PROTOCOL_SSLV3|SSL_PROTOCOL_TLSV1|SSL_PROTOCOL_TLSV1_1)
+
+#define SSL_POLICY_MODERN_PROTOCOLS  \
+    (SSL_PROTOCOL_ALL & ~SSL_POLICY_LEGACY_PROTOCOLS)
+#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"
+#endif
+    
+#define SSL_POLICY_INTERMEDIATE_PROTOCOLS \
+    (SSL_PROTOCOL_ALL & ~SSL_PROTOCOL_SSLV3)
+#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_OLD_PROTOCOLS            (SSL_PROTOCOL_ALL)
+#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_HIGH_CIPHERS         "HIGH:!MD5:!RC4:!3DES:!aNULL:!eNULL:!EXP"
+#define SSL_POLICY_MEDIUM_CIPHERS       "HIGH:MEDIUM:!MD5:!RC4:!3DES:!aNULL:!eNULL:!EXP"
+
+#define SSL_POLICY_PROXY_VERIFY_MODE    SSL_CVERIFY_REQUIRE
+#define SSL_POLICY_PROXY_VERIFY_DEPTH   5
+
+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,
+                       ssl_verify_t proxy_verify_mode, int proxy_verify_depth)
+{
+    SSLPolicyRec *policy;
+    
+    policy = apr_pcalloc(p, sizeof(*policy));
+    policy->name = name;
+    policy->sc = ssl_config_server_new(p);
+    policy->dc = ssl_config_perdir_create(p, "/");
+    
+    if (protocols || ciphers) {
+        policy->sc->server->protocol_set      = 1;
+        policy->sc->server->protocol          = protocols;
+        policy->dc->proxy->protocol_set       = 1;
+        policy->dc->proxy->protocol           = protocols;
+    }
+    
+    if (ciphers) {
+        policy->sc->server->auth.cipher_suite = ciphers;
+        policy->dc->proxy->auth.cipher_suite = ciphers;
+    }
+
+    policy->sc->compression               = compression ? TRUE : FALSE;
+    policy->sc->session_tickets           = session_tickets ? TRUE : FALSE;
+    
+    policy->dc->proxy->auth.verify_mode  = proxy_verify_mode;
+    if (proxy_verify_depth >= 0) {
+        policy->dc->proxy->auth.verify_depth = proxy_verify_depth;
+    }
+    
+    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);
+        
+        /* We could also invoke the commands here and let them parse strings. */
+#ifdef HAVE_TLSV1_X
+        add_policy(policies, p, "modern", 
+                   SSL_POLICY_MODERN_PROTOCOLS, SSL_POLICY_MODERN_CIPHERS, 
+                   1, 0, 0, 
+                   SSL_POLICY_PROXY_VERIFY_MODE, SSL_POLICY_PROXY_VERIFY_DEPTH);
+#endif        
+        add_policy(policies, p, "intermediate", 
+                   SSL_POLICY_INTERMEDIATE_PROTOCOLS, SSL_POLICY_INTERMEDIATE_CIPHERS, 
+                   1, 0, 0, 
+                   SSL_POLICY_PROXY_VERIFY_MODE, SSL_POLICY_PROXY_VERIFY_DEPTH);
+                   
+        add_policy(policies, p, "old", 
+                   SSL_POLICY_OLD_PROTOCOLS, SSL_POLICY_OLD_CIPHERS, 
+                   1, 0, 0, 
+                   SSL_CVERIFY_NONE, -1);
+
+        /* we could add those, similar to definitions in docs/conf/extra/httpd-ssl.con 
+        add_policy(policies, p, "high", 
+                   SSL_POLICY_INTERMEDIATE_PROTOCOLS, SSL_POLICY_HIGH_CIPHERS, 
+                   1, 0, 0, 
+                   SSL_CVERIFY_REQUIRE, 5);
+        
+        add_policy(policies, p, "medium", 
+                   SSL_POLICY_INTERMEDIATE_PROTOCOLS, SSL_POLICY_MEDIUM_CIPHERS, 
+                   1, 0, 0, 
+                   SSL_CVERIFY_REQUIRE, 5);
+        */
+        
+        apr_pool_userdata_set(policies, SSL_MOD_POLICIES_KEY,
+                              apr_pool_cleanup_null, p);
+        return policies;
+    }
+    return NULL;
+}
+
+SSLPolicyRec *ssl_policy_lookup(apr_pool_t *pool, const char *name)
+{
+    apr_hash_t *policies = get_policies(pool, 0);
+    if (policies) {
+        return apr_hash_get(policies, name, APR_HASH_KEY_STRING);
+    }
+    else if ((pool = apr_pool_parent_get(pool))) {
+        return ssl_policy_lookup(pool, name);
+    }
+    return NULL;
+}
+
+static void ssl_policy_set(apr_pool_t *pool, SSLPolicyRec *policy)
+{
+    apr_hash_t *policies = get_policies(pool, 1);
+    return apr_hash_set(policies, policy->name, APR_HASH_KEY_STRING, policy);
+}
+
+const char *ssl_cmd_SSLPolicyDefine(cmd_parms *cmd, void *mconfig, const char *arg)
+{
+    server_rec *s = cmd->server;
+    SSLSrvConfigRec *sc = mySrvConfig(s);
+    SSLDirConfigRec *dc = ap_get_module_config(s->lookup_defaults, &ssl_module);
+    SSLPolicyRec *policy;
+    const char *endp = ap_strrchr_c(arg, '>');
+    const char *err, *name;
+
+    if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
+        return err;
+    }
+        
+    if (endp == NULL) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name, "> directive missing closing '>'", NULL);
+    }
+
+    arg = apr_pstrndup(cmd->pool, arg, endp-arg);
+    if (!arg || !*arg) {
+        return "<SSLPolicy > block must specify a name";
+    }
+
+    name = ap_getword_white(cmd->pool, &arg);
+    if (*arg != '\0') {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name, "> takes only 1 argument", NULL);
+    }
+    
+    policy = apr_pcalloc(cmd->pool, sizeof(*policy));
+    policy->name = name;
+    policy->sc = ssl_config_server_new(cmd->pool);
+    policy->dc = ssl_config_perdir_create(cmd->pool, "/");/* TODO */
+
+    ap_set_module_config(s->module_config,  &ssl_module, policy->sc);
+    ap_set_module_config(s->lookup_defaults,  &ssl_module, policy->dc);
+    
+    err = ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
+    if (!err) {
+        /* If this new policy uses other policies, we need to merge it
+         * before adding, otherwise a policy cannot re-use an existing one */
+        ssl_policy_apply(policy->sc, cmd->pool);
+        ssl_dir_policy_apply(policy->dc, cmd->pool);
+        /* time to persist */
+        ssl_policy_set(cmd->pool, policy);
+    }
+    
+    ap_set_module_config(s->module_config,  &ssl_module, sc);
+    ap_set_module_config(s->lookup_defaults,  &ssl_module, dc);
+
+    return err;
+}
+
+const char *ssl_cmd_SSLPolicyApply(cmd_parms *cmd, void *mconfig, const char *arg)
+{
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+    
+    if (!sc->policies) {
+        sc->policies = apr_array_make(cmd->pool, 5, sizeof(const char*));
+    }
+    
+    APR_ARRAY_PUSH(sc->policies, const char *) = arg;
+
+    return NULL;
+}
+
+const char *ssl_cmd_SSLProxyPolicyApply(cmd_parms *cmd, void *mconfig, const char *arg)
+{
+    SSLDirConfigRec *dc = ap_get_module_config(cmd->server->lookup_defaults, &ssl_module);
+    
+    if (!dc->policies) {
+        dc->policies = apr_array_make(cmd->pool, 5, sizeof(const char*));
+    }
+    
+    APR_ARRAY_PUSH(dc->policies, const char *) = arg;
+
+    return NULL;
+}
+
+void ssl_policy_apply(SSLSrvConfigRec *sc, apr_pool_t *p)
+{
+    SSLSrvConfigRec *mrg;
+    SSLPolicyRec *policy;
+    apr_array_header_t *policies;
+    const char *name;
+    int i;
+
+    policies = sc->policies;
+    if (policies && policies->nelts > 0 && !sc->error_policy) {
+        sc->policies = NULL;
+        for (i = policies->nelts - 1; i >= 0; --i) {
+            name = APR_ARRAY_IDX(policies, i, const char *);
+            policy = ssl_policy_lookup(p, name);
+            if (policy) {
+                mrg = ssl_config_server_merge(p, policy->sc, sc);
+                /* apply in place */
+                memcpy(sc, mrg, sizeof(*sc));
+            }
+            else {
+                sc->error_policy = name;
+                break;
+                /* report error policies in post_config */
+            }
+        }
+    }
+}
+
+void ssl_dir_policy_apply(SSLDirConfigRec *dc, apr_pool_t *p)
+{
+    SSLDirConfigRec *mrg;
+    SSLPolicyRec *policy;
+    apr_array_header_t *policies;
+    const char *name;
+    int i;
+    
+    policies = dc->policies;
+    if (policies && policies->nelts > 0 &&!dc->error_policy) {
+        dc->policies = NULL;
+        for (i = policies->nelts - 1; i >= 0; --i) {
+            name = APR_ARRAY_IDX(policies, i, const char *);
+            policy = ssl_policy_lookup(p, name);
+            if (policy) {
+                mrg = ssl_config_perdir_merge(p, policy->dc, dc);
+                /* apply in place */
+                memcpy(dc, mrg, sizeof(*dc));
+            }
+            else {
+                dc->error_policy = name;
+                break;
+                /* report error policies in post_config */
+            }
+        }
+    }
+}
+
 /*
  *  Configuration functions for particular directives
  */
@@ -588,6 +909,7 @@
     ssl_randseed_t *seed;
     int arg2len = strlen(arg2);
 
+    /* replace: check_no_policy_and(flags) */
     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
         return err;
     }
@@ -2057,3 +2379,4 @@
     }
 
 }
+
Index: modules/ssl/ssl_engine_init.c
===================================================================
--- modules/ssl/ssl_engine_init.c	(revision 1804998)
+++ modules/ssl/ssl_engine_init.c	(working copy)
@@ -280,6 +280,13 @@
             sc->fips = FALSE;
         }
 #endif
+
+        if (sc->error_policy) {
+            rv = ssl_policy_lookup(p, sc->error_policy)? APR_EGENERAL : APR_ENOENT;
+            ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO() 
+                         "Applying SSLPolicy '%s'", sc->error_policy);
+            return rv;
+        }
     }
 
 #if APR_HAS_THREADS && MODSSL_USE_OPENSSL_PRE_1_1_API
Index: modules/ssl/ssl_private.h
===================================================================
--- modules/ssl/ssl_private.h	(revision 1804998)
+++ modules/ssl/ssl_private.h	(working copy)
@@ -586,6 +586,7 @@
     apr_global_mutex_t   *stapling_cache_mutex;
     apr_global_mutex_t   *stapling_refresh_mutex;
 #endif
+
 } SSLModConfigRec;
 
 /** Structure representing configured filenames for certs and keys for
@@ -736,6 +737,9 @@
     BOOL             compression;
 #endif
     BOOL             session_tickets;
+    
+    apr_array_header_t *policies;      /* policy that shall be applied to this config */
+    const char      *error_policy;     /* error in policy merge, bubble up */
 };
 
 /**
@@ -758,8 +762,20 @@
     modssl_ctx_t *proxy;
     BOOL          proxy_enabled;
     BOOL          proxy_post_config;
+
+    apr_array_header_t *policies;      /* policy that shall be applied to this config */
+    const char      *error_policy;     /* error in policy merge, bubble up */
 };
 
+typedef struct SSLPolicyRec SSLPolicyRec;
+struct SSLPolicyRec {
+    const char *name;
+    SSLSrvConfigRec *sc;
+    SSLDirConfigRec *dc;
+};
+
+SSLPolicyRec *ssl_policy_lookup(apr_pool_t *pool, const char *name);
+
 /**
  *  function prototypes
  */
@@ -777,6 +793,8 @@
 void        *ssl_config_perdir_merge(apr_pool_t *, void *, void *);
 void         ssl_config_proxy_merge(apr_pool_t *,
                                     SSLDirConfigRec *, SSLDirConfigRec *);
+const char  *ssl_cmd_SSLPolicyDefine(cmd_parms *, void *, const char *);
+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 *);
@@ -808,6 +826,7 @@
 const char  *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag);
 const char *ssl_cmd_SSLInsecureRenegotiation(cmd_parms *cmd, void *dcfg, int flag);
 
+const char  *ssl_cmd_SSLProxyPolicyApply(cmd_parms *, void *, const char *);
 const char  *ssl_cmd_SSLProxyEngine(cmd_parms *cmd, void *dcfg, int flag);
 const char  *ssl_cmd_SSLProxyProtocol(cmd_parms *, void *, const char *);
 const char  *ssl_cmd_SSLProxyCipherSuite(cmd_parms *, void *, const char *);
