httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ic...@apache.org
Subject svn commit: r1806939 [1/2] - in /httpd/httpd/trunk: ./ docs/manual/mod/ modules/md/ modules/ssl/
Date Fri, 01 Sep 2017 12:11:39 GMT
Author: icing
Date: Fri Sep  1 12:11:38 2017
New Revision: 1806939

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

mod_md: v0.8.1 from github, new feats in CHANGES


Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/docs/manual/mod/mod_md.xml
    httpd/httpd/trunk/modules/md/md.h
    httpd/httpd/trunk/modules/md/md_acme.c
    httpd/httpd/trunk/modules/md/md_acme.h
    httpd/httpd/trunk/modules/md/md_acme_acct.c
    httpd/httpd/trunk/modules/md/md_acme_acct.h
    httpd/httpd/trunk/modules/md/md_acme_authz.c
    httpd/httpd/trunk/modules/md/md_acme_authz.h
    httpd/httpd/trunk/modules/md/md_acme_drive.c
    httpd/httpd/trunk/modules/md/md_cmd_reg.c
    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_curl.c
    httpd/httpd/trunk/modules/md/md_reg.c
    httpd/httpd/trunk/modules/md/md_store.c
    httpd/httpd/trunk/modules/md/md_store.h
    httpd/httpd/trunk/modules/md/md_store_fs.c
    httpd/httpd/trunk/modules/md/md_util.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
    httpd/httpd/trunk/modules/md/mod_md_config.h
    httpd/httpd/trunk/modules/md/mod_md_os.c
    httpd/httpd/trunk/modules/md/mod_md_os.h
    httpd/httpd/trunk/modules/ssl/ssl_engine_init.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Fri Sep  1 12:11:38 2017
@@ -1,7 +1,29 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
-  *) mod_md: v0.7.0:
+  *) mod_md: v0.8.1:
+     - New directive ```MDPrivateKeys``` to specify the type and parameter to private key generation.
+       Currently only 'RSA' is supported as type with an option number of bits >= 2048 as parameter.
+       Simple test cases for config handling added.
+     - Private RSA keys are now generated with 2048 bits by default. Use ```MDPrivateKeys``` for
+       higher security. 
+     - IMPORTANT: store format change. The following changes will be made to an existing md store on 
+       first start with a new version (be it by mod_md in the server or a run by a new 'a2md'):
+         - pkey.pem will be renamed to privkey.pem
+         - cert.pem and chain.pem will be concatenated to pubcert.pem. The former files will remain,
+           but no longer be used. They will disappear on next renewal.
+       ADVICE: If the current store data is vital to you, please make a backup first!
+     - Fixed test case clearing of store to keep key alive, enabling true random store key again.
+     - Removed pun "Something, like certbot" from the User-Agent request header. Refs issue #34
+     - Cleaned up reporting of missing/mismatched MDCertificateAgreement in the logs. This will
+       no longer trigger early retries.
+     - badNonce encounters are no longer reported as errors. Retries are attempted now silently.
+       Refs github issue #35
+     - new default MDRenewWindow. Instead of 14 days, the default is now a third before the end of
+       the certificates lifetime. For the usual 90 days of Let's Encrypt certificates, this makes
+       an effective renewal window of 30 days - as recommended by LE. Refs issue #30
+     - Enabled conversion warnings if supported by compiler, eliminated several signed/unsigned
+       warnings.
      - LIVE: the real Let's Encrypt CA is now live by default! If you need to experiment, configure
            MDCertificateAuthority https://acme-staging.api.letsencrypt.org/directory   
      - When existing, complete certificates are renewed, the activation of the new ones is

Modified: httpd/httpd/trunk/docs/manual/mod/mod_md.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_md.xml?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/docs/manual/mod/mod_md.xml (original)
+++ httpd/httpd/trunk/docs/manual/mod/mod_md.xml Fri Sep  1 12:11:38 2017
@@ -342,6 +342,40 @@ MDPortMap 80:- 443:5002
     </directivesynopsis>
 
     <directivesynopsis>
+        <name>MDPrivateKeys</name>
+        <description></description>
+        <syntax>MDPrivateKeys type [ params... ]</syntax>
+        <default>MDPrivateKeys RSA 2048</default>
+        <contextlist>
+            <context>server config</context>
+        </contextlist>
+        <usage>
+            <p>
+                Defines what kind of private keys are generated for a managed domain and with
+                what parameters. The only supported type right now is 'RSA' and the only parameter
+                it takes is the number of bits used for the key.
+            </p><p>
+                The current (2017) recommendation is at least 2048 bits and a smaller number is
+                not accepted here. Higher numbers offer longer security, but are computationally more 
+                expensive, e.g. increase the load on your server. That might or might not be an
+                issue for you.
+            </p><p>
+                Other key types will be defined in the future.
+            </p>
+            <example><title>Example</title>
+                <highlight language="config">
+MDPrivateKeys RSA 3072
+                </highlight>
+            </example>
+            <p>
+                Please note that this setting only has an effect on new keys. Any existing
+                private key you have remains unaffected. Also, this only affects private keys
+                generated for certificates. ACME account keys are unaffected by this.
+            </p>
+        </usage>
+    </directivesynopsis>
+
+    <directivesynopsis>
         <name>MDRenewWindow</name>
         <description></description>
         <syntax>MDRenewWindow duration</syntax>

Modified: httpd/httpd/trunk/modules/md/md.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md.h?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md.h (original)
+++ httpd/httpd/trunk/modules/md/md.h Fri Sep  1 12:11:38 2017
@@ -25,8 +25,10 @@ struct md_cert_t;
 struct md_pkey_t;
 struct md_store_t;
 struct md_srv_conf_t;
+struct md_pkey_spec_t;
 
 #define MD_TLSSNI01_DNS_SUFFIX     ".acme.invalid"
