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 2017/09/05 13:10:11 UTC

svn commit: r1807347 - in /httpd/httpd/trunk: ./ modules/md/

Author: icing
Date: Tue Sep  5 13:10:11 2017
New Revision: 1807347

URL: http://svn.apache.org/viewvc?rev=1807347&view=rev
Log:
On the trunk:

  *) mod_md: v0.9.1:
     - various fixes in MDRenewWindow handling when specifying percent. Serialization changed. If 
       someone already used percent configurations, it is advised to change these to a new value,
       reload and change back to the wanted ones.
     - various fixes in handling of MDPrivateKeys when specifying 2048 bits (the default) explicitly.
     - mod_md version removed from top level md_store.json file. The store has its own format version
       to facilitate upgrades.
 

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/modules/md/md.h
    httpd/httpd/trunk/modules/md/md_core.c
    httpd/httpd/trunk/modules/md/md_crypt.c
    httpd/httpd/trunk/modules/md/md_crypt.h
    httpd/httpd/trunk/modules/md/md_reg.c
    httpd/httpd/trunk/modules/md/md_reg.h
    httpd/httpd/trunk/modules/md/md_store_fs.c
    httpd/httpd/trunk/modules/md/md_version.h
    httpd/httpd/trunk/modules/md/mod_md.c
    httpd/httpd/trunk/modules/md/mod_md_config.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Tue Sep  5 13:10:11 2017
@@ -1,6 +1,15 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) mod_md: v0.9.1:
+     - various fixes in MDRenewWindow handling when specifying percent. Serialization changed. If 
+       someone already used percent configurations, it is advised to change these to a new value,
+       reload and change back to the wanted ones.
+     - various fixes in handling of MDPrivateKeys when specifying 2048 bits (the default) explicitly.
+     - mod_md version removed from top level md_store.json file. The store has its own format version
+       to facilitate upgrades.
+    [Stefan Eissing]
+
   *) mod_http2: DoS flow control protection is less agressive as long as active tasks stay
      below worker capacity. Intended to fix problems with media streaming. [Stefan Eissing]
      

Modified: httpd/httpd/trunk/modules/md/md.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md.h?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md.h (original)
+++ httpd/httpd/trunk/modules/md/md.h Tue Sep  5 13:10:11 2017
@@ -28,7 +28,9 @@ struct md_srv_conf_t;
 struct md_pkey_spec_t;
 
 #define MD_TLSSNI01_DNS_SUFFIX     ".acme.invalid"
-#define MD_PKEY_RSA_BITS_DEF       2048U
+
+#define MD_PKEY_RSA_BITS_MIN       2048
+#define MD_PKEY_RSA_BITS_DEF       2048
 
 typedef enum {
     MD_S_UNKNOWN,                   /* MD has not been analysed yet */
@@ -121,7 +123,7 @@ struct md_t {
 #define MD_KEY_PKEY             "privkey"
 #define MD_KEY_PROTO            "proto"
 #define MD_KEY_REGISTRATION     "registration"
-#define MD_KEY_RENEW_NORM       "renew-norm"
+#define MD_KEY_RENEW            "renew"
 #define MD_KEY_RENEW_WINDOW     "renew-window"
 #define MD_KEY_RESOURCE         "resource"
 #define MD_KEY_STATE            "state"
@@ -237,6 +239,11 @@ md_t *md_merge(apr_pool_t *p, const md_t
 struct md_json_t *md_to_json (const md_t *md, apr_pool_t *p);
 md_t *md_from_json(struct md_json_t *json, apr_pool_t *p);
 
+/**
+ * Determine if MD should renew its cert (if it has one)
+ */
+int md_should_renew(const md_t *md);
+
 /**************************************************************************************************/
 /* domain credentials */
 

Modified: httpd/httpd/trunk/modules/md/md_core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_core.c?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_core.c (original)
+++ httpd/httpd/trunk/modules/md/md_core.c Tue Sep  5 13:10:11 2017
@@ -201,6 +201,33 @@ md_t *md_create(apr_pool_t *p, apr_array
     return md;
 }
 
+int md_should_renew(const md_t *md) 
+{
+    apr_time_t now = apr_time_now();
+
+    if (md->expires <= now) {
+        return 1;
+    }
+    else if (md->expires > 0) {
+        apr_interval_time_t renew_win, left, life;
+        
+        renew_win = md->renew_window;
+        if (md->renew_norm > 0 
+            && md->renew_norm > renew_win
+            && md->expires > md->valid_from) {
+            /* Calc renewal days as fraction of cert lifetime - if known */
+            life = md->expires - md->valid_from; 
+            renew_win = (apr_time_t)(life * ((double)renew_win / md->renew_norm));
+        }
+        
+        left = md->expires - now;
+        if (left <= renew_win) {
+            return 1;
+        }                
+    }
+    return 0;
+}
+
 /**************************************************************************************************/
 /* lifetime */
 
@@ -304,12 +331,13 @@ md_json_t *md_to_json(const md_t *md, ap
             md_json_sets(ts, json, MD_KEY_CERT, MD_KEY_VALID_FROM, NULL);
         }
         if (md->renew_norm > 0) {
-            md_json_setl((long)apr_time_sec(md->renew_norm), json, MD_KEY_RENEW_NORM, NULL);
-            md_json_setl((long)apr_time_sec(md->renew_window), json, MD_KEY_RENEW_WINDOW, NULL);
+            md_json_sets(apr_psprintf(p, "%ld%%", (long)(md->renew_window * 100L / md->renew_norm)), 
+                                      json, MD_KEY_RENEW_WINDOW, NULL);
         }
         else {
             md_json_setl((long)apr_time_sec(md->renew_window), json, MD_KEY_RENEW_WINDOW, NULL);
         }
+        md_json_setb(md_should_renew(md), json, MD_KEY_RENEW, NULL);
         if (md->ca_challenges && md->ca_challenges->nelts > 0) {
             apr_array_header_t *na;
             na = md_array_str_compact(p, md->ca_challenges, 0);
@@ -348,8 +376,18 @@ md_t *md_from_json(md_json_t *json, apr_
         if (s && *s) {
             md->valid_from = apr_date_parse_rfc(s);
         }
-        md->renew_norm = apr_time_from_sec(md_json_getl(json, MD_KEY_RENEW_NORM, NULL));
+        md->renew_norm = 0;
         md->renew_window = apr_time_from_sec(md_json_getl(json, MD_KEY_RENEW_WINDOW, NULL));
+        if (md->renew_window <= 0) {
+            const char *s = md_json_gets(json, MD_KEY_RENEW_WINDOW, NULL);
+            if (s && strchr(s, '%')) {
+                int percent = atoi(s);
+                if (0 < percent && percent < 100) {
+                    md->renew_norm = apr_time_from_sec(100 * MD_SECS_PER_DAY);
+                    md->renew_window = apr_time_from_sec(percent * MD_SECS_PER_DAY);
+                }
+            }
+        }
         if (md_json_has_key(json, MD_KEY_CA, MD_KEY_CHALLENGES, NULL)) {
             md->ca_challenges = apr_array_make(p, 5, sizeof(const char*));
             md_json_dupsa(md->ca_challenges, p, json, MD_KEY_CA, MD_KEY_CHALLENGES, NULL);

Modified: httpd/httpd/trunk/modules/md/md_crypt.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_crypt.c?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_crypt.c (original)
+++ httpd/httpd/trunk/modules/md/md_crypt.c Tue Sep  5 13:10:11 2017
@@ -191,7 +191,7 @@ md_json_t *md_pkey_spec_to_json(const md
                 break;
             case MD_PKEY_TYPE_RSA:
                 md_json_sets("RSA", json, MD_KEY_TYPE, NULL);
-                if (spec->params.rsa.bits > 2048) {
+                if (spec->params.rsa.bits >= MD_PKEY_RSA_BITS_MIN) {
                     md_json_setl(spec->params.rsa.bits, json, MD_KEY_BITS, NULL);
                 }
                 break;
@@ -217,14 +217,36 @@ md_pkey_spec_t *md_pkey_spec_from_json(s
         else if (!apr_strnatcasecmp("RSA", s)) {
             spec->type = MD_PKEY_TYPE_RSA;
             l = md_json_getl(json, MD_KEY_BITS, NULL);
-            if (l > 2048) {
+            if (l >= MD_PKEY_RSA_BITS_MIN) {
                 spec->params.rsa.bits = (unsigned int)l;
             }
+            else {
+                spec->params.rsa.bits = MD_PKEY_RSA_BITS_DEF;
+            }
         }
     }
     return spec;
 }
 
+int md_pkey_spec_eq(md_pkey_spec_t *spec1, md_pkey_spec_t *spec2)
+{
+    if (spec1 == spec2) {
+        return 1;
+    }
+    if (spec1 && spec2 && spec1->type == spec2->type) {
+        switch (spec1->type) {
+            case MD_PKEY_TYPE_DEFAULT:
+                return 1;
+            case MD_PKEY_TYPE_RSA:
+                if (spec1->params.rsa.bits == spec2->params.rsa.bits) {
+                    return 1;
+                }
+                break;
+        }
+    }
+    return 0;
+}
+
 static md_pkey_t *make_pkey(apr_pool_t *p) 
 {
     md_pkey_t *pkey = apr_pcalloc(p, sizeof(*pkey));
@@ -363,7 +385,7 @@ static apr_status_t gen_rsa(md_pkey_t **
         rv = APR_SUCCESS;
     }
     else {
-        md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p, "unable to generate new key"); 
+        md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p, "error generate pkey RSA %d", bits); 
         *ppkey = NULL;
         rv = APR_EGENERAL;
     }

Modified: httpd/httpd/trunk/modules/md/md_crypt.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_crypt.h?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_crypt.h (original)
+++ httpd/httpd/trunk/modules/md/md_crypt.h Tue Sep  5 13:10:11 2017
@@ -80,6 +80,7 @@ void *md_pkey_get_EVP_PKEY(struct md_pke
 
 struct md_json_t *md_pkey_spec_to_json(const md_pkey_spec_t *spec, apr_pool_t *p);
 md_pkey_spec_t *md_pkey_spec_from_json(struct md_json_t *json, apr_pool_t *p);
+int md_pkey_spec_eq(md_pkey_spec_t *spec1, md_pkey_spec_t *spec2);
 
 /**************************************************************************************************/
 /* X509 certificates */

Modified: httpd/httpd/trunk/modules/md/md_reg.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_reg.c?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_reg.c (original)
+++ httpd/httpd/trunk/modules/md/md_reg.c Tue Sep  5 13:10:11 2017
@@ -151,7 +151,7 @@ static apr_status_t check_values(md_reg_
 /**************************************************************************************************/
 /* state assessment */
 
-static apr_status_t state_init(md_reg_t *reg, apr_pool_t *p, md_t *md)
+static apr_status_t state_init(md_reg_t *reg, apr_pool_t *p, md_t *md, int save_changes)
 {
     md_state_t state = MD_S_UNKNOWN;
     const md_creds_t *creds;
@@ -166,7 +166,7 @@ static apr_status_t state_init(md_reg_t
             md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, 
                           "md{%s}: incomplete, without private key", md->name);
         }
-        else if (!creds->pubcert) {
+        else if (!creds->cert) {
             md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, 
                           "md{%s}: incomplete, has key but no certificate", md->name);
         }
@@ -216,41 +216,24 @@ out:
         state = MD_S_ERROR;
         md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, "md{%s}: error", md->name);
     }
+    
+    if (save_changes && md->state == state
+        && md->valid_from == valid_from && md->expires == expires) {
+        save_changes = 0;
+    }
     md->state = state;
     md->valid_from = valid_from;
     md->expires = expires;
-    return rv;
-}
-
-static apr_status_t state_vinit(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
-{
-    md_reg_t *reg = baton;
-    md_t *md = va_arg(ap, md_t *);
-    
-    return state_init(reg, p, md);
-}
-
-static apr_status_t md_state_init(md_reg_t *reg, md_t *md, apr_pool_t *p)
-{
-    return md_util_pool_vdo(state_vinit, reg, p, md, NULL);
-}
-
-static md_t *state_check(md_reg_t *reg, md_t *md, apr_pool_t *p) 
-{
-    if (md) {
-        int ostate = md->state;
-        if (APR_SUCCESS == state_init(reg, p, md) && md->state != ostate) {
-            md_save(reg->store, p, MD_SG_DOMAINS, md, 0);
-        }
+    if (save_changes && APR_SUCCESS == rv) {
+        return md_save(reg->store, p, MD_SG_DOMAINS, md, 0);
     }
-    return md;
+    return rv;
 }
 
 apr_status_t md_reg_assess(md_reg_t *reg, md_t *md, int *perrored, int *prenew, apr_pool_t *p)
 {
     int renew = 0;
     int errored = 0;
-    apr_time_t now = apr_time_now();
     
     switch (md->state) {
         case MD_S_UNKNOWN:
@@ -271,31 +254,13 @@ apr_status_t md_reg_assess(md_reg_t *reg
                              "md(%s): looks complete, but has unknown expiration date.", md->name);
                 errored = 1;
             }
-            else if (md->expires <= now) {
+            else if (md->expires <= apr_time_now()) {
                 /* Maybe we hibernated in the meantime? */
                 md->state = MD_S_EXPIRED;
                 renew = 1;
             }
             else {
-                apr_interval_time_t renew_win, left, life;
-
-                renew_win = md->renew_window;
-                if (md->renew_norm > 0 
-                    && md->renew_norm > renew_win
-                    && md->expires > md->valid_from) {
-                    /* Calc renewal days as fraction of cert lifetime - if known */
-                    life = md->expires - md->valid_from; 
-                    renew_win = life * md->renew_norm / renew_win;
-                }
-                
-                left = md->expires - now;
-                if (left <= renew_win) {
-                    int days_left = (int)(apr_time_sec(left) / MD_SECS_PER_DAY);
-                    md_log_perror( MD_LOG_MARK, MD_LOG_DEBUG, 0, p,  
-                                  "md(%s): %d days to expiry, attempt renewal", 
-                                  md->name, days_left);
-                    renew = 1;
-                }                
+                renew = md_should_renew(md);
             }
             break;
         case MD_S_INCOMPLETE:
@@ -326,7 +291,7 @@ static int reg_md_iter(void *baton, md_s
     reg_do_ctx *ctx = baton;
     
     if (!ctx->exclude || strcmp(ctx->exclude, md->name)) {
-        md = state_check(ctx->reg, (md_t*)md, ptemp);
+        state_init(ctx->reg, ptemp, (md_t*)md, 1);
         return ctx->cb(ctx->baton, ctx->reg, md);
     }
     return 1;
@@ -357,7 +322,8 @@ md_t *md_reg_get(md_reg_t *reg, const ch
     md_t *md;
     
     if (APR_SUCCESS == md_load(reg->store, MD_SG_DOMAINS, name, &md, p)) {
-        return state_check(reg, md, p);
+        state_init(reg, p, md, 1);
+        return md;
     }
     return NULL;
 }
@@ -386,12 +352,15 @@ md_t *md_reg_find(md_reg_t *reg, const c
     ctx.md = NULL;
     
     md_reg_do(find_domain, &ctx, reg, p);
-    return state_check(reg, (md_t*)ctx.md, p);
+    if (ctx.md) {
+        state_init(reg, p, ctx.md, 1);
+    }
+    return ctx.md;
 }
 
 typedef struct {
     const md_t *md_checked;
-    const md_t *md;
+    md_t *md;
     const char *s;
 } find_overlap_ctx;
 
@@ -420,7 +389,10 @@ md_t *md_reg_find_overlap(md_reg_t *reg,
     if (pdomain && ctx.s) {
         *pdomain = ctx.s;
     }
-    return state_check(reg, (md_t*)ctx.md, p);
+    if (ctx.md) {
+        state_init(reg, p, ctx.md, 1);
+    }
+    return ctx.md;
 }
 
 apr_status_t md_reg_get_cred_files(md_reg_t *reg, const md_t *md, apr_pool_t *p,
@@ -447,7 +419,7 @@ static apr_status_t p_md_add(void *baton
     md = va_arg(ap, md_t *);
     mine = md_clone(ptemp, md);
     if (APR_SUCCESS == (rv = check_values(reg, ptemp, md, MD_UPD_ALL))
-        && APR_SUCCESS == (rv = md_state_init(reg, mine, ptemp))
+        && APR_SUCCESS == (rv = state_init(reg, ptemp, mine, 0))
         && APR_SUCCESS == (rv = md_save(reg->store, p, MD_SG_DOMAINS, mine, 1))) {
     }
     return rv;
@@ -525,9 +497,16 @@ static apr_status_t p_md_update(void *ba
         nmd->ca_challenges = (updates->ca_challenges? 
                               apr_array_copy(p, updates->ca_challenges) : NULL);
     }
+    if (MD_UPD_PKEY_SPEC & fields) {
+        md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update pkey spec: %s", name);
+        nmd->pkey_spec = NULL;
+        if (updates->pkey_spec) {
+            nmd->pkey_spec = apr_pmemdup(p, updates->pkey_spec, sizeof(md_pkey_spec_t));
+        }
+    }
     
     if (fields && APR_SUCCESS == (rv = md_save(reg->store, p, MD_SG_DOMAINS, nmd, 0))) {
-        rv = md_state_init(reg, nmd, ptemp);
+        rv = state_init(reg, ptemp, nmd, 0);
     }
     return rv;
 }
@@ -792,6 +771,13 @@ apr_status_t md_reg_sync(md_reg_t *reg,
                     smd->ca_challenges = NULL;
                     fields |= MD_UPD_CA_CHALLENGES;
                 }
+                if (!md_pkey_spec_eq(md->pkey_spec, smd->pkey_spec)) {
+                    fields |= MD_UPD_PKEY_SPEC;
+                    smd->pkey_spec = NULL;
+                    if (md->pkey_spec) {
+                        smd->pkey_spec = apr_pmemdup(p, md->pkey_spec, sizeof(md_pkey_spec_t));
+                    }
+                }
                 
                 if (fields) {
                     rv = md_reg_update(reg, ptemp, smd->name, smd, fields);

Modified: httpd/httpd/trunk/modules/md/md_reg.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_reg.h?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_reg.h (original)
+++ httpd/httpd/trunk/modules/md/md_reg.h Tue Sep  5 13:10:11 2017
@@ -91,7 +91,8 @@ int md_reg_do(md_reg_do_cb *cb, void *ba
 #define MD_UPD_DRIVE_MODE   0x0080
 #define MD_UPD_RENEW_WINDOW 0x0100
 #define MD_UPD_CA_CHALLENGES 0x0200
-#define MD_UPD_ALL          0x7FFF
+#define MD_UPD_PKEY_SPEC    0x0400
+#define MD_UPD_ALL          0x7FFFFFFF
 
 /**
  * Update the given fields for the managed domain. Take the new

Modified: httpd/httpd/trunk/modules/md/md_store_fs.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_store_fs.c?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_store_fs.c (original)
+++ httpd/httpd/trunk/modules/md/md_store_fs.c Tue Sep  5 13:10:11 2017
@@ -37,7 +37,7 @@
 /**************************************************************************************************/
 /* file system based implementation of md_store_t */
 
-#define MD_STORE_VERSION        2
+#define MD_STORE_VERSION        3
 
 typedef struct {
     apr_fileperms_t dir;
@@ -99,7 +99,6 @@ static apr_status_t init_store_file(md_s
     unsigned char *key;
     apr_status_t rv;
     
-    md_json_sets(MOD_MD_VERSION, json, MD_KEY_VERSION, NULL);
     md_json_setn(MD_STORE_VERSION, json, MD_KEY_STORE, MD_KEY_VERSION, NULL);
 
     s_fs->key_len = FS_STORE_KLEN;
@@ -217,9 +216,13 @@ static apr_status_t read_store_file(md_s
         /* Need to migrate format? */
         if (store_version < MD_STORE_VERSION) {
             if (store_version <= 1.0) {
-                md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "migrating store v1.0 -> v1.1");
+                md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "migrating store v1 -> v2");
                 rv = upgrade_from_1_0(s_fs, p, ptemp);
             }
+            if (store_version <= 2.0) {
+                md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "migrating store v2 -> v3");
+                md_json_del(json, MD_KEY_VERSION, NULL);
+            }
             
             if (APR_SUCCESS == rv) {
                 md_json_setn(MD_STORE_VERSION, json, MD_KEY_STORE, MD_KEY_VERSION, NULL);

Modified: httpd/httpd/trunk/modules/md/md_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_version.h?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_version.h (original)
+++ httpd/httpd/trunk/modules/md/md_version.h Tue Sep  5 13:10:11 2017
@@ -26,7 +26,7 @@
  * @macro
  * Version number of the md module as c string
  */
-#define MOD_MD_VERSION "0.9.0"
+#define MOD_MD_VERSION "0.9.1-git"
 
 /**
  * @macro
@@ -34,7 +34,7 @@
  * release. This is a 24 bit number with 8 bits for major number, 8 bits
  * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
  */
-#define MOD_MD_VERSION_NUM 0x000900
+#define MOD_MD_VERSION_NUM 0x000901
 
 #define MD_EXPERIMENTAL 0
 #define MD_ACME_DEF_URL    "https://acme-v01.api.letsencrypt.org/directory"

Modified: httpd/httpd/trunk/modules/md/mod_md.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md.c?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md.c (original)
+++ httpd/httpd/trunk/modules/md/mod_md.c Tue Sep  5 13:10:11 2017
@@ -78,10 +78,8 @@ static void md_merge_srv(md_t *md, md_sr
     if (md->drive_mode == MD_DRIVE_DEFAULT) {
         md->drive_mode = md_config_geti(md->sc, MD_CONFIG_DRIVE_MODE);
     }
-    if (md->renew_norm <= 0) {
+    if (md->renew_norm <= 0 && md->renew_window <= 0) {
         md->renew_norm = md_config_get_interval(md->sc, MD_CONFIG_RENEW_NORM);
-    }
-    if (md->renew_window <= 0) {
         md->renew_window = md_config_get_interval(md->sc, MD_CONFIG_RENEW_WINDOW);
     }
     if (md->transitive < 0) {

Modified: httpd/httpd/trunk/modules/md/mod_md_config.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md_config.c?rev=1807347&r1=1807346&r2=1807347&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md_config.c (original)
+++ httpd/httpd/trunk/modules/md/mod_md_config.c Tue Sep  5 13:10:11 2017
@@ -496,8 +496,8 @@ static const char *md_config_set_renew_w
     else {
         switch (percentage_parse(value, &percent)) {
             case APR_SUCCESS:
-                config->renew_norm = 100;
-                config->renew_window = percent;
+                config->renew_norm = apr_time_from_sec(100 * MD_SECS_PER_DAY);
+                config->renew_window = apr_time_from_sec(percent * MD_SECS_PER_DAY);
                 return NULL;
             case APR_BADARG:
                 return "MDRenewWindow as percent must be less than 100";
@@ -630,10 +630,11 @@ static const char *md_config_set_pkeys(c
         }
         else if (argc == 2) {
             bits = (int)apr_atoi64(argv[1]);
-            if (bits < 2048 || bits >= INT_MAX) {
-                return "must be a 2048 or higher in order to be considered safe. "
-                "Too large a value will slow down everything. Larger then 4096 probably does "
-                "not make sense unless quantum cryptography really changes spin.";
+            if (bits < MD_PKEY_RSA_BITS_MIN || bits >= INT_MAX) {
+                return apr_psprintf(cmd->pool, "must be %d or higher in order to be considered "
+                "safe. Too large a value will slow down everything. Larger then 4096 probably does "
+                "not make sense unless quantum cryptography really changes spin.", 
+                MD_PKEY_RSA_BITS_MIN);
             }
         }
         else {