Commit 46dc37e1 authored by Stefan Eissing's avatar Stefan Eissing
Browse files

On the trunk:

mod_md v0.7.0: 
     - 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
       delayed by 24 hours (or until the existing ones expire, whatever is earler) to accomodate
       for clients with weird clocks, refs #1. 
     - Fixed store sync when MDCAChallenges was removed again from an MD. 
     - Fixed crash when MD matched the base server, fixes #23
     - Fixed watchgod resetting staging when server processes disappeared (e.g. reached
       max requests or other limits).



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1805294 13f79535-47bb-0310-9956-ffa450edef68
parent 102a5dd6
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
                                                         -*- coding: utf-8 -*-
Changes with Apache 2.5.0

  *) mod_md: v0.7.0:
     - 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
       delayed by 24 hours (or until the existing ones expire, whatever is earler) to accomodate
       for clients with weird clocks, refs #1. 
     - Fixed store sync when MDCAChallenges was removed again from an MD. 
     - Fixed crash when MD matched the base server, fixes #23
     - Fixed watchgod resetting staging when server processes disappeared (e.g. reached
       max requests or other limits).
    [Stefan Eissing]
  
  *) mod_proxy: loadfactor parameter can now be a decimal number (eg: 1.25).
     [Jim Jagielski]

+8 −4
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@ struct md_t {
    struct apr_array_header_t *ca_challenges; /* challenge types configured for this MD */

    md_state_t state;               /* state of this MD */
    apr_time_t expires;             /* When the credentials for this domain expire. 0 if unknown */
    apr_time_t valid_from;          /* When the credentials start to be valid. 0 if unknown */
    apr_time_t expires;             /* When the credentials expire. 0 if unknown */
    const char *cert_url;           /* url where cert has been created, remember during drive */ 
    
    const struct md_srv_conf_t *sc; /* server config where it was defined or NULL */
@@ -123,6 +124,7 @@ struct md_t {
#define MD_KEY_TYPE             "type"
#define MD_KEY_URL              "url"
#define MD_KEY_URI              "uri"
#define MD_KEY_VALID_FROM       "validFrom"
#define MD_KEY_VALUE            "value"
#define MD_KEY_VERSION          "version"

@@ -138,9 +140,6 @@ struct md_t {
#define MD_VAL_UPDATE(n,o,s)    ((n)->s != (o)->s)
#define MD_SVAL_UPDATE(n,o,s)   ((n)->s && (!(o)->s || strcmp((n)->s, (o)->s)))

#define MD_SECS_PER_HOUR      (60*60)
#define MD_SECS_PER_DAY       (24*MD_SECS_PER_HOUR)

/**
 * Determine if the Managed Domain contains a specific domain name.
 */
@@ -213,6 +212,11 @@ md_t *md_clone(apr_pool_t *p, const md_t *src);
 */
md_t *md_copy(apr_pool_t *p, const md_t *src);

/**
 * Create a merged md with the settings of add overlaying the ones from base.
 */
md_t *md_merge(apr_pool_t *p, const md_t *add, const md_t *base);

/** 
 * Convert the managed domain into a JSON representation and vice versa. 
 *
+21 −1
Original line number Diff line number Diff line
@@ -651,7 +651,7 @@ static apr_status_t acme_stage(md_proto_driver_t *d)
        rv = md_load(d->store, MD_SG_STAGING, d->md->name, &ad->md, d->p);
        if (APR_SUCCESS == rv) {
            /* So, we have a copy in staging, but is it a recent or an old one? */
            if (!md_is_newer(d->store, MD_SG_STAGING, MD_SG_DOMAINS, d->md->name, d->p)) {
            if (md_is_newer(d->store, MD_SG_DOMAINS, MD_SG_STAGING, d->md->name, d->p)) {
                reset_staging = 1;
            }
        }
@@ -785,6 +785,26 @@ static apr_status_t acme_stage(md_proto_driver_t *d)
                          "%s: retrieving certificate chain", d->md->name);
            rv = ad_chain_install(d);
        }

        if (APR_SUCCESS == rv && ad->cert) {
            apr_time_t now = apr_time_now();
            apr_interval_time_t max_delay, delay_activation; 
            
            /* determine when this cert should be activated */
            d->stage_valid_from = md_cert_get_not_before(ad->cert);
            if (d->md->state == MD_S_COMPLETE && d->md->expires > now) {            
                /**
                 * The MD is complete and un-expired. This is a renewal run. 
                 * Give activation 24 hours leeway (if we have that time) to
                 * accomodate for clients with somewhat weird clocks.
                 */
                delay_activation = apr_time_from_sec(MD_SECS_PER_DAY);
                if (delay_activation > (max_delay = d->md->expires - now)) {
                    delay_activation = max_delay;
                }
                d->stage_valid_from += delay_activation;
            }
        }
    }
out:    
    return rv;
+1 −1
Original line number Diff line number Diff line
@@ -273,7 +273,7 @@ static apr_status_t assess_and_drive(md_cmd_ctx *ctx, md_t *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, ctx->p))) {
        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);
            
            rv = md_reg_load(ctx->reg, md->name, ctx->p);
+29 −0
Original line number Diff line number Diff line
@@ -245,6 +245,26 @@ md_t *md_clone(apr_pool_t *p, const md_t *src)
    return md;   
}

md_t *md_merge(apr_pool_t *p, const md_t *add, const md_t *base)
{
    md_t *n = apr_pcalloc(p, sizeof(*n));

    n->ca_url = add->ca_url? add->ca_url : base->ca_url;
    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;
    if (add->ca_challenges) {
        n->ca_challenges = apr_array_copy(p, add->ca_challenges);
    }
    else if (base->ca_challenges) {
        n->ca_challenges = apr_array_copy(p, base->ca_challenges);
    }
    return n;
}


/**************************************************************************************************/
/* format conversion */

@@ -271,6 +291,11 @@ md_json_t *md_to_json(const md_t *md, apr_pool_t *p)
            apr_rfc822_date(ts, md->expires);
            md_json_sets(ts, json, MD_KEY_CERT, MD_KEY_EXPIRES, NULL);
        }
        if (md->valid_from > 0) {
            char *ts = apr_pcalloc(p, APR_RFC822_DATE_LEN);
            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->ca_challenges && md->ca_challenges->nelts > 0) {
            apr_array_header_t *na;
@@ -303,6 +328,10 @@ md_t *md_from_json(md_json_t *json, apr_pool_t *p)
        if (s && *s) {
            md->expires = apr_date_parse_rfc(s);
        }
        s = md_json_dups(p, json, MD_KEY_CERT, MD_KEY_VALID_FROM, NULL);
        if (s && *s) {
            md->valid_from = apr_date_parse_rfc(s);
        }
        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*));
Loading