+#define MD_PKEY_RSA_BITS_DEF       2048U
 
 typedef enum {
     MD_S_UNKNOWN,                   /* MD has not been analysed yet */
@@ -34,6 +36,7 @@ typedef enum {
     MD_S_COMPLETE,                  /* MD has all necessary information, can go live */
     MD_S_EXPIRED,                   /* MD is complete, but credentials have expired */
     MD_S_ERROR,                     /* MD data is flawed, unable to be processed as is */ 
+    MD_S_MISSING,                   /* MD is missing config information, cannot proceed */
 } md_state_t;
 
 typedef enum {
@@ -70,7 +73,9 @@ struct md_t {
 
     int transitive;                 /* != 0 iff VirtualHost names/aliases are auto-added */
     int drive_mode;                 /* mode of obtaining credentials */
+    struct md_pkey_spec_t *pkey_spec;/* specification for generating new private keys */
     int must_staple;                /* certificates should set the OCSP Must Staple extension */
+    apr_interval_time_t renew_norm; /* if > 0, normalized cert lifetime */
     apr_interval_time_t renew_window;/* time before expiration that starts renewal */
     
     const char *ca_url;             /* url of CA certificate service */
@@ -91,6 +96,7 @@ struct md_t {
 
 #define MD_KEY_ACCOUNT          "account"
 #define MD_KEY_AGREEMENT        "agreement"
+#define MD_KEY_BITS             "bits"
 #define MD_KEY_CA               "ca"
 #define MD_KEY_CA_URL           "ca-url"
 #define MD_KEY_CERT             "cert"
@@ -112,8 +118,10 @@ struct md_t {
 #define MD_KEY_KEYAUTHZ         "keyAuthorization"
 #define MD_KEY_LOCATION         "location"
 #define MD_KEY_NAME             "name"
+#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_WINDOW     "renew-window"
 #define MD_KEY_RESOURCE         "resource"
 #define MD_KEY_STATE            "state"
@@ -129,7 +137,8 @@ struct md_t {
 #define MD_KEY_VERSION          "version"
 
 #define MD_FN_MD                "md.json"
-#define MD_FN_PKEY              "pkey.pem"
+#define MD_FN_PRIVKEY           "privkey.pem"
+#define MD_FN_PUBCERT           "pubcert.pem"
 #define MD_FN_CERT              "cert.pem"
 #define MD_FN_CHAIN             "chain.pem"
 #define MD_FN_HTTPD_JSON        "httpd.json"
@@ -230,9 +239,9 @@ md_t *md_from_json(struct md_json_t *jso
 
 typedef struct md_creds_t md_creds_t;
 struct md_creds_t {
+    struct md_pkey_t *privkey;
+    struct apr_array_header_t *pubcert;    /* complete md_cert* chain */
     struct md_cert_t *cert;
-    struct md_pkey_t *pkey;
-    struct apr_array_header_t *chain;      /* list of md_cert* */
     int expired;
 };
 

Modified: httpd/httpd/trunk/modules/md/md_acme.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_acme.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_acme.c (original)
+++ httpd/httpd/trunk/modules/md/md_acme.c Fri Sep  1 12:11:38 2017
@@ -111,9 +111,8 @@ apr_status_t md_acme_create(md_acme_t **
     acme = apr_pcalloc(p, sizeof(*acme));
     acme->url = url;
     acme->p = p;
-    acme->user_agent = apr_psprintf(p, "%s mod_md/%s (Something, like certbot)", 
+    acme->user_agent = apr_psprintf(p, "%s mod_md/%s", 
                                     base_product, MOD_MD_VERSION);
-    acme->pkey_bits = 4096;
     acme->max_retries = 3;
     
     if (APR_SUCCESS != (rv = apr_uri_parse(p, url, &uri_parsed))) {
@@ -260,9 +259,15 @@ static apr_status_t inspect_problem(md_a
             ptype = md_json_gets(problem, "type", NULL); 
             pdetail = md_json_gets(problem, "detail", NULL);
             req->rv = problem_status_get(ptype);
-             
-            md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, req->rv, req->p,
-                          "acme problem %s: %s", ptype, pdetail);
+            
+            if (APR_STATUS_IS_EAGAIN(req->rv)) {
+                md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, req->rv, req->p,
+                              "acme reports %s: %s", ptype, pdetail);
+            }
+            else {
+                md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, req->rv, req->p,
+                              "acme problem %s: %s", ptype, pdetail);
+            }
             return req->rv;
         }
     }

Modified: httpd/httpd/trunk/modules/md/md_acme.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_acme.h?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_acme.h (original)
+++ httpd/httpd/trunk/modules/md/md_acme.h Fri Sep  1 12:11:38 2017
@@ -62,7 +62,6 @@ struct md_acme_t {
     
     const char *nonce;
     int max_retries;
-    unsigned int pkey_bits;
 };
 
 /**
@@ -126,8 +125,12 @@ apr_status_t md_acme_agree(md_acme_t *ac
  * accounces the Tos URL it wants. If this is equal to the agreement specified,
  * the server is notified of this. If the server requires a ToS that the account
  * thinks it has already given, it is resend.
+ *
+ * If an agreement is required, different from the current one, APR_INCOMPLETE is
+ * returned and the agreement url is returned in the parameter.
  */
-apr_status_t md_acme_check_agreement(md_acme_t *acme, apr_pool_t *p, const char *agreement);
+apr_status_t md_acme_check_agreement(md_acme_t *acme, apr_pool_t *p, 
+                                     const char *agreement, const char **prequired);
 
 /**
  * Get the ToS agreement for current account.

Modified: httpd/httpd/trunk/modules/md/md_acme_acct.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_acme_acct.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_acme_acct.c (original)
+++ httpd/httpd/trunk/modules/md/md_acme_acct.c Fri Sep  1 12:11:38 2017
@@ -327,6 +327,7 @@ static apr_status_t acct_register(md_acm
     apr_status_t rv;
     md_pkey_t *pkey;
     const char *err = NULL, *uri;
+    md_pkey_spec_t spec;
     int i;
     
     md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "create new account");
@@ -347,7 +348,10 @@ static apr_status_t acct_register(md_acm
         }
     }
     
-    if (APR_SUCCESS == (rv = md_pkey_gen_rsa(&pkey, acme->p, acme->pkey_bits))
+    spec.type = MD_PKEY_TYPE_RSA;
+    spec.params.rsa.bits = MD_ACME_ACCT_PKEY_BITS;
+    
+    if (APR_SUCCESS == (rv = md_pkey_gen(&pkey, acme->p, &spec))
         && APR_SUCCESS == (rv = acct_make(&acme->acct,  p, acme->url, NULL, contacts))) {
         acct_ctx_t ctx;
 
@@ -614,11 +618,13 @@ static int agreement_required(md_acme_ac
             || (acct->tos_required && strcmp(acct->tos_required, acct->agreement)));
 }
 
-apr_status_t md_acme_check_agreement(md_acme_t *acme, apr_pool_t *p, const char *agreement)
+apr_status_t md_acme_check_agreement(md_acme_t *acme, apr_pool_t *p, 
+                                     const char *agreement, const char **prequired)
 {
     apr_status_t rv = APR_SUCCESS;
     
     /* Check if (correct) Terms-of-Service for account were accepted */
+    *prequired = NULL;
     if (agreement_required(acme->acct)) {
         const char *tos = acme->acct->tos_required;
         if (!tos) {
@@ -642,10 +648,8 @@ apr_status_t md_acme_check_agreement(md_
             rv = md_acme_agree(acme, p, tos);
         }
         else {
-            md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, acme->p, 
-                          "need to accept terms-of-service <%s> for account %s", 
-                          tos, acme->acct->id);
-            rv = APR_EACCES;
+            *prequired = apr_pstrdup(p, tos);
+            rv = APR_INCOMPLETE;
         }
     }
     return rv;

Modified: httpd/httpd/trunk/modules/md/md_acme_acct.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_acme_acct.h?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_acme_acct.h (original)
+++ httpd/httpd/trunk/modules/md/md_acme_acct.h Fri Sep  1 12:11:38 2017
@@ -41,4 +41,8 @@ struct md_acme_acct_t {
 #define MD_FN_ACCOUNT           "account.json"
 #define MD_FN_ACCT_KEY          "account.pem"
 
+/* ACME account private keys are always RSA and have that many bits. Since accounts
+ * are expected to live long, better err on the safe side. */
+#define MD_ACME_ACCT_PKEY_BITS  3072
+
 #endif /* md_acme_acct_h */

Modified: httpd/httpd/trunk/modules/md/md_acme_authz.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_acme_authz.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_acme_authz.c (original)
+++ httpd/httpd/trunk/modules/md/md_acme_authz.c Fri Sep  1 12:11:38 2017
@@ -91,10 +91,10 @@ apr_status_t md_acme_authz_set_remove(md
     for (i = 0; i < set->authzs->nelts; ++i) {
         authz = APR_ARRAY_IDX(set->authzs, i, md_acme_authz_t *);
         if (!apr_strnatcasecmp(domain, authz->domain)) {
-            int n = i +1;
+            int n = i + 1;
             if (n < set->authzs->nelts) {
                 void **elems = (void **)set->authzs->elts;
-                memmove(elems + i, elems + n, set->authzs->nelts - n); 
+                memmove(elems + i, elems + n, (size_t)(set->authzs->nelts - n)); 
             }
             --set->authzs->nelts;
             return APR_SUCCESS;
@@ -292,7 +292,8 @@ static apr_status_t setup_key_authz(md_a
 }
 
 static apr_status_t cha_http_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, 
-                                      md_acme_t *acme, md_store_t *store, apr_pool_t *p)
+                                      md_acme_t *acme, md_store_t *store, 
+                                      md_pkey_spec_t *key_spec, apr_pool_t *p)
 {
     const char *data;
     apr_status_t rv;
@@ -347,7 +348,8 @@ static apr_status_t setup_cha_dns(const
 }
 
 static apr_status_t cha_tls_sni_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, 
-                                         md_acme_t *acme, md_store_t *store, apr_pool_t *p)
+                                         md_acme_t *acme, md_store_t *store, 
+                                         md_pkey_spec_t *key_spec, apr_pool_t *p)
 {
     md_cert_t *cha_cert;
     md_pkey_t *cha_key;
@@ -365,7 +367,7 @@ static apr_status_t cha_tls_sni_01_setup
     if ((APR_SUCCESS == rv && !md_cert_covers_domain(cha_cert, cha_dns)) 
         || APR_STATUS_IS_ENOENT(rv)) {
         
-        if (APR_SUCCESS != (rv = md_pkey_gen_rsa(&cha_key, p, acme->pkey_bits))) {
+        if (APR_SUCCESS != (rv = md_pkey_gen(&cha_key, p, key_spec))) {
             md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: create tls-sni-01 challgenge key",
                           authz->domain);
             goto out;
@@ -405,7 +407,8 @@ out:
 }
 
 typedef apr_status_t cha_starter(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, 
-                                 md_acme_t *acme, md_store_t *store, apr_pool_t *p);
+                                 md_acme_t *acme, md_store_t *store, 
+                                 md_pkey_spec_t *key_spec, apr_pool_t *p);
                                  
 typedef struct {
     const char *name;
@@ -449,7 +452,8 @@ static apr_status_t find_type(void *bato
 }
 
 apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, md_acme_t *acme, md_store_t *store, 
-                                   apr_array_header_t *challenges, apr_pool_t *p)
+                                   apr_array_header_t *challenges, 
+                                   md_pkey_spec_t *key_spec, apr_pool_t *p)
 {
     apr_status_t rv;
     int i;
@@ -485,7 +489,7 @@ apr_status_t md_acme_authz_respond(md_ac
     
     for (i = 0; i < CHA_TYPES_LEN; ++i) {
         if (!apr_strnatcasecmp(CHA_TYPES[i].name, fctx.accepted->type)) {
-            return CHA_TYPES[i].start(fctx.accepted, authz, acme, store, p);
+            return CHA_TYPES[i].start(fctx.accepted, authz, acme, store, key_spec, p);
         }
     }
     
@@ -560,7 +564,7 @@ md_acme_authz_t *md_acme_authz_from_json
         authz->domain = md_json_dups(p, json, MD_KEY_DOMAIN, NULL);            
         authz->location = md_json_dups(p, json, MD_KEY_LOCATION, NULL);            
         authz->dir = md_json_dups(p, json, MD_KEY_DIR, NULL);            
-        authz->state = (int)md_json_getl(json, MD_KEY_STATE, NULL);            
+        authz->state = (md_acme_authz_state_t)md_json_getl(json, MD_KEY_STATE, NULL);            
         return authz;
     }
     return NULL;
@@ -631,7 +635,7 @@ static apr_status_t p_save(void *baton,
     const char *md_name;
     int create;
     
-    group = va_arg(ap, int);
+    group = (md_store_group_t)va_arg(ap, int);
     md_name = va_arg(ap, const char *);
     set = va_arg(ap, md_acme_authz_set_t *);
     create = va_arg(ap, int);
@@ -657,7 +661,7 @@ static apr_status_t p_purge(void *baton,
     const char *md_name;
     int i;
 
-    group = va_arg(ap, int);
+    group = (md_store_group_t)va_arg(ap, int);
     md_name = va_arg(ap, const char *);
 
     if (APR_SUCCESS == md_acme_authz_set_load(store, group, md_name, &authz_set, p)) {

Modified: httpd/httpd/trunk/modules/md/md_acme_authz.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_acme_authz.h?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_acme_authz.h (original)
+++ httpd/httpd/trunk/modules/md/md_acme_authz.h Fri Sep  1 12:11:38 2017
@@ -21,6 +21,7 @@ struct md_acme_t;
 struct md_acme_acct_t;
 struct md_json_t;
 struct md_store_t;
+struct md_pkey_spec_t;
 
 typedef struct md_acme_challenge_t md_acme_challenge_t;
 
@@ -67,8 +68,8 @@ apr_status_t md_acme_authz_update(md_acm
                                   struct md_store_t *store, apr_pool_t *p);
 
 apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, struct md_acme_t *acme, 
-                                   struct md_store_t *store, 
-                                   apr_array_header_t *challenges, apr_pool_t *p);
+                                   struct md_store_t *store, apr_array_header_t *challenges, 
+                                   struct md_pkey_spec_t *key_spec, apr_pool_t *p);
 apr_status_t md_acme_authz_del(md_acme_authz_t *authz, struct md_acme_t *acme, 
                                struct md_store_t *store, apr_pool_t *p);
 

Modified: httpd/httpd/trunk/modules/md/md_acme_drive.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_acme_drive.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_acme_drive.c (original)
+++ httpd/httpd/trunk/modules/md/md_acme_drive.c Fri Sep  1 12:11:38 2017
@@ -42,9 +42,11 @@ typedef struct {
     const char *phase;
     int complete;
 
-    md_pkey_t *pkey;
-    md_cert_t *cert;
-    apr_array_header_t *chain;
+    md_pkey_t *privkey;              /* the new private key */
+    apr_array_header_t *pubcert;     /* the new certificate + chain certs */
+    
+    md_cert_t *cert;                 /* the new certificate */
+    apr_array_header_t *chain;       /* the chain certificates */
 
     md_acme_t *acme;
     md_t *md;
@@ -122,8 +124,8 @@ static apr_status_t ad_set_acct(md_proto
             goto out;
         }
     
-        if (APR_SUCCESS == (rv = md_acme_create_acct(ad->acme, d->p, 
-                                                     md->contacts, md->ca_agreement))
+        if (APR_SUCCESS == (rv = md_acme_create_acct(ad->acme, d->p, md->contacts, 
+                                                     md->ca_agreement))
             && APR_SUCCESS == (rv = md_acme_acct_save_staged(ad->acme, d->store, md, d->p))) {
             md->ca_account = MD_ACME_ACCT_STAGED;
             update = 1;
@@ -267,11 +269,13 @@ static apr_status_t ad_start_challenges(
         switch (authz->state) {
             case MD_ACME_AUTHZ_S_VALID:
                 break;
-            case MD_ACME_AUTHZ_S_PENDING:
                 
-                rv = md_acme_authz_respond(authz, ad->acme, d->store, ad->ca_challenges, d->p);
+            case MD_ACME_AUTHZ_S_PENDING:
+                rv = md_acme_authz_respond(authz, ad->acme, d->store, ad->ca_challenges, 
+                                           d->md->pkey_spec, d->p);
                 changed = 1;
                 break;
+                
             default:
                 rv = APR_EINVAL;
                 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, d->p, 
@@ -464,22 +468,22 @@ static apr_status_t csr_req(md_acme_t *a
 static apr_status_t ad_setup_certificate(md_proto_driver_t *d)
 {
     md_acme_driver_t *ad = d->baton;
-    md_pkey_t *pkey;
+    md_pkey_t *privkey;
     apr_status_t rv;
 
-    ad->phase = "setup cert pkey";
+    ad->phase = "setup cert privkey";
     
-    rv = md_pkey_load(d->store, MD_SG_STAGING, ad->md->name, &pkey, d->p);
+    rv = md_pkey_load(d->store, MD_SG_STAGING, ad->md->name, &privkey, d->p);
     if (APR_STATUS_IS_ENOENT(rv)) {
-        if (APR_SUCCESS == (rv = md_pkey_gen_rsa(&pkey, d->p, ad->acme->pkey_bits))) {
-            rv = md_pkey_save(d->store, d->p, MD_SG_STAGING, ad->md->name, pkey, 1);
+        if (APR_SUCCESS == (rv = md_pkey_gen(&privkey, d->p, d->md->pkey_spec))) {
+            rv = md_pkey_save(d->store, d->p, MD_SG_STAGING, ad->md->name, privkey, 1);
         }
-        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, d->p, "%s: generate pkey", ad->md->name);
+        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, d->p, "%s: generate privkey", ad->md->name);
     }
 
     if (APR_SUCCESS == rv) {
         ad->phase = "setup csr";
-        rv = md_cert_req_create(&ad->csr_der_64, ad->md, pkey, d->p);
+        rv = md_cert_req_create(&ad->csr_der_64, ad->md, privkey, d->p);
         md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, d->p, "%s: create CSR", ad->md->name);
     }
 
@@ -674,6 +678,12 @@ static apr_status_t acme_stage(md_proto_
         ad->md = NULL;
     }
     
+    if (ad->md && ad->md->state == MD_S_MISSING) {
+        /* There is config information missing. It makes no sense to drive this MD further */
+        rv = APR_INCOMPLETE;
+        goto out;
+    }
+    
     if (ad->md) {
         /* staging in progress. look for new ACME account information collected there */
         rv = md_reg_creds_get(&ad->ncreds, d->reg, MD_SG_STAGING, d->md, d->p);
@@ -684,7 +694,7 @@ static apr_status_t acme_stage(md_proto_
     }
     
     /* Find out where we're at with this managed domain */
-    if (ad->ncreds && ad->ncreds->pkey && ad->ncreds->cert && ad->ncreds->chain) {
+    if (ad->ncreds && ad->ncreds->privkey && ad->ncreds->pubcert) {
         /* There is a full set staged, to be loaded */
         md_log_perror(MD_LOG_MARK, MD_LOG_INFO, 0, d->p, "%s: all data staged", d->md->name);
         renew = 0;
@@ -724,11 +734,32 @@ static apr_status_t acme_stage(md_proto_
              * requests for new authorizations are denied. ToS may change during the
              * lifetime of an account */
             if (APR_SUCCESS == rv) {
+                const char *required;
+                
                 ad->phase = "check agreement";
                 md_log_perror(MD_LOG_MARK, MD_LOG_INFO, 0, d->p, 
                               "%s: check Terms-of-Service agreement", d->md->name);
                 
-                rv = md_acme_check_agreement(ad->acme, d->p, ad->md->ca_agreement);
+                rv = md_acme_check_agreement(ad->acme, d->p, ad->md->ca_agreement, &required);
+                
+                if (APR_STATUS_IS_INCOMPLETE(rv) && required) {
+                    /* The CA wants the user to agree to Terms-of-Services. Until the user
+                     * has reconfigured and restarted the server, this MD cannot be
+                     * driven further */
+                    ad->md->state = MD_S_MISSING;
+                    md_save(d->store, d->p, MD_SG_STAGING, ad->md, 0);
+
+                    md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, d->p, 
+                                  "%s: the CA requires you to accept the terms-of-service "
+                                  "as specified in <%s>. "
+                                  "Please read the document that you find at that URL and, "
+                                  "if you agree to the conditions, configure "
+                                  "\"MDCertificateAgreement url\" "
+                                  "with exactly that URL in your Apache. "
+                                  "Then (graceful) restart the server to activate.", 
+                                  ad->md->name, required);
+                    goto out;
+                }
             }
             
             /* If we know a cert's location, try to get it. Previous download might
@@ -780,12 +811,28 @@ static apr_status_t acme_stage(md_proto_
         }
         
         if (APR_SUCCESS == rv && !ad->chain) {
+            /* have we created this already? */
+            md_chain_load(d->store, MD_SG_STAGING, ad->md->name, &ad->chain, d->p);
+        }
+        if (APR_SUCCESS == rv && !ad->chain) {
             ad->phase = "install chain";
             md_log_perror(MD_LOG_MARK, MD_LOG_INFO, 0, d->p, 
                           "%s: retrieving certificate chain", d->md->name);
             rv = ad_chain_install(d);
         }
 
+        if (APR_SUCCESS == rv && !ad->pubcert) {
+            /* have we created this already? */
+            md_pubcert_load(d->store, MD_SG_STAGING, ad->md->name, &ad->pubcert, d->p);
+        }
+        if (APR_SUCCESS == rv && !ad->pubcert) {
+            /* combine cert + chain into the pubcert */
+            ad->pubcert = apr_array_make(d->p, ad->chain->nelts + 1, sizeof(md_cert_t*));
+            APR_ARRAY_PUSH(ad->pubcert, md_cert_t *) = ad->cert;
+            apr_array_cat(ad->pubcert, ad->chain);
+            rv = md_pubcert_save(d->store, d->p, MD_SG_STAGING, ad->md->name, ad->pubcert, 0);
+        }
+
         if (APR_SUCCESS == rv && ad->cert) {
             apr_time_t now = apr_time_now();
             apr_interval_time_t max_delay, delay_activation; 
@@ -832,10 +879,9 @@ static apr_status_t acme_preload(md_stor
                                  const char *name, apr_pool_t *p) 
 {
     apr_status_t rv;
-    md_pkey_t *pkey, *acct_key;
+    md_pkey_t *privkey, *acct_key;
     md_t *md;
-    md_cert_t *cert;
-    apr_array_header_t *chain;
+    apr_array_header_t *pubcert;
     struct md_acme_acct_t *acct;
 
     md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "%s: preload start", name);
@@ -852,16 +898,12 @@ static apr_status_t acme_preload(md_stor
         md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: loading md json", name);
         return rv;
     }
-    if (APR_SUCCESS != (rv = md_cert_load(store, MD_SG_STAGING, name, &cert, p))) {
-        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: loading certificate", name);
-        return rv;
-    }
-    if (APR_SUCCESS != (rv = md_chain_load(store, MD_SG_STAGING, name, &chain, p))) {
-        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: loading cert chain", name);
+    if (APR_SUCCESS != (rv = md_pkey_load(store, MD_SG_STAGING, name, &privkey, p))) {
+        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: loading staging private key", name);
         return rv;
     }
-    if (APR_SUCCESS != (rv = md_pkey_load(store, MD_SG_STAGING, name, &pkey, p))) {
-        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: loading staging private key", name);
+    if (APR_SUCCESS != (rv = md_pubcert_load(store, MD_SG_STAGING, name, &pubcert, p))) {
+        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: loading pubcert", name);
         return rv;
     }
 
@@ -904,16 +946,12 @@ static apr_status_t acme_preload(md_stor
         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: saving md json", name);
         return rv;
     }
-    if (APR_SUCCESS != (rv = md_cert_save(store, p, load_group, name, cert, 1))) {
-        md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: saving certificate", name);
-        return rv;
-    }
-    if (APR_SUCCESS != (rv = md_chain_save(store, p, load_group, name, chain, 1))) {
+    if (APR_SUCCESS != (rv = md_pubcert_save(store, p, load_group, name, pubcert, 1))) {
         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: saving cert chain", name);
         return rv;
     }
-    if (APR_SUCCESS != (rv = md_pkey_save(store, p, load_group, name, pkey, 1))) {
-        md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: saving domain private key", name);
+    if (APR_SUCCESS != (rv = md_pkey_save(store, p, load_group, name, privkey, 1))) {
+        md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: saving private key", name);
         return rv;
     }
     

Modified: httpd/httpd/trunk/modules/md/md_cmd_reg.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_cmd_reg.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_cmd_reg.c (original)
+++ httpd/httpd/trunk/modules/md/md_cmd_reg.c Fri Sep  1 12:11:38 2017
@@ -103,7 +103,7 @@ static apr_status_t cmd_reg_list(md_cmd_
     else {
         md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ctx->p, "list do");
         md_reg_do(list_add_md, mdlist, ctx->reg, ctx->p);
-        qsort(mdlist->elts, mdlist->nelts, sizeof(md_t *), md_name_cmp);
+        qsort(mdlist->elts, (size_t)mdlist->nelts, sizeof(md_t *), md_name_cmp);
     
         for (i = 0; i < mdlist->nelts; ++i) {
             md = APR_ARRAY_IDX(mdlist, i, const md_t*);
@@ -274,7 +274,7 @@ static apr_status_t assess_and_drive(md_
         md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, ctx->p, "%s: %s", md->name, msg);
         
         if (APR_SUCCESS == (rv = md_reg_stage(ctx->reg, md, challenge, reset, NULL, ctx->p))) {
-        md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, ctx->p, "%s: loading", md->name);
+            md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, ctx->p, "%s: loading", md->name);
             
             rv = md_reg_load(ctx->reg, md->name, ctx->p);
             
@@ -317,7 +317,7 @@ static apr_status_t cmd_reg_drive(md_cmd
     }
     else {
         md_reg_do(list_add_md, mdlist, ctx->reg, ctx->p);
-        qsort(mdlist->elts, mdlist->nelts, sizeof(md_t *), md_name_cmp);
+        qsort(mdlist->elts, (size_t)mdlist->nelts, sizeof(md_t *), md_name_cmp);
     }   
     
     rv = APR_SUCCESS;

Modified: httpd/httpd/trunk/modules/md/md_core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_core.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_core.c (original)
+++ httpd/httpd/trunk/modules/md/md_core.c Fri Sep  1 12:11:38 2017
@@ -24,6 +24,7 @@
 
 #include "md_json.h"
 #include "md.h"
+#include "md_crypt.h"
 #include "md_log.h"
 #include "md_store.h"
 #include "md_util.h"
@@ -229,6 +230,8 @@ md_t *md_clone(apr_pool_t *p, const md_t
         md->name = apr_pstrdup(p, src->name);
         md->drive_mode = src->drive_mode;
         md->domains = md_array_str_compact(p, src->domains, 0);
+        md->pkey_spec = src->pkey_spec;
+        md->renew_norm = src->renew_norm;
         md->renew_window = src->renew_window;
         md->contacts = md_array_str_clone(p, src->contacts);
         if (src->ca_url) md->ca_url = apr_pstrdup(p, src->ca_url);
@@ -253,8 +256,10 @@ md_t *md_merge(apr_pool_t *p, const md_t
     n->ca_proto = add->ca_proto? add->ca_proto : base->ca_proto;
     n->ca_agreement = add->ca_agreement? add->ca_agreement : base->ca_agreement;
     n->drive_mode = (add->drive_mode != MD_DRIVE_DEFAULT)? add->drive_mode : base->drive_mode;
-    n->renew_window = (add->renew_window <= 0)? add->renew_window : base->renew_window;
-    n->transitive = (add->transitive < 0)? add->transitive : base->transitive;
+    n->pkey_spec = add->pkey_spec? add->pkey_spec : base->pkey_spec;
+    n->renew_norm = (add->renew_norm > 0)? add->renew_norm : base->renew_norm;
+    n->renew_window = (add->renew_window > 0)? add->renew_window : base->renew_window;
+    n->transitive = (add->transitive >= 0)? add->transitive : base->transitive;
     if (add->ca_challenges) {
         n->ca_challenges = apr_array_copy(p, add->ca_challenges);
     }
@@ -264,7 +269,6 @@ md_t *md_merge(apr_pool_t *p, const md_t
     return n;
 }
 
-
 /**************************************************************************************************/
 /* format conversion */
 
@@ -284,6 +288,9 @@ md_json_t *md_to_json(const md_t *md, ap
         if (md->cert_url) {
             md_json_sets(md->cert_url, json, MD_KEY_CERT, MD_KEY_URL, NULL);
         }
+        if (md->pkey_spec) {
+            md_json_setj(md_pkey_spec_to_json(md->pkey_spec, p), json, MD_KEY_PKEY, NULL);
+        }
         md_json_setl(md->state, json, MD_KEY_STATE, NULL);
         md_json_setl(md->drive_mode, json, MD_KEY_DRIVE_MODE, NULL);
         if (md->expires > 0) {
@@ -296,7 +303,13 @@ md_json_t *md_to_json(const md_t *md, ap
             apr_rfc822_date(ts, md->valid_from);
             md_json_sets(ts, json, MD_KEY_CERT, MD_KEY_VALID_FROM, NULL);
         }
-        md_json_setl(apr_time_sec(md->renew_window), json, MD_KEY_RENEW_WINDOW, 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);
+        }
+        else {
+            md_json_setl((long)apr_time_sec(md->renew_window), json, MD_KEY_RENEW_WINDOW, 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);
@@ -320,7 +333,10 @@ md_t *md_from_json(md_json_t *json, apr_
         md->ca_url = md_json_dups(p, json, MD_KEY_CA, MD_KEY_URL, NULL);
         md->ca_agreement = md_json_dups(p, json, MD_KEY_CA, MD_KEY_AGREEMENT, NULL);
         md->cert_url = md_json_dups(p, json, MD_KEY_CERT, MD_KEY_URL, NULL);
-        md->state = (int)md_json_getl(json, MD_KEY_STATE, NULL);
+        if (md_json_has_key(json, MD_KEY_PKEY, MD_KEY_TYPE, NULL)) {
+            md->pkey_spec = md_pkey_spec_from_json(md_json_getj(json, MD_KEY_PKEY, NULL), p);
+        }
+        md->state = (md_state_t)md_json_getl(json, MD_KEY_STATE, NULL);
         md->drive_mode = (int)md_json_getl(json, MD_KEY_DRIVE_MODE, NULL);
         md->domains = md_array_str_compact(p, md->domains, 0);
         md->transitive = (int)md_json_getl(json, MD_KEY_TRANSITIVE, NULL);
@@ -332,6 +348,7 @@ 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_window = apr_time_from_sec(md_json_getl(json, MD_KEY_RENEW_WINDOW, NULL));
         if (md_json_has_key(json, MD_KEY_CA, MD_KEY_CHALLENGES, NULL)) {
             md->ca_challenges = apr_array_make(p, 5, sizeof(const char*));

Modified: httpd/httpd/trunk/modules/md/md_crypt.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_crypt.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_crypt.c (original)
+++ httpd/httpd/trunk/modules/md/md_crypt.c Fri Sep  1 12:11:38 2017
@@ -31,6 +31,7 @@
 
 #include "md.h"
 #include "md_crypt.h"
+#include "md_json.h"
 #include "md_log.h"
 #include "md_http.h"
 #include "md_util.h"
@@ -83,7 +84,7 @@ static void seed_RAND(int pid)
 {   
     unsigned char stackdata[256];
     /* stolen from mod_ssl/ssl_engine_rand.c */
-    apr_size_t n, l;
+    int n;
     struct {
         time_t t;
         pid_t pid;
@@ -99,8 +100,7 @@ static void seed_RAND(int pid)
      */
     my_seed.pid = pid;
     
-    l = sizeof(my_seed);
-    RAND_seed((unsigned char *)&my_seed, l);
+    RAND_seed((unsigned char *)&my_seed, sizeof(my_seed));
     
     /*
      * seed in some current state of the run-time stack (128 bytes)
@@ -173,7 +173,7 @@ static int pem_passwd(char *buf, int siz
         if (ctx->pass_len < size) {
             size = (int)ctx->pass_len;
         }
-        memcpy(buf, ctx->pass_phrase, size);
+        memcpy(buf, ctx->pass_phrase, (size_t)size);
     }
     return ctx->pass_len;
 }
@@ -181,6 +181,50 @@ static int pem_passwd(char *buf, int siz
 /**************************************************************************************************/
 /* private keys */
 
+md_json_t *md_pkey_spec_to_json(const md_pkey_spec_t *spec, apr_pool_t *p)
+{
+    md_json_t *json = md_json_create(p);
+    if (json) {
+        switch (spec->type) {
+            case MD_PKEY_TYPE_DEFAULT:
+                md_json_sets("Default", json, MD_KEY_TYPE, NULL);
+                break;
+            case MD_PKEY_TYPE_RSA:
+                md_json_sets("RSA", json, MD_KEY_TYPE, NULL);
+                if (spec->params.rsa.bits > 2048) {
+                    md_json_setl(spec->params.rsa.bits, json, MD_KEY_BITS, NULL);
+                }
+                break;
+            default:
+                md_json_sets("Unsupported", json, MD_KEY_TYPE, NULL);
+                break;
+        }
+    }
+    return json;    
+}
+
+md_pkey_spec_t *md_pkey_spec_from_json(struct md_json_t *json, apr_pool_t *p)
+{
+    md_pkey_spec_t *spec = apr_pcalloc(p, sizeof(*spec));
+    const char *s;
+    long l;
+    
+    if (spec) {
+        s = md_json_gets(json, MD_KEY_TYPE, NULL);
+        if (!s || !apr_strnatcasecmp("Default", s)) {
+            spec->type = MD_PKEY_TYPE_DEFAULT;
+        }
+        else if (!apr_strnatcasecmp("RSA", s)) {
+            spec->type = MD_PKEY_TYPE_RSA;
+            l = md_json_getl(json, MD_KEY_BITS, NULL);
+            if (l > 2048) {
+                spec->params.rsa.bits = (unsigned int)l;
+            }
+        }
+    }
+    return spec;
+}
+
 static md_pkey_t *make_pkey(apr_pool_t *p) 
 {
     md_pkey_t *pkey = apr_pcalloc(p, sizeof(*pkey));
@@ -231,7 +275,7 @@ apr_status_t md_pkey_fload(md_pkey_t **p
             apr_pool_cleanup_register(p, pkey, pkey_cleanup, apr_pool_cleanup_null);
         }
         else {
-            long err = ERR_get_error();
+            unsigned long err = ERR_get_error();
             rv = APR_EINVAL;
             md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, 
                           "error loading pkey %s: %s (pass phrase was %snull)", fname,
@@ -251,6 +295,7 @@ static apr_status_t pkey_to_buffer(buffe
     void *cb_baton = NULL;
     passwd_ctx ctx;
     unsigned long err;
+    int i;
     
     if (!bio) {
         return APR_ENOMEM;
@@ -278,11 +323,12 @@ static apr_status_t pkey_to_buffer(buffe
         return APR_EINVAL;
     }
 
-    buffer->len = BIO_pending(bio);
-    if (buffer->len > 0) {
-        buffer->data = apr_palloc(p, buffer->len+1);
-        buffer->len = BIO_read(bio, buffer->data, (int)buffer->len);
-        buffer->data[buffer->len] = '\0';
+    i = BIO_pending(bio);
+    if (i > 0) {
+        buffer->data = apr_palloc(p, (apr_size_t)i + 1);
+        i = BIO_read(bio, buffer->data, i);
+        buffer->data[i] = '\0';
+        buffer->len = (apr_size_t)i;
     }
     BIO_free(bio);
     return APR_SUCCESS;
@@ -303,7 +349,7 @@ apr_status_t md_pkey_fsave(md_pkey_t *pk
     return rv;
 }
 
-apr_status_t md_pkey_gen_rsa(md_pkey_t **ppkey, apr_pool_t *p, int bits)
+static apr_status_t gen_rsa(md_pkey_t **ppkey, apr_pool_t *p, unsigned int bits)
 {
     EVP_PKEY_CTX *ctx = NULL;
     apr_status_t rv;
@@ -312,7 +358,7 @@ apr_status_t md_pkey_gen_rsa(md_pkey_t *
     ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
     if (ctx 
         && EVP_PKEY_keygen_init(ctx) >= 0
-        && EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) >= 0
+        && EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, (int)bits) >= 0
         && EVP_PKEY_keygen(ctx, &(*ppkey)->pkey) >= 0) {
         rv = APR_SUCCESS;
     }
@@ -328,6 +374,19 @@ apr_status_t md_pkey_gen_rsa(md_pkey_t *
     return rv;
 }
 
+apr_status_t md_pkey_gen(md_pkey_t **ppkey, apr_pool_t *p, md_pkey_spec_t *spec)
+{
+    md_pkey_type_t ptype = spec? spec->type : MD_PKEY_TYPE_DEFAULT;
+    switch (ptype) {
+        case MD_PKEY_TYPE_DEFAULT:
+            return gen_rsa(ppkey, p, MD_PKEY_RSA_BITS_DEF);
+        case MD_PKEY_TYPE_RSA:
+            return gen_rsa(ppkey, p, spec->params.rsa.bits);
+        default:
+            return APR_ENOTIMPL;
+    }
+}
+
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
 
 #ifndef NID_tlsfeature
@@ -350,7 +409,7 @@ static void RSA_get0_key(const RSA *r,
 static const char *bn64(const BIGNUM *b, apr_pool_t *p) 
 {
     if (b) {
-         int len = BN_num_bytes(b);
+         apr_size_t len = (apr_size_t)BN_num_bytes(b);
          char *buffer = apr_pcalloc(p, len);
          if (buffer) {
             BN_bn2bin(b, (unsigned char *)buffer);
@@ -393,7 +452,7 @@ apr_status_t md_crypt_sign64(const char
     const char *sign64 = NULL;
     apr_status_t rv = APR_ENOMEM;
     
-    buffer = apr_pcalloc(p, EVP_PKEY_size(pkey->pkey));
+    buffer = apr_pcalloc(p, (apr_size_t)EVP_PKEY_size(pkey->pkey));
     if (buffer) {
         ctx = EVP_MD_CTX_create();
         if (ctx) {
@@ -728,6 +787,7 @@ apr_status_t md_cert_fload(md_cert_t **p
 static apr_status_t cert_to_buffer(buffer *buffer, md_cert_t *cert, apr_pool_t *p)
 {
     BIO *bio = BIO_new(BIO_s_mem());
+    int i;
     
     if (!bio) {
         return APR_ENOMEM;
@@ -740,11 +800,12 @@ static apr_status_t cert_to_buffer(buffe
         return APR_EINVAL;
     }
 
-    buffer->len = BIO_pending(bio);
-    if (buffer->len > 0) {
-        buffer->data = apr_palloc(p, buffer->len+1);
-        buffer->len = BIO_read(bio, buffer->data, (int)buffer->len);
-        buffer->data[buffer->len] = '\0';
+    i = BIO_pending(bio);
+    if (i > 0) {
+        buffer->data = apr_palloc(p, (apr_size_t)i + 1);
+        i = BIO_read(bio, buffer->data, i);
+        buffer->data[i] = '\0';
+        buffer->len = (apr_size_t)i;
     }
     BIO_free(bio);
     return APR_SUCCESS;
@@ -797,7 +858,7 @@ apr_status_t md_cert_read_http(md_cert_t
             const unsigned char *bf = (const unsigned char*)der;
             X509 *x509;
             
-            if (NULL == (x509 = d2i_X509(NULL, &bf, der_len))) {
+            if (NULL == (x509 = d2i_X509(NULL, &bf, (long)der_len))) {
                 rv = APR_EINVAL;
             }
             else {
@@ -818,19 +879,16 @@ md_cert_state_t md_cert_state_get(md_cer
     return MD_CERT_UNKNOWN;
 }
 
-apr_status_t md_chain_fload(apr_array_header_t **pcerts, apr_pool_t *p, const char *fname)
+apr_status_t md_chain_fappend(struct apr_array_header_t *certs, apr_pool_t *p, const char *fname)
 {
     FILE *f;
     apr_status_t rv;
-    apr_array_header_t *certs = NULL;
     X509 *x509;
     md_cert_t *cert;
     unsigned long err;
     
     rv = md_util_fopen(&f, fname, "r");
     if (rv == APR_SUCCESS) {
-        certs = apr_array_make(p, 5, sizeof(md_cert_t *));
-        
         ERR_clear_error();
         while (NULL != (x509 = PEM_read_X509(f, NULL, NULL, NULL))) {
             cert = make_cert(p, x509);
@@ -862,6 +920,16 @@ apr_status_t md_chain_fload(apr_array_he
 out:
     md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p, "read chain file %s, found %d certs", 
                   fname, certs? certs->nelts : 0);
+    return rv;
+}
+
+apr_status_t md_chain_fload(apr_array_header_t **pcerts, apr_pool_t *p, const char *fname)
+{
+    apr_array_header_t *certs;
+    apr_status_t rv;
+
+    certs = apr_array_make(p, 5, sizeof(md_cert_t *));
+    rv = md_chain_fappend(certs, p, fname);
     *pcerts = (APR_SUCCESS == rv)? certs : NULL;
     return rv;
 }
@@ -1027,12 +1095,12 @@ apr_status_t md_cert_req_create(const ch
         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: der length", md->name);
         rv = APR_EGENERAL; goto out;
     }
-    s = csr_der = apr_pcalloc(p, csr_der_len + 1);
+    s = csr_der = apr_pcalloc(p, (apr_size_t)csr_der_len + 1);
     if (i2d_X509_REQ(csr, (unsigned char**)&s) != csr_der_len) {
         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: csr der enc", md->name);
         rv = APR_EGENERAL; goto out;
     }
-    csr_der_64 = md_util_base64url_encode(csr_der, csr_der_len, p);
+    csr_der_64 = md_util_base64url_encode(csr_der, (apr_size_t)csr_der_len, p);
     rv = APR_SUCCESS;
     
 out:
@@ -1104,7 +1172,7 @@ apr_status_t md_cert_self_sign(md_cert_t
         rv = APR_EGENERAL; goto out;
     }
     
-    days = ((apr_time_sec(valid_for) + MD_SECS_PER_DAY - 1)/ MD_SECS_PER_DAY);
+    days = (int)((apr_time_sec(valid_for) + MD_SECS_PER_DAY - 1)/ MD_SECS_PER_DAY);
     if (!X509_set_notBefore(x, ASN1_TIME_set(NULL, time(NULL)))) {
         rv = APR_EGENERAL; goto out;
     }

Modified: httpd/httpd/trunk/modules/md/md_crypt.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_crypt.h?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_crypt.h (original)
+++ httpd/httpd/trunk/modules/md/md_crypt.h Fri Sep  1 12:11:38 2017
@@ -41,9 +41,25 @@ apr_status_t md_crypt_sha256_digest_hex(
 
 typedef struct md_pkey_t md_pkey_t;
 
+typedef enum {
+    MD_PKEY_TYPE_DEFAULT,
+    MD_PKEY_TYPE_RSA,
+} md_pkey_type_t;
+
+typedef struct md_pkey_rsa_spec_t {
+    apr_uint32_t bits;
+} md_pkey_rsa_spec_t;
+
+typedef struct md_pkey_spec_t {
+    md_pkey_type_t type;
+    union {
+        md_pkey_rsa_spec_t rsa;
+    } params;
+} md_pkey_spec_t;
+
 apr_status_t md_crypt_init(apr_pool_t *pool);
 
-apr_status_t md_pkey_gen_rsa(md_pkey_t **ppkey, apr_pool_t *p, int bits);
+apr_status_t md_pkey_gen(md_pkey_t **ppkey, apr_pool_t *p, md_pkey_spec_t *spec);
 void md_pkey_free(md_pkey_t *pkey);
 
 const char *md_pkey_get_rsa_e64(md_pkey_t *pkey, apr_pool_t *p);
@@ -62,6 +78,9 @@ apr_status_t md_crypt_sign64(const char
 void *md_cert_get_X509(struct md_cert_t *cert);
 void *md_pkey_get_EVP_PKEY(struct md_pkey_t *pkey);
 
+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);
+
 /**************************************************************************************************/
 /* X509 certificates */
 
@@ -100,6 +119,8 @@ apr_status_t md_chain_fload(struct apr_a
                             apr_pool_t *p, const char *fname);
 apr_status_t md_chain_fsave(struct apr_array_header_t *certs, 
                             apr_pool_t *p, const char *fname, apr_fileperms_t perms);
+apr_status_t md_chain_fappend(struct apr_array_header_t *certs, 
+                              apr_pool_t *p, const char *fname);
 
 apr_status_t md_cert_req_create(const char **pcsr_der_64, const struct md_t *md, 
                                 md_pkey_t *pkey, apr_pool_t *p);

Modified: httpd/httpd/trunk/modules/md/md_curl.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_curl.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_curl.c (original)
+++ httpd/httpd/trunk/modules/md/md_curl.c Fri Sep  1 12:11:38 2017
@@ -99,7 +99,7 @@ static size_t resp_data_cb(void *data, s
         if (res->req->resp_limit) {
             apr_off_t body_len = 0;
             apr_brigade_length(res->body, 0, &body_len);
-            if (body_len + len > res->req->resp_limit) {
+            if (body_len + (apr_off_t)len > res->req->resp_limit) {
                 return 0; /* signal curl failure */
             }
         }
@@ -117,7 +117,7 @@ static size_t header_cb(void *buffer, si
     md_http_response_t *res = baton;
     size_t len, clen = elen * nmemb;
     const char *name = NULL, *value = "", *b = buffer;
-    int i;
+    apr_size_t i;
     
     len = (clen && b[clen-1] == '\n')? clen-1 : clen;
     len = (len && b[len-1] == '\r')? len-1 : len;
@@ -183,7 +183,7 @@ static int curlify_headers(void *baton,
 static apr_status_t curl_perform(md_http_request_t *req)
 {
     apr_status_t rv = APR_SUCCESS;
-    int curle;
+    CURLcode curle;
     md_http_response_t *res;
     CURL *curl;
     struct curl_slist *req_hdrs = NULL;
@@ -253,7 +253,8 @@ static apr_status_t curl_perform(md_http
     }
     else {
         md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, res->rv, req->pool, 
-                      "request %ld failed(%d): %s", req->id, curle, curl_easy_strerror(curle));
+                      "request %ld failed(%d): %s", req->id, curle, 
+                      curl_easy_strerror(curle));
     }
     
     if (req->cb) {

Modified: httpd/httpd/trunk/modules/md/md_reg.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_reg.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_reg.c (original)
+++ httpd/httpd/trunk/modules/md/md_reg.c Fri Sep  1 12:11:38 2017
@@ -162,19 +162,14 @@ static apr_status_t state_init(md_reg_t
 
     if (APR_SUCCESS == (rv = md_reg_creds_get(&creds, reg, MD_SG_DOMAINS, md, p))) {
         state = MD_S_INCOMPLETE;
-        if (!creds->pkey) {
+        if (!creds->privkey) {
             md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, 
                           "md{%s}: incomplete, without private key", md->name);
         }
-        else if (!creds->cert) {
+        else if (!creds->pubcert) {
             md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, 
                           "md{%s}: incomplete, has key but no certificate", md->name);
         }
-        else if (!creds->chain) {
-            md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, 
-                          "md{%s}: incomplete, has key and certificate, but no chain file.", 
-                          md->name);
-        }
         else {
             valid_from = md_cert_get_not_before(creds->cert);
             expires = md_cert_get_not_after(creds->cert);
@@ -199,8 +194,8 @@ static apr_status_t state_init(md_reg_t
                 goto out;
             }
 
-            for (i = 0; i < creds->chain->nelts; ++i) {
-                cert = APR_ARRAY_IDX(creds->chain, i, const md_cert_t *);
+            for (i = 1; i < creds->pubcert->nelts; ++i) {
+                cert = APR_ARRAY_IDX(creds->pubcert, i, const md_cert_t *);
                 if (!md_cert_is_valid_now(cert)) {
                     state = MD_S_ERROR;
                     md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, 
@@ -281,17 +276,34 @@ apr_status_t md_reg_assess(md_reg_t *reg
                 md->state = MD_S_EXPIRED;
                 renew = 1;
             }
-            else if ((md->expires - now) <= md->renew_window) {
-                int days = (int)(apr_time_sec(md->expires - now) / 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);
-                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;
+                }                
             }
             break;
         case MD_S_INCOMPLETE:
         case MD_S_EXPIRED:
             renew = 1;
             break;
+        case MD_S_MISSING:
+            break;
     }
     *prenew = renew;
     *perrored = errored;
@@ -417,16 +429,10 @@ apr_status_t md_reg_get_cred_files(md_re
 {
     apr_status_t rv;
     
-    rv = md_store_get_fname(pkeyfile, reg->store, MD_SG_DOMAINS, md->name, MD_FN_PKEY, p);
+    *pchainfile = NULL;
+    rv = md_store_get_fname(pkeyfile, reg->store, MD_SG_DOMAINS, md->name, MD_FN_PRIVKEY, p);
     if (APR_SUCCESS == rv) {
-        rv = md_store_get_fname(pcertfile, reg->store, MD_SG_DOMAINS, md->name, MD_FN_CERT, p);
-    }
-    if (APR_SUCCESS == rv) {
-        rv = md_store_get_fname(pchainfile, reg->store, MD_SG_DOMAINS, md->name, MD_FN_CHAIN, p);
-        if (APR_STATUS_IS_ENOENT(rv)) {
-            *pchainfile = NULL;
-            rv = APR_SUCCESS;
-        }
+        rv = md_store_get_fname(pcertfile, reg->store, MD_SG_DOMAINS, md->name, MD_FN_PUBCERT, p);
     }
     return rv;
 }
@@ -513,6 +519,7 @@ static apr_status_t p_md_update(void *ba
     }
     if (MD_UPD_RENEW_WINDOW & fields) {
         md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update renew-window: %s", name);
+        nmd->renew_norm = updates->renew_norm;
         nmd->renew_window = updates->renew_window;
     }
     if (MD_UPD_CA_CHALLENGES & fields) {
@@ -544,29 +551,28 @@ static int ok_or_noent(apr_status_t rv)
 static apr_status_t creds_load(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
 {
     md_reg_t *reg = baton;
-    apr_status_t rv;
-    md_cert_t *cert;
-    md_pkey_t *pkey;
-    apr_array_header_t *chain;
+    md_pkey_t *privkey;
+    apr_array_header_t *pubcert;
     md_creds_t *creds, **pcreds;
     const md_t *md;
     md_cert_state_t cert_state;
     md_store_group_t group;
+    apr_status_t rv;
     
     pcreds = va_arg(ap, md_creds_t **);
-    group = va_arg(ap, int);
+    group = (md_store_group_t)va_arg(ap, int);
     md = va_arg(ap, const md_t *);
     
-    if (ok_or_noent(rv = md_cert_load(reg->store, group, md->name, &cert, p))
-        && ok_or_noent(rv = md_pkey_load(reg->store, group, md->name, &pkey, p))
-        && ok_or_noent(rv = md_chain_load(reg->store, group, md->name, &chain, p))) {
+    if (ok_or_noent(rv = md_pkey_load(reg->store, group, md->name, &privkey, p))
+        && ok_or_noent(rv = md_pubcert_load(reg->store, group, md->name, &pubcert, p))) {
         rv = APR_SUCCESS;
             
         creds = apr_pcalloc(p, sizeof(*creds));
-        creds->cert = cert;
-        creds->pkey = pkey;
-        creds->chain = chain;
-        
+        creds->privkey = privkey;
+        if (pubcert && pubcert->nelts > 0) {
+            creds->pubcert = pubcert;
+            creds->cert = APR_ARRAY_IDX(pubcert, 0, md_cert_t *);
+        }
         if (creds->cert) {
             switch ((cert_state = md_cert_state_get(creds->cert))) {
                 case MD_CERT_VALID:
@@ -767,10 +773,12 @@ apr_status_t md_reg_sync(md_reg_t *reg,
                     smd->contacts = md->contacts;
                     fields |= MD_UPD_CONTACTS;
                 }
-                if (MD_VAL_UPDATE(md, smd, renew_window)) {
+                if (MD_VAL_UPDATE(md, smd, renew_window) 
+                    || MD_VAL_UPDATE(md, smd, renew_norm)) {
                     md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, 
-                                  "%s: update renew_window, old=%ld, new=%ld", 
-                                  smd->name, (long)smd->renew_window, md->renew_window);
+                                  "%s: update renew norm=%ld, window=%ld", 
+                                  smd->name, (long)md->renew_norm, (long)md->renew_window);
+                    smd->renew_norm = md->renew_norm;
                     smd->renew_window = md->renew_window;
                     fields |= MD_UPD_RENEW_WINDOW;
                 }
@@ -880,7 +888,7 @@ apr_status_t md_reg_stage(md_reg_t *reg,
         return APR_SUCCESS;
     }
     
-    proto = apr_hash_get(reg->protos, md->ca_proto, strlen(md->ca_proto));
+    proto = apr_hash_get(reg->protos, md->ca_proto, (apr_ssize_t)strlen(md->ca_proto));
     if (!proto) {
         md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p, 
                       "md %s has unknown CA protocol: %s", md->name, md->ca_proto);
@@ -918,7 +926,7 @@ static apr_status_t run_load(void *baton
         return APR_EINVAL;
     }
     
-    proto = apr_hash_get(reg->protos, md->ca_proto, strlen(md->ca_proto));
+    proto = apr_hash_get(reg->protos, md->ca_proto, (apr_ssize_t)strlen(md->ca_proto));
     if (!proto) {
         md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p, 
                       "md %s has unknown CA protocol: %s", md->name, md->ca_proto);

Modified: httpd/httpd/trunk/modules/md/md_store.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_store.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_store.c (original)
+++ httpd/httpd/trunk/modules/md/md_store.c Fri Sep  1 12:11:38 2017
@@ -232,13 +232,13 @@ typedef struct {
 apr_status_t md_pkey_load(md_store_t *store, md_store_group_t group, const char *name, 
                           md_pkey_t **ppkey, apr_pool_t *p)
 {
-    return md_store_load(store, group, name, MD_FN_PKEY, MD_SV_PKEY, (void**)ppkey, p);
+    return md_store_load(store, group, name, MD_FN_PRIVKEY, MD_SV_PKEY, (void**)ppkey, p);
 }
 
 apr_status_t md_pkey_save(md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *name, 
                           struct md_pkey_t *pkey, int create)
 {
-    return md_store_save(store, p, group, name, MD_FN_PKEY, MD_SV_PKEY, pkey, create);
+    return md_store_save(store, p, group, name, MD_FN_PRIVKEY, MD_SV_PKEY, pkey, create);
 }
 
 apr_status_t md_cert_load(md_store_t *store, md_store_group_t group, const char *name, 
@@ -267,6 +267,19 @@ apr_status_t md_chain_save(md_store_t *s
     return md_store_save(store, p, group, name, MD_FN_CHAIN, MD_SV_CHAIN, chain, create);
 }
 
+apr_status_t md_pubcert_load(md_store_t *store, md_store_group_t group, const char *name, 
+                             struct apr_array_header_t **ppubcert, apr_pool_t *p)
+{
+    return md_store_load(store, group, name, MD_FN_PUBCERT, MD_SV_CHAIN, (void**)ppubcert, p);
+}
+
+apr_status_t md_pubcert_save(md_store_t *store, apr_pool_t *p, 
+                             md_store_group_t group, const char *name, 
+                             struct apr_array_header_t *pubcert, int create)
+{
+    return md_store_save(store, p, group, name, MD_FN_PUBCERT, MD_SV_CHAIN, pubcert, create);
+}
+
 typedef struct {
     md_store_t *store;
     md_store_group_t group;

Modified: httpd/httpd/trunk/modules/md/md_store.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_store.h?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_store.h (original)
+++ httpd/httpd/trunk/modules/md/md_store.h Fri Sep  1 12:11:38 2017
@@ -146,5 +146,11 @@ apr_status_t md_chain_load(md_store_t *s
 apr_status_t md_chain_save(md_store_t *store, apr_pool_t *p, md_store_group_t group, 
                            const char *name, struct apr_array_header_t *chain, int create);
 
+apr_status_t md_pubcert_load(md_store_t *store, md_store_group_t group, const char *name, 
+                             struct apr_array_header_t **ppubcert, apr_pool_t *p);
+apr_status_t md_pubcert_save(md_store_t *store, apr_pool_t *p, 
+                             md_store_group_t group, const char *name, 
+                             struct apr_array_header_t *pubcert, int create);
+
 
 #endif /* mod_md_md_store_h */

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=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_store_fs.c (original)
+++ httpd/httpd/trunk/modules/md/md_store_fs.c Fri Sep  1 12:11:38 2017
@@ -37,7 +37,7 @@
 /**************************************************************************************************/
 /* file system based implementation of md_store_t */
 
-#define MD_STORE_VERSION        1.0
+#define MD_STORE_VERSION        2
 
 typedef struct {
     apr_fileperms_t dir;
@@ -60,8 +60,6 @@ struct md_store_fs_t {
     
     int port_80;
     int port_443;
-
-    const unsigned char *dupkey;
 };
 
 #define FS_STORE(store)     (md_store_fs_t*)(((char*)store)-offsetof(md_store_fs_t, s))
@@ -98,32 +96,88 @@ static apr_status_t init_store_file(md_s
 {
     md_json_t *json = md_json_create(p);
     const char *key64;
+    unsigned char *key;
     apr_status_t rv;
-    unsigned char key[FS_STORE_KLEN];
-    int i;
     
     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);
 
-    /*if (APR_SUCCESS != (rv = md_rand_bytes(key, sizeof(key), p))) {
+    s_fs->key_len = FS_STORE_KLEN;
+    s_fs->key = key = apr_pcalloc(p, FS_STORE_KLEN);
+    if (APR_SUCCESS != (rv = md_rand_bytes(key, s_fs->key_len, p))) {
         return rv;
-    }*/
-    for (i = 0; i < FS_STORE_KLEN; ++i) {
-        key[i] = 'a' + (i % 26);
-    } 
-
-    s_fs->key_len = sizeof(key);
-    s_fs->key = apr_pcalloc(p, sizeof(key) + 1);
-    memcpy((void*)s_fs->key, key, sizeof(key));
-    s_fs->dupkey = apr_pmemdup(p, key, sizeof(key));
+    }
         
-    key64 = md_util_base64url_encode((char *)key, sizeof(key), ptemp);
+    key64 = md_util_base64url_encode((char *)key, s_fs->key_len, ptemp);
     md_json_sets(key64, json, MD_KEY_KEY, NULL);
-    
     rv = md_json_fcreatex(json, ptemp, MD_JSON_FMT_INDENT, fname, MD_FPROT_F_UONLY);
     memset((char*)key64, 0, strlen(key64));
 
-    assert(memcmp(s_fs->key, s_fs->dupkey, FS_STORE_KLEN) == 0);
+    return rv;
+}
+
+static apr_status_t rename_pkey(void *baton, apr_pool_t *p, apr_pool_t *ptemp, 
+                                const char *dir, const char *name, 
+                                apr_filetype_e ftype)
+{
+    const char *from, *to;
+    apr_status_t rv = APR_SUCCESS;
+
+    if (APR_SUCCESS == (rv = md_util_path_merge(&from, ptemp, dir, name, NULL))
+        && APR_SUCCESS == (rv = md_util_path_merge(&to, ptemp, dir, MD_FN_PRIVKEY, NULL))) {
+        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "renaming %s/%s to %s", 
+                      dir, name, MD_FN_PRIVKEY);
+        return apr_file_rename(from, to, ptemp);
+    }
+    return rv;
+}
+
+static apr_status_t mk_pubcert(void *baton, apr_pool_t *p, apr_pool_t *ptemp, 
+                               const char *dir, const char *name, 
+                               apr_filetype_e ftype)
+{
+    md_cert_t *cert;
+    apr_array_header_t *chain, *pubcert;
+    const char *fname, *fpubcert;
+    apr_status_t rv = APR_SUCCESS;
+    
+    if (   APR_SUCCESS == (rv = md_util_path_merge(&fpubcert, ptemp, dir, MD_FN_PUBCERT, NULL))
+        && APR_STATUS_IS_ENOENT((rv = md_chain_fload(&pubcert, ptemp, fpubcert)))
+        && APR_SUCCESS == (rv = md_util_path_merge(&fname, ptemp, dir, name, NULL))
+        && APR_SUCCESS == (rv = md_cert_fload(&cert, ptemp, fname))
+        && APR_SUCCESS == (rv = md_util_path_merge(&fname, ptemp, dir, MD_FN_CHAIN, NULL))) {
+        
+        rv = md_chain_fload(&chain, ptemp, fname);
+        if (APR_STATUS_IS_ENOENT(rv)) {
+            chain = apr_array_make(ptemp, 1, sizeof(md_cert_t*));
+            rv = APR_SUCCESS;
+        }
+        if (APR_SUCCESS == rv) {
+            pubcert = apr_array_make(ptemp, chain->nelts + 1, sizeof(md_cert_t*));
+            APR_ARRAY_PUSH(pubcert, md_cert_t *) = cert;
+            apr_array_cat(pubcert, chain);
+            rv = md_chain_fsave(pubcert, ptemp, fpubcert, MD_FPROT_F_UONLY);
+        }
+    }
+    return rv;
+}
+
+static apr_status_t upgrade_from_1_0(md_store_fs_t *s_fs, apr_pool_t *p, apr_pool_t *ptemp)
+{
+    md_store_group_t g;
+    apr_status_t rv = APR_SUCCESS;
+    
+    /* Migrate pkey.pem -> privkey.pem */
+    for (g = MD_SG_NONE; g < MD_SG_COUNT && APR_SUCCESS == rv; ++g) {
+        rv = md_util_files_do(rename_pkey, s_fs, p, s_fs->base, 
+                              md_store_group_name(g), "*", "pkey.pem", NULL);
+    }
+    /* Generate fullcert.pem from cert.pem and chain.pem where missing */
+    rv = md_util_files_do(mk_pubcert, s_fs, p, s_fs->base, 
+                          md_store_group_name(MD_SG_DOMAINS), "*", MD_FN_CERT, NULL);
+    rv = md_util_files_do(mk_pubcert, s_fs, p, s_fs->base, 
+                          md_store_group_name(MD_SG_ARCHIVE), "*", MD_FN_CERT, NULL);
+    
     return rv;
 }
 
@@ -131,7 +185,7 @@ static apr_status_t read_store_file(md_s
                                     apr_pool_t *p, apr_pool_t *ptemp)
 {
     md_json_t *json;
-    const char *key64;
+    const char *key64, *key;
     apr_status_t rv;
     double store_version;
     
@@ -145,22 +199,34 @@ static apr_status_t read_store_file(md_s
             md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "version too new: %s", store_version);
             return APR_EINVAL;
         }
-        else if (store_version > MD_STORE_VERSION) {
-            /* migrate future store version changes */
-        } 
-        
+
         key64 = md_json_dups(p, json, MD_KEY_KEY, NULL);
         if (!key64) {
             md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "missing key: %s", MD_KEY_KEY);
             return APR_EINVAL;
         }
         
-        s_fs->key_len = md_util_base64url_decode((const char **)&s_fs->key, key64, p);
-        if (s_fs->key_len < FS_STORE_KLEN) {
-            md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "key too short: %d", s_fs->key_len);
+        s_fs->key_len = md_util_base64url_decode(&key, key64, p);
+        s_fs->key = (const unsigned char*)key;
+        if (s_fs->key_len != FS_STORE_KLEN) {
+            md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "key length unexpected: %d", 
+                          s_fs->key_len);
             return APR_EINVAL;
         }
-        s_fs->dupkey = apr_pmemdup(p, s_fs->key, FS_STORE_KLEN);
+
+        /* 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");
+                rv = upgrade_from_1_0(s_fs, p, ptemp);
+            }
+            
+            if (APR_SUCCESS == rv) {
+                md_json_setn(MD_STORE_VERSION, json, MD_KEY_STORE, MD_KEY_VERSION, NULL);
+                rv = md_json_freplace(json, ptemp, MD_JSON_FMT_INDENT, fname, MD_FPROT_F_UONLY);
+           }
+           md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, p, "migrated store");
+        } 
     }
     return rv;
 }
@@ -320,7 +386,6 @@ static void get_pass(const char **ppass,
         *plen = 0;
     }
     else {
-        assert(memcmp(s_fs->key, s_fs->dupkey, FS_STORE_KLEN) == 0);
         *ppass = (const char *)s_fs->key;
         *plen = s_fs->key_len;
     }
@@ -374,10 +439,10 @@ static apr_status_t pfs_load(void *baton
     void **pvalue;
     apr_status_t rv;
     
-    group = va_arg(ap, int);
+    group = (md_store_group_t)va_arg(ap, int);
     name = va_arg(ap, const char *);
     aspect = va_arg(ap, const char *);
-    vtype = va_arg(ap, int);
+    vtype = (md_store_vtype_t)va_arg(ap, int);
     pvalue= va_arg(ap, void **);
         
     rv = fs_get_fname(&fpath, &s_fs->s, group, name, aspect, ptemp);
@@ -438,8 +503,8 @@ static apr_status_t pfs_is_newer(void *b
     int *pnewer;
     apr_status_t rv;
     
-    group1 = va_arg(ap, int);
-    group2 = va_arg(ap, int);
+    group1 = (md_store_group_t)va_arg(ap, int);
+    group2 = (md_store_group_t)va_arg(ap, int);
     name = va_arg(ap, const char*);
     aspect = va_arg(ap, const char*);
     pnewer = va_arg(ap, int*);
@@ -483,10 +548,10 @@ static apr_status_t pfs_save(void *baton
     const char *pass;
     apr_size_t pass_len;
     
-    group = va_arg(ap, int);
+    group = (md_store_group_t)va_arg(ap, int);
     name = va_arg(ap, const char*);
     aspect = va_arg(ap, const char*);
-    vtype = va_arg(ap, int);
+    vtype = (md_store_vtype_t)va_arg(ap, int);
     value = va_arg(ap, void *);
     create = va_arg(ap, int);
     
@@ -540,7 +605,7 @@ static apr_status_t pfs_remove(void *bat
     apr_finfo_t info;
     md_store_group_t group;
     
-    group = va_arg(ap, int);
+    group = (md_store_group_t)va_arg(ap, int);
     name = va_arg(ap, const char*);
     aspect = va_arg(ap, const char *);
     force = va_arg(ap, int);
@@ -599,7 +664,7 @@ static apr_status_t pfs_purge(void *bato
     md_store_group_t group;
     apr_status_t rv;
     
-    group = va_arg(ap, int);
+    group = (md_store_group_t)va_arg(ap, int);
     name = va_arg(ap, const char*);
     
     groupname = md_store_group_name(group);
@@ -684,8 +749,8 @@ static apr_status_t pfs_move(void *baton
     int archive;
     apr_status_t rv;
     
-    from = va_arg(ap, int);
-    to = va_arg(ap, int);
+    from = (md_store_group_t)va_arg(ap, int);
+    to = (md_store_group_t)va_arg(ap, int);
     name = va_arg(ap, const char*);
     archive = va_arg(ap, int);
     

Modified: httpd/httpd/trunk/modules/md/md_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_util.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_util.c (original)
+++ httpd/httpd/trunk/modules/md/md_util.c Fri Sep  1 12:11:38 2017
@@ -73,7 +73,7 @@ char *md_util_str_tolower(char *s)
 {
     char *orig = s;
     while (*s) {
-        *s = apr_tolower(*s);
+        *s = (char)apr_tolower(*s);
         ++s;
     }
     return orig;
@@ -759,26 +759,28 @@ const char *md_print_duration(apr_pool_t
 
 /* base64 url encoding ****************************************************************************/
 
-static const int BASE64URL_UINT6[] = {
+#define N6 (unsigned int)-1
+
+static const unsigned int BASE64URL_UINT6[] = {
 /*   0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f        */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*  0 */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*  1 */ 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, /*  2 */
-    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /*  3 */ 
-    -1, 0,  1,  2,  3,  4,  5,  6,   7,  8,  9, 10, 11, 12, 13, 14, /*  4 */
-    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, /*  5 */
-    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /*  6 */
-    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /*  7 */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*  8 */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*  9 */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*  a */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*  b */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*  c */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*  d */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*  e */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1  /*  f */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /*  0 */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /*  1 */ 
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, 62, N6, N6, /*  2 */
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, N6, N6, N6, N6, N6, N6, /*  3 */ 
+    N6, 0,  1,  2,  3,  4,  5,  6,   7,  8,  9, 10, 11, 12, 13, 14, /*  4 */
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, N6, N6, N6, N6, 63, /*  5 */
+    N6, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /*  6 */
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, N6, N6, N6, N6, N6, /*  7 */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /*  8 */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /*  9 */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /*  a */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /*  b */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /*  c */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /*  d */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /*  e */
+    N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6  /*  f */
 };
-static const char BASE64URL_CHARS[] = {
+static const unsigned char BASE64URL_CHARS[] = {
     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /*  0 -  9 */
     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10 - 19 */
     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20 - 29 */
@@ -788,21 +790,23 @@ static const char BASE64URL_CHARS[] = {
     '8', '9', '-', '_', ' ', ' ', ' ', ' ', ' ', ' ', /* 60 - 69 */
 };
 
+#define BASE64URL_CHAR(x)    BASE64URL_CHARS[ (unsigned int)(x) & 0x3fu ]
+   
 apr_size_t md_util_base64url_decode(const char **decoded, const char *encoded, 
                                     apr_pool_t *pool)
 {
     const unsigned char *e = (const unsigned char *)encoded;
     const unsigned char *p = e;
     unsigned char *d;
-    int n;
-    apr_size_t len, mlen, remain, i;
+    unsigned int n;
+    long len, mlen, remain, i;
     
-    while (*p && BASE64URL_UINT6[ *p ] != -1) {
+    while (*p && BASE64URL_UINT6[ *p ] != N6) {
         ++p;
     }
     len = p - e;
     mlen = (len/4)*4;
-    *decoded = apr_pcalloc(pool, len+1);
+    *decoded = apr_pcalloc(pool, (apr_size_t)len + 1);
     
     i = 0;
     d = (unsigned char*)*decoded;
@@ -811,60 +815,59 @@ apr_size_t md_util_base64url_decode(cons
              (BASE64URL_UINT6[ e[i+1] ] << 12) +
              (BASE64URL_UINT6[ e[i+2] ] << 6) +
              (BASE64URL_UINT6[ e[i+3] ]));
-        *d++ = n >> 16;
-        *d++ = n >> 8 & 0xffu;
-        *d++ = n & 0xffu;
+        *d++ = (unsigned char)(n >> 16);
+        *d++ = (unsigned char)(n >> 8 & 0xffu);
+        *d++ = (unsigned char)(n & 0xffu);
     }
     remain = len - mlen;
     switch (remain) {
         case 2:
             n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) +
                  (BASE64URL_UINT6[ e[mlen+1] ] << 12));
-            *d++ = n >> 16;
+            *d++ = (unsigned char)(n >> 16);
             remain = 1;
             break;
         case 3:
             n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) +
                  (BASE64URL_UINT6[ e[mlen+1] ] << 12) +
                  (BASE64URL_UINT6[ e[mlen+2] ] << 6));
-            *d++ = n >> 16;
-            *d++ = n >> 8 & 0xffu;
+            *d++ = (unsigned char)(n >> 16);
+            *d++ = (unsigned char)(n >> 8 & 0xffu);
             remain = 2;
             break;
         default: /* do nothing */
             break;
     }
-    return mlen/4*3 + remain;
+    return (apr_size_t)(mlen/4*3 + remain);
 }
 
-const char *md_util_base64url_encode(const char *data, 
-                                     apr_size_t dlen, apr_pool_t *pool)
+const char *md_util_base64url_encode(const char *data, apr_size_t dlen, apr_pool_t *pool)
 {
-    long i, len = (int)dlen;
+    int i, len = (int)dlen;
     apr_size_t slen = ((dlen+2)/3)*4 + 1; /* 0 terminated */
     const unsigned char *udata = (const unsigned char*)data;
-    char *enc, *p = apr_pcalloc(pool, slen);
+    unsigned char *enc, *p = apr_pcalloc(pool, slen);
     
     enc = p;
     for (i = 0; i < len-2; i+= 3) {
-        *p++ = BASE64URL_CHARS[ (udata[i] >> 2) & 0x3fu ];
-        *p++ = BASE64URL_CHARS[ ((udata[i] << 4) + (udata[i+1] >> 4)) & 0x3fu ];
-        *p++ = BASE64URL_CHARS[ ((udata[i+1] << 2) + (udata[i+2] >> 6)) & 0x3fu ];
-        *p++ = BASE64URL_CHARS[ udata[i+2] & 0x3fu ];
+        *p++ = BASE64URL_CHAR( (udata[i]   >> 2) );
+        *p++ = BASE64URL_CHAR( (udata[i]   << 4) + (udata[i+1] >> 4) );
+        *p++ = BASE64URL_CHAR( (udata[i+1] << 2) + (udata[i+2] >> 6) );
+        *p++ = BASE64URL_CHAR( (udata[i+2]) );
     }
     
     if (i < len) {
-        *p++ = BASE64URL_CHARS[ (udata[i] >> 2) & 0x3fu ];
+        *p++ = BASE64URL_CHAR( (udata[i] >> 2) );
         if (i == (len - 1)) {
-            *p++ = BASE64URL_CHARS[ (udata[i] << 4) & 0x3fu ];
+            *p++ = BASE64URL_CHARS[ ((unsigned int)udata[i] << 4) & 0x3fu ];
         }
         else {
-            *p++ = BASE64URL_CHARS[ ((udata[i] << 4) + (udata[i+1] >> 4)) & 0x3fu ];
-            *p++ = BASE64URL_CHARS[ (udata[i+1] << 2) & 0x3fu ];
+            *p++ = BASE64URL_CHAR( (udata[i] << 4) + (udata[i+1] >> 4) );
+            *p++ = BASE64URL_CHAR( (udata[i+1] << 2) );
         }
     }
     *p++ = '\0';
-    return enc;
+    return (char *)enc;
 }
 
 /*******************************************************************************
@@ -874,12 +877,12 @@ const char *md_util_base64url_encode(con
 typedef struct {
     const char *s;
     apr_size_t slen;
-    int i;
-    int link_start;
+    apr_size_t i;
+    apr_size_t link_start;
     apr_size_t link_len;
-    int pn_start;
+    apr_size_t pn_start;
     apr_size_t pn_len;
-    int pv_start;
+    apr_size_t pv_start;
     apr_size_t pv_len;
 } link_ctx;
 
@@ -960,9 +963,9 @@ static int skip_nonws(link_ctx *ctx)
     return (ctx->i < ctx->slen);
 }
 
-static int find_chr(link_ctx *ctx, char c, int *pidx)
+static unsigned int find_chr(link_ctx *ctx, char c, apr_size_t *pidx)
 {
-    int j;
+    apr_size_t j;
     for (j = ctx->i; j < ctx->slen; ++j) {
         if (ctx->s[j] == c) {
             *pidx = j;
@@ -984,7 +987,7 @@ static int read_chr(link_ctx *ctx, char
 static int skip_qstring(link_ctx *ctx)
 {
     if (skip_ws(ctx) && read_chr(ctx, '\"')) {
-        int end;
+        apr_size_t end;
         if (find_chr(ctx, '\"', &end)) {
             ctx->i = end + 1;
             return 1;
@@ -996,7 +999,7 @@ static int skip_qstring(link_ctx *ctx)
 static int skip_ptoken(link_ctx *ctx)
 {
     if (skip_ws(ctx)) {
-        int i;
+        apr_size_t i;
         for (i = ctx->i; i < ctx->slen && ptoken_char(ctx->s[i]); ++i) {
             /* nop */
         }
@@ -1013,7 +1016,7 @@ static int read_link(link_ctx *ctx)
 {
     ctx->link_start = ctx->link_len = 0;
     if (skip_ws(ctx) && read_chr(ctx, '<')) {
-        int end;
+        apr_size_t end;
         if (find_chr(ctx, '>', &end)) {
             ctx->link_start = ctx->i;
             ctx->link_len = end - ctx->link_start;
@@ -1027,7 +1030,7 @@ static int read_link(link_ctx *ctx)
 static int skip_pname(link_ctx *ctx)
 {
     if (skip_ws(ctx)) {
-        int i;
+        apr_size_t i;
         for (i = ctx->i; i < ctx->slen && attr_char(ctx->s[i]); ++i) {
             /* nop */
         }
@@ -1068,7 +1071,7 @@ static int skip_param(link_ctx *ctx)
 
 static int pv_contains(link_ctx *ctx, const char *s)
 {
-    int pvstart = ctx->pv_start;
+    apr_size_t pvstart = ctx->pv_start;
     apr_size_t pvlen = ctx->pv_len;
     
     if (ctx->s[pvstart] == '\"' && pvlen > 1) {
@@ -1078,7 +1081,7 @@ static int pv_contains(link_ctx *ctx, co
     if (pvlen > 0) {
         apr_size_t slen = strlen(s);
         link_ctx pvctx;
-        int i;
+        apr_size_t i;
         
         memset(&pvctx, 0, sizeof(pvctx));
         pvctx.s = ctx->s + pvstart;
@@ -1148,7 +1151,7 @@ static int find_url(void *baton, const c
         
         memset(&ctx, 0, sizeof(ctx));
         ctx.s = value;
-        ctx.slen = (int)strlen(value);
+        ctx.slen = strlen(value);
         
         while (read_link(&ctx)) {
             while (skip_param(&ctx)) {

Modified: httpd/httpd/trunk/modules/md/md_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_version.h?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_version.h (original)
+++ httpd/httpd/trunk/modules/md/md_version.h Fri Sep  1 12:11:38 2017
@@ -26,7 +26,7 @@
  * @macro
  * Version number of the md module as c string
  */
-#define MOD_MD_VERSION "0.7.0-git"
+#define MOD_MD_VERSION "0.8.1"
 
 /**
  * @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 0x000700
+#define MOD_MD_VERSION_NUM 0x000801
 
 #define MD_EXPERIMENTAL 0
 #define MD_ACME_DEF_URL    "https://acme-v01.api.letsencrypt.org/directory"



Mime
View raw message