Commit 37edb2d0 authored by Stefan Eissing's avatar Stefan Eissing
Browse files

mod_md: v0.6.1 from github

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/trunk-md@1804529 13f79535-47bb-0310-9956-ffa450edef68
parent b062d92c
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ struct md_t {
    apr_interval_time_t renew_window;/* time before expiration that starts renewal */
    
    struct apr_array_header_t *domains; /* all DNS names this MD includes */
    int transitive;                 /* != 0 iff VirtualHost names/aliases are auto-added */
    md_drive_mode_t drive_mode;     /* mode of obtaining credentials */
    int must_staple;                /* certificates should set the OCSP Must Staple extension */
    
@@ -116,6 +117,7 @@ struct md_t {
#define MD_KEY_STATUS           "status"
#define MD_KEY_STORE            "store"
#define MD_KEY_TOKEN            "token"
#define MD_KEY_TRANSITIVE       "transitive"
#define MD_KEY_TYPE             "type"
#define MD_KEY_URL              "url"
#define MD_KEY_URI              "uri"
@@ -140,7 +142,7 @@ struct md_t {
/**
 * Determine if the Managed Domain contains a specific domain name.
 */
int md_contains(const md_t *md, const char *domain);
int md_contains(const md_t *md, const char *domain, int case_sensitive);

/**
 * Determine if the names of the two managed domains overlap.
@@ -150,7 +152,7 @@ int md_domains_overlap(const md_t *md1, const md_t *md2);
/**
 * Determine if the domain names are equal.
 */
int md_equal_domains(const md_t *md1, const md_t *md2);
int md_equal_domains(const md_t *md1, const md_t *md2, int case_sensitive);

/**
 * Determine if the domains in md1 contain all domains of md2.
@@ -184,8 +186,8 @@ md_t *md_get_by_domain(struct apr_array_header_t *mds, const char *domain);
md_t *md_get_by_dns_overlap(struct apr_array_header_t *mds, const md_t *md);

/**
 * Find the managed domain in the list that has the most overlaps in domains to the
 * given md.
 * Find the managed domain in the list that, for the given md, 
 * has the same name, or the most number of overlaps in domains
 */
md_t *md_find_closest_match(apr_array_header_t *mds, const md_t *md);

+39 −39
Original line number Diff line number Diff line
@@ -186,7 +186,7 @@ static apr_status_t ad_setup_authz(md_proto_driver_t *d)
    /* Remove anything we no longer need */
    for (i = 0; i < ad->authz_set->authzs->nelts; ++i) {
        authz = APR_ARRAY_IDX(ad->authz_set->authzs, i, md_acme_authz_t*);
        if (!md_contains(md, authz->domain)) {
        if (!md_contains(md, authz->domain, 0)) {
            md_acme_authz_set_remove(ad->authz_set, authz->domain);
            changed = 1;
        }
@@ -589,7 +589,7 @@ static apr_status_t ad_chain_install(md_proto_driver_t *d)
static apr_status_t acme_driver_init(md_proto_driver_t *d)
{
    md_acme_driver_t *ad;
    apr_status_t rv;
    apr_status_t rv = APR_SUCCESS;

    ad = apr_pcalloc(d->p, sizeof(*ad));
    
@@ -627,43 +627,6 @@ static apr_status_t acme_driver_init(md_proto_driver_t *d)
    
    md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, d->p, "%s: init driver", d->md->name);
    
    rv = md_load(d->store, MD_SG_STAGING, d->md->name, &ad->md, d->p);
    md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, d->p, "%s: checked stage md", d->md->name);
    if (d->reset || APR_STATUS_IS_ENOENT(rv)) {
        /* reset the staging area for this domain */
        rv = md_store_purge(d->store, d->p, MD_SG_STAGING, d->md->name);
        if (APR_SUCCESS != rv && !APR_STATUS_IS_ENOENT(rv)) {
            return rv;
        }
        rv = APR_SUCCESS;
    }
    
    if (ad->md) {
        /* staging in progress.
         * There are certain md properties that are updated in staging, others are only
         * updated in the domains store. Are these still the same? If not, we better
         * start anew.
         */
        if (strcmp(d->md->ca_url, ad->md->ca_url)
            || strcmp(d->md->ca_proto, ad->md->ca_proto)) {
            /* reject staging info in this case */
            ad->md = NULL;
            return APR_SUCCESS;
        }
        
        if (d->md->ca_agreement 
            && (!ad->md->ca_agreement || strcmp(d->md->ca_agreement, ad->md->ca_agreement))) {
            ad->md->ca_agreement = d->md->ca_agreement;
        }
        
        /* look for new ACME account information collected there */
        rv = md_reg_creds_get(&ad->ncreds, d->reg, MD_SG_STAGING, d->md, d->p);
        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, d->p, "%s: checked creds", d->md->name);
        if (APR_STATUS_IS_ENOENT(rv)) {
            rv = APR_SUCCESS;
        }
    }
    
    return rv;
}

@@ -673,6 +636,7 @@ static apr_status_t acme_driver_init(md_proto_driver_t *d)
static apr_status_t acme_stage(md_proto_driver_t *d)
{
    md_acme_driver_t *ad = d->baton;
    int reset_staging = d->reset;
    apr_status_t rv = APR_SUCCESS;
    int renew = 1;

@@ -683,6 +647,42 @@ static apr_status_t acme_stage(md_proto_driver_t *d)
                      apr_array_pstrcat(d->p, ad->ca_challenges, ' '));
    }

    if (!reset_staging) {
        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)) {
                reset_staging = 1;
            }
        }
        else if (APR_STATUS_IS_ENOENT(rv)) {
            reset_staging = 1;
            rv = APR_SUCCESS;
        }
        md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, d->p, 
                      "%s: checked staging area, will%s reset",
                      d->md->name, reset_staging? "" : " not");
    }
    
    if (reset_staging) {
        /* reset the staging area for this domain */
        rv = md_store_purge(d->store, d->p, MD_SG_STAGING, d->md->name);
        if (APR_SUCCESS != rv && !APR_STATUS_IS_ENOENT(rv)) {
            return rv;
        }
        rv = APR_SUCCESS;
        ad->md = NULL;
    }
    
    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);
        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, d->p, "%s: checked creds", d->md->name);
        if (APR_STATUS_IS_ENOENT(rv)) {
            rv = APR_SUCCESS;
        }
    }
    
    /* Find out where we're at with this managed domain */
    if (ad->ncreds && ad->ncreds->pkey && ad->ncreds->cert && ad->ncreds->chain) {
        /* There is a full set staged, to be loaded */
+11 −8
Original line number Diff line number Diff line
@@ -29,9 +29,9 @@
#include "md_util.h"


int md_contains(const md_t *md, const char *domain)
int md_contains(const md_t *md, const char *domain, int case_sensitive)
{
   return md_array_str_index(md->domains, domain, 0, 0) >= 0;
   return md_array_str_index(md->domains, domain, 0, case_sensitive) >= 0;
}

const char *md_common_name(const md_t *md1, const md_t *md2)
@@ -45,7 +45,7 @@ const char *md_common_name(const md_t *md1, const md_t *md2)
    
    for (i = 0; i < md1->domains->nelts; ++i) {
        const char *name1 = APR_ARRAY_IDX(md1->domains, i, const char*);
        if (md_contains(md2, name1)) {
        if (md_contains(md2, name1, 0)) {
            return name1;
        }
    }
@@ -70,7 +70,7 @@ apr_size_t md_common_name_count(const md_t *md1, const md_t *md2)
    hits = 0;
    for (i = 0; i < md1->domains->nelts; ++i) {
        const char *name1 = APR_ARRAY_IDX(md1->domains, i, const char*);
        if (md_contains(md2, name1)) {
        if (md_contains(md2, name1, 0)) {
            ++hits;
        }
    }
@@ -84,19 +84,20 @@ md_t *md_create_empty(apr_pool_t *p)
        md->domains = apr_array_make(p, 5, sizeof(const char *));
        md->contacts = apr_array_make(p, 5, sizeof(const char *));
        md->drive_mode = MD_DRIVE_DEFAULT;
        md->transitive = -1;
        md->defn_name = "unknown";
        md->defn_line_number = 0;
    }
    return md;
}

int md_equal_domains(const md_t *md1, const md_t *md2)
int md_equal_domains(const md_t *md1, const md_t *md2, int case_sensitive)
{
    int i;
    if (md1->domains->nelts == md2->domains->nelts) {
        for (i = 0; i < md1->domains->nelts; ++i) {
            const char *name1 = APR_ARRAY_IDX(md1->domains, i, const char*);
            if (!md_contains(md2, name1)) {
            if (!md_contains(md2, name1, case_sensitive)) {
                return 0;
            }
        }
@@ -111,7 +112,7 @@ int md_contains_domains(const md_t *md1, const md_t *md2)
    if (md1->domains->nelts >= md2->domains->nelts) {
        for (i = 0; i < md2->domains->nelts; ++i) {
            const char *name2 = APR_ARRAY_IDX(md2->domains, i, const char*);
            if (!md_contains(md1, name2)) {
            if (!md_contains(md1, name2, 0)) {
                return 0;
            }
        }
@@ -169,7 +170,7 @@ md_t *md_get_by_domain(struct apr_array_header_t *mds, const char *domain)
    int i;
    for (i = 0; i < mds->nelts; ++i) {
        md_t *md = APR_ARRAY_IDX(mds, i, md_t *);
        if (md_contains(md, domain)) {
        if (md_contains(md, domain, 0)) {
            return md;
        }
    }
@@ -264,6 +265,7 @@ md_json_t *md_to_json(const md_t *md, apr_pool_t *p)
        md_json_sets(md->name, json, MD_KEY_NAME, NULL);
        md_json_setsa(domains, json, MD_KEY_DOMAINS, NULL);
        md_json_setsa(md->contacts, json, MD_KEY_CONTACTS, NULL);
        md_json_setl(md->transitive, json, MD_KEY_TRANSITIVE, NULL);
        md_json_sets(md->ca_account, json, MD_KEY_CA, MD_KEY_ACCOUNT, NULL);
        md_json_sets(md->ca_proto, json, MD_KEY_CA, MD_KEY_PROTO, NULL);
        md_json_sets(md->ca_url, json, MD_KEY_CA, MD_KEY_URL, NULL);
@@ -305,6 +307,7 @@ md_t *md_from_json(md_json_t *json, apr_pool_t *p)
        md->state = (int)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);
        s = md_json_dups(p, json, MD_KEY_CERT, MD_KEY_EXPIRES, NULL);
        if (s && *s) {
            md->expires = apr_date_parse_rfc(s);
+14 −7
Original line number Diff line number Diff line
@@ -357,7 +357,7 @@ static int find_domain(void *baton, md_reg_t *reg, md_t *md)
{
    find_domain_ctx *ctx = baton;
    
    if (md_contains(md, ctx->domain)) {
    if (md_contains(md, ctx->domain, 0)) {
        ctx->md = md;
        return 0;
    }
@@ -685,7 +685,7 @@ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
    md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, 
                  "sync: found %d mds in store", ctx.store_mds->nelts);
    if (APR_SUCCESS == rv) {
        int i, added, fields;
        int i, fields;
        md_t *md, *config_md, *smd, *omd;
        const char *common;
        
@@ -696,11 +696,18 @@ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
            smd = md_find_closest_match(ctx.store_mds, md);
            if (smd) {
                fields = 0;
                /* add any newly configured domains to the store md */
                added = md_array_str_add_missing(smd->domains, md->domains, 0);
                if (added) {
                
                /* Once stored, we keep the name */
                if (strcmp(md->name, smd->name)) {
                    md->name = apr_pstrdup(p, smd->name);
                }
                
                /* Make the stored domain list *exactly* the same, even if
                 * someone only changed upper/lowercase, we'd like to persist that. */
                if (!md_equal_domains(md, smd, 1)) {
                    md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, 
                                 "%s: %d domains added", smd->name, added);
                                 "%s: %d domains changed", smd->name);
                    smd->domains = md_array_str_clone(ptemp, md->domains);
                    fields |= MD_UPD_DOMAINS;
                }
                
@@ -712,7 +719,7 @@ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
                    
                    /* Is this md still configured or has it been abandoned in the config? */
                    config_md = md_get_by_name(ctx.conf_mds, omd->name);
                    if (config_md && md_contains(config_md, common)) {
                    if (config_md && md_contains(config_md, common, 0)) {
                        /* domain used in two configured mds, not allowed */
                        rv = APR_EINVAL;
                        md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, 
+13 −0
Original line number Diff line number Diff line
@@ -138,6 +138,12 @@ apr_status_t md_store_get_fname(const char **pfname,
    return APR_ENOTIMPL;
}

int md_store_is_newer(md_store_t *store, md_store_group_t group1, md_store_group_t group2,  
                      const char *name, const char *aspect, apr_pool_t *p)
{
    return store->is_newer(store, group1, group2, name, aspect, p);
}

/**************************************************************************************************/
/* convenience */

@@ -211,6 +217,13 @@ apr_status_t md_remove(md_store_t *store, apr_pool_t *p,
    return md_util_pool_vdo(p_remove, &ctx, p, name, force, NULL);
}

int md_is_newer(md_store_t *store, md_store_group_t group1, md_store_group_t group2,  
                      const char *name, apr_pool_t *p)
{
    return md_store_is_newer(store, group1, group2, name, MD_FN_MD, p);
}


typedef struct {
    apr_pool_t *p;
    apr_array_header_t *mds;
Loading