]> granicus.if.org Git - apache/commitdiff
On the trunk:
authorStefan Eissing <icing@apache.org>
Fri, 11 Aug 2017 13:04:29 +0000 (13:04 +0000)
committerStefan Eissing <icing@apache.org>
Fri, 11 Aug 2017 13:04:29 +0000 (13:04 +0000)
mod_md: some internal refactoring of config/sectio handling

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1804787 13f79535-47bb-0310-9956-ffa450edef68

modules/md/md.h
modules/md/md_cmd_reg.c
modules/md/md_cmd_store.c
modules/md/md_core.c
modules/md/mod_md.c
modules/md/mod_md_config.c
modules/md/mod_md_config.h

index 7f543a09e6b5676672b2749b848f8b73bc5dd814..91a2988ff2801bbf53a541b6b48fed0004898fef 100644 (file)
@@ -24,6 +24,7 @@ struct md_json_t;
 struct md_cert_t;
 struct md_pkey_t;
 struct md_store_t;
+struct md_srv_conf_t;
 
 #define MD_TLSSNI01_DNS_SUFFIX     ".acme.invalid"
 
@@ -64,24 +65,25 @@ typedef enum {
 typedef struct md_t md_t;
 struct md_t {
     const char *name;               /* unique name of 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_interval_time_t renew_window;/* time before expiration that starts renewal */
-    
     struct apr_array_header_t *domains; /* all DNS names this MD includes */
+    struct apr_array_header_t *contacts;   /* list of contact uris, e.g. mailto:xxx */
+
     int transitive;                 /* != 0 iff VirtualHost names/aliases are auto-added */
-    md_drive_mode_t drive_mode;     /* mode of obtaining credentials */
+    int drive_mode;                 /* mode of obtaining credentials */
     int must_staple;                /* certificates should set the OCSP Must Staple extension */
+    apr_interval_time_t renew_window;/* time before expiration that starts renewal */
     
     const char *ca_url;             /* url of CA certificate service */
     const char *ca_proto;           /* protocol used vs CA (e.g. ACME) */
     const char *ca_account;         /* account used at CA */
     const char *ca_agreement;       /* accepted agreement uri between CA and user */ 
     struct apr_array_header_t *ca_challenges; /* challenge types configured for this MD */
-    struct apr_array_header_t *contacts;   /* list of contact uris, e.g. mailto:xxx */
 
+    md_state_t state;               /* state of this MD */
+    apr_time_t expires;             /* When the credentials for this domain 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 */
     const char *defn_name;          /* config file this MD was defined */
     unsigned defn_line_number;      /* line number of definition */
 };
@@ -199,7 +201,7 @@ md_t *md_create_empty(apr_pool_t *p);
 /**
  * Create a managed domain, given a list of domain names.
  */
-const char *md_create(md_t **pmd, apr_pool_t *p, struct apr_array_header_t *domains);
+md_t *md_create(apr_pool_t *p, struct apr_array_header_t *domains);
 
 /**
  * Deep copy an md record into another pool.
index 2fc107d420170d99b8163d4e1cdb76904f54cd05..12f7018a5b3a00decf08bd8d6bf84ecfab62413a 100644 (file)
 static apr_status_t cmd_reg_add(md_cmd_ctx *ctx, const md_cmd_t *cmd)
 {
     md_t *md;
-    const char *err;
     apr_status_t rv;
 
-    err = md_create(&md, ctx->p, md_cmd_gather_args(ctx, 0));
-    if (err) {
+    md = md_create(ctx->p, md_cmd_gather_args(ctx, 0));
+    if (md->domains->nelts == 0) {
         return APR_EINVAL;
     }
 
index 41b75a07a7d52e15596342363aa4c095ec853bed..56c4f2712fc9632226d0eda824d2065ca9d61e9e 100644 (file)
 static apr_status_t cmd_add(md_cmd_ctx *ctx, const md_cmd_t *cmd) 
 {
     md_t *md, *nmd;
-    const char *err;
     apr_status_t rv;
 
-    err = md_create(&md, ctx->p, md_cmd_gather_args(ctx, 0));
-    if (err) {
+    md = md_create(ctx->p, md_cmd_gather_args(ctx, 0));
+    if (md->domains->nelts == 0) {
         return APR_EINVAL;
     }
 
index 0a67e85ebb5bf208aa48b1bb092dc68fff4454cf..7506ff63ac8e2a962864fbad75be13eb0778ad1e 100644 (file)
@@ -189,24 +189,15 @@ md_t *md_get_by_dns_overlap(struct apr_array_header_t *mds, const md_t *md)
     return NULL;
 }
 
-const char *md_create(md_t **pmd, apr_pool_t *p, apr_array_header_t *domains)
+md_t *md_create(apr_pool_t *p, apr_array_header_t *domains)
 {
     md_t *md;
     
-    if (domains->nelts <= 0) {
-        return "needs at least one domain name";
-    }
-    
     md = md_create_empty(p);
-    if (!md) {
-        return "not enough memory";
-    }
-
     md->domains = md_array_str_compact(p, domains, 0);
     md->name = APR_ARRAY_IDX(md->domains, 0, const char *);
     
-    *pmd = md;
-    return NULL;   
+    return md;
 }
 
 /**************************************************************************************************/
index 7d0814fe8fea6f13f79ff1cb870d1dac2e8f0458..1d4abeaf9b693754fd6de5e6b4146434d1131455 100644 (file)
@@ -47,126 +47,46 @@ static void md_hooks(apr_pool_t *pool);
 
 AP_DECLARE_MODULE(md) = {
     STANDARD20_MODULE_STUFF,
-    md_config_create_dir, /* func to create per dir config */
-    md_config_merge_dir,  /* func to merge per dir config */
+    NULL,                 /* func to create per dir config */
+    NULL,                 /* func to merge per dir config */
     md_config_create_svr, /* func to create per server config */
     md_config_merge_svr,  /* func to merge per server config */
     md_cmds,              /* command handlers */
     md_hooks
 };
 
-typedef struct {
-    apr_array_header_t *mds;
-    apr_array_header_t *unused_names;
-    int can_http;
-    int can_https;
-} md_ctx;
-static apr_status_t md_calc_md_list(md_ctx *ctx, apr_pool_t *p, apr_pool_t *plog,
-                                    apr_pool_t *ptemp, server_rec *base_server)
+static void md_merge_srv(md_t *md, md_srv_conf_t *base_sc, apr_pool_t *p)
 {
-    server_rec *s;
-    apr_array_header_t *mds;
-    int i, j;
-    md_t *md, *nmd;
-    const char *domain;
-    apr_status_t rv = APR_SUCCESS;
-    md_config_t *config;
-    apr_port_t effective_80, effective_443;
-    ap_listen_rec *lr;
-    apr_sockaddr_t *sa;
-
-    ctx->can_http = 0;
-    ctx->can_https = 0;
-    mds = apr_array_make(p, 5, sizeof(const md_t*));
-
-    config = (md_config_t *)md_config_get(base_server);
-    effective_80 = md_config_geti(config, MD_CONFIG_LOCAL_80);
-    effective_443 = md_config_geti(config, MD_CONFIG_LOCAL_443);
-    
-    for (lr = ap_listeners; lr; lr = lr->next) {
-        for (sa = lr->bind_addr; sa; sa = sa->next) {
-            if  (sa->port == effective_80 
-                 && (!lr->protocol || !strncmp("http", lr->protocol, 4))) {
-                ctx->can_http = 1;
-            }
-            else if (sa->port == effective_443
-                     && (!lr->protocol || !strncmp("http", lr->protocol, 4))) {
-                ctx->can_https = 1;
-            }
-        }
+    if (!md->sc) {
+        md->sc = base_sc;
     }
-    
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10037)
-                 "server seems%s reachable via http: (port 80->%d) "
-                 "and%s reachable via https: (port 443->%d) ",
-                 ctx->can_http? "" : " not", effective_80,
-                 ctx->can_https? "" : " not", effective_443);
-    
-    for (s = base_server; s; s = s->next) {
-        config = (md_config_t *)md_config_get(s);
-
-        for (i = 0; i < config->mds->nelts; ++i) {
-            nmd = APR_ARRAY_IDX(config->mds, i, md_t*);
 
-            for (j = 0; j < mds->nelts; ++j) {
-                md = APR_ARRAY_IDX(mds, j, md_t*);
-
-                if (nmd == md) {
-                    nmd = NULL;
-                    break; /* merged between different configs */
-                }
-                
-                if ((domain = md_common_name(nmd, md)) != NULL) {
-                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server, APLOGNO(10038)
-                                 "two Managed Domains have an overlap in domain '%s'"
-                                 ", first definition in %s(line %d), second in %s(line %d)",
-                                 domain, md->defn_name, md->defn_line_number,
-                                 nmd->defn_name, nmd->defn_line_number);
-                    return APR_EINVAL;
-                }
-            }
-            
-            if (nmd) {
-                /* new managed domain not seen before */
-                if (!nmd->ca_url) {
-                    nmd->ca_url = md_config_gets(config, MD_CONFIG_CA_URL);
-                }
-                if (!nmd->ca_proto) {
-                    nmd->ca_proto = md_config_gets(config, MD_CONFIG_CA_PROTO);
-                }
-                if (!nmd->ca_agreement) {
-                    nmd->ca_agreement = md_config_gets(config, MD_CONFIG_CA_AGREEMENT);
-                }
-                if (s->server_admin && strcmp(DEFAULT_ADMIN, s->server_admin)) {
-                    apr_array_clear(nmd->contacts);
-                    APR_ARRAY_PUSH(nmd->contacts, const char *) = 
-                        md_util_schemify(p, s->server_admin, "mailto");
-                }
-                if (nmd->drive_mode == MD_DRIVE_DEFAULT) {
-                    nmd->drive_mode = md_config_geti(config, MD_CONFIG_DRIVE_MODE);
-                }
-                if (nmd->renew_window <= 0) {
-                    nmd->renew_window = md_config_get_interval(config, MD_CONFIG_RENEW_WINDOW);
-                }
-                if (nmd->transitive < 0) {
-                    nmd->transitive = md_config_geti(config, MD_CONFIG_TRANSITIVE);
-                }
-                if (!nmd->ca_challenges && config->ca_challenges) {
-                    nmd->ca_challenges = apr_array_copy(p, config->ca_challenges);
-                }
-                APR_ARRAY_PUSH(mds, md_t *) = nmd;
-                
-                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10039)
-                             "Added MD[%s, CA=%s, Proto=%s, Agreement=%s, Drive=%d, renew=%ld]",
-                             nmd->name, nmd->ca_url, nmd->ca_proto, nmd->ca_agreement,
-                             nmd->drive_mode, (long)nmd->renew_window);
-            }
-        }
+    if (!md->ca_url) {
+        md->ca_url = md_config_gets(md->sc, MD_CONFIG_CA_URL);
     }
-    
-    ctx->mds = (APR_SUCCESS == rv)? mds : NULL;
-    return rv;
+    if (!md->ca_proto) {
+        md->ca_proto = md_config_gets(md->sc, MD_CONFIG_CA_PROTO);
+    }
+    if (!md->ca_agreement) {
+        md->ca_agreement = md_config_gets(md->sc, MD_CONFIG_CA_AGREEMENT);
+    }
+    if (md->sc->s->server_admin && strcmp(DEFAULT_ADMIN, md->sc->s->server_admin)) {
+        apr_array_clear(md->contacts);
+        APR_ARRAY_PUSH(md->contacts, const char *) = 
+        md_util_schemify(p, md->sc->s->server_admin, "mailto");
+    }
+    if (md->drive_mode == MD_DRIVE_DEFAULT) {
+        md->drive_mode = md_config_geti(md->sc, MD_CONFIG_DRIVE_MODE);
+    }
+    if (md->renew_window <= 0) {
+        md->renew_window = md_config_get_interval(md->sc, MD_CONFIG_RENEW_WINDOW);
+    }
+    if (md->transitive < 0) {
+        md->transitive = md_config_geti(md->sc, MD_CONFIG_TRANSITIVE);
+    }
+    if (!md->ca_challenges && md->sc->ca_challenges) {
+        md->ca_challenges = apr_array_copy(p, md->sc->ca_challenges);
+    }        
 }
 
 static apr_status_t check_coverage(md_t *md, const char *domain, server_rec *s, apr_pool_t *p)
@@ -188,93 +108,171 @@ static apr_status_t check_coverage(md_t *md, const char *domain, server_rec *s,
     }
 }
 
-static apr_status_t md_check_vhost_mapping(md_ctx *ctx, apr_pool_t *p, apr_pool_t *plog,
-                                           apr_pool_t *ptemp, server_rec *base_server)
+static apr_status_t apply_to_servers(md_t *md, server_rec *base_server, 
+                                     apr_pool_t *p, apr_pool_t *ptemp)
 {
     server_rec *s;
     request_rec r;
-    md_config_t *config;
+    md_srv_conf_t *sc;
+    md_mod_conf_t *mc;
     apr_status_t rv = APR_SUCCESS, rv2;
-    md_t *md;
-    int i, j, k;
+    int i, j;
     const char *domain, *name;
     
+    sc = md_config_get(base_server);
+    mc = sc->mc;
+    
     /* Find the (at most one) managed domain for each vhost/base server and
      * remember it at our config for it. 
      * The config is not accepted, if a vhost matches 2 or more managed domains.
      */
-    ctx->unused_names = apr_array_make(p, 5, sizeof(const char*));
     memset(&r, 0, sizeof(r));
-    for (i = 0; i < ctx->mds->nelts; ++i) {
-        md = APR_ARRAY_IDX(ctx->mds, i, md_t*);
-        config = NULL;
-        /* This MD may apply to 0, 1 or more sever_recs */
-        for (s = base_server; s; s = s->next) {
-            r.server = s;
-            for (j = 0; j < md->domains->nelts; ++j) {
-                domain = APR_ARRAY_IDX(md->domains, j, const char*);
+    sc = NULL;
+        
+    /* This MD may apply to 0, 1 or more sever_recs */
+    for (s = base_server; s; s = s->next) {
+        r.server = s;
+        
+        for (i = 0; i < md->domains->nelts; ++i) {
+            domain = APR_ARRAY_IDX(md->domains, i, const char*);
+            
+            if (ap_matches_request_vhost(&r, domain, s->port)) {
+                /* Create a unique md_srv_conf_t record for this server. 
+                 * We keep local information here. */
+                sc = md_config_get_unique(s, p);
                 
-                if (ap_matches_request_vhost(&r, domain, s->port)) {
-                    /* Create a unique md_config_t record for this server. 
-                     * We keep local information here. */
-                    config = (md_config_t *)md_config_get_unique(s, p);
+                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10041)
+                             "Server %s:%d matches md %s (config %s)", 
+                             s->server_hostname, s->port, md->name, sc->name);
                 
-                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10041)
-                                 "Server %s:%d matches md %s (config %s)", 
-                                 s->server_hostname, s->port, md->name, config->name);
-                    
-                    if (config->md == md) {
-                        /* already matched via another domain name */
-                    }
-                    else if (config->md) {
-                         
-                        ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server, APLOGNO(10042)
-                                     "conflict: MD %s matches server %s, but MD %s also matches.",
-                                     md->name, s->server_hostname, config->md->name);
-                        rv = APR_EINVAL;
-                        goto next_server;
-                    }
-                    
-                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10043)
-                                 "Managed Domain %s applies to vhost %s:%d", md->name,
-                                 s->server_hostname, s->port);
-                    if (s->server_admin && strcmp(DEFAULT_ADMIN, s->server_admin)) {
-                        apr_array_clear(md->contacts);
-                        APR_ARRAY_PUSH(md->contacts, const char *) = 
-                            md_util_schemify(p, s->server_admin, "mailto");
-                        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10044)
-                                     "Managed Domain %s assigned server admin %s", md->name,
-                                     s->server_admin);
-                    }
-                    config->md = md;
-
-                    /* This server matches a managed domain. If it contains names or
-                     * alias that are not in this md, a generated certificate will not match. */
-                    if (APR_SUCCESS == (rv2 = check_coverage(md, s->server_hostname, s, p))) {
-                        for (k = 0; k < s->names->nelts; ++k) {
-                            name = APR_ARRAY_IDX(s->names, k, const char*);
-                            if (APR_SUCCESS != (rv2 = check_coverage(md, name, s, p))) {
-                                break;
-                            }
+                if (sc->md == md) {
+                    /* already matched via another domain name */
+                    goto next_server;
+                }
+                else if (sc->md) {
+                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server, APLOGNO(10042)
+                                 "conflict: MD %s matches server %s, but MD %s also matches.",
+                                 md->name, s->server_hostname, sc->md->name);
+                    rv = APR_EINVAL;
+                    goto next_server;
+                }
+                
+                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10043)
+                             "Managed Domain %s applies to vhost %s:%d", md->name,
+                             s->server_hostname, s->port);
+                
+                /* If there is a non-default ServerAdmin defined for this vhost, take
+                 * that one as contact info */
+                if (s->server_admin && strcmp(DEFAULT_ADMIN, s->server_admin)) {
+                    apr_array_clear(md->contacts);
+                    APR_ARRAY_PUSH(md->contacts, const char *) = 
+                    md_util_schemify(p, s->server_admin, "mailto");
+                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10044)
+                                 "Managed Domain %s assigned server admin %s", md->name,
+                                 s->server_admin);
+                }
+                /* remember */
+                sc->md = md;
+                
+                /* This server matches a managed domain. If it contains names or
+                 * alias that are not in this md, a generated certificate will not match. */
+                if (APR_SUCCESS == (rv2 = check_coverage(md, s->server_hostname, s, p))) {
+                    for (j = 0; j < s->names->nelts; ++j) {
+                        name = APR_ARRAY_IDX(s->names, j, const char*);
+                        if (APR_SUCCESS != (rv2 = check_coverage(md, name, s, p))) {
+                            break;
                         }
                     }
-                    if (APR_SUCCESS != rv2) {
-                        rv = rv2;
-                    }
-                    goto next_server;
                 }
+                
+                if (APR_SUCCESS != rv2) {
+                    rv = rv2;
+                }
+                goto next_server;
             }
-next_server:
-            continue;
         }
-        
-        if (config == NULL && md->drive_mode != MD_DRIVE_ALWAYS) {
-            /* Not an error, but looks suspicious */
-            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(10045)
-                         "No VirtualHost matches Managed Domain %s", md->name);
-            APR_ARRAY_PUSH(ctx->unused_names, const char*)  = md->name;
+    next_server:
+        continue;
+    }
+    
+    if (sc == NULL && md->drive_mode != MD_DRIVE_ALWAYS) {
+        /* Not an error, but looks suspicious */
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(10045)
+                     "No VirtualHost matches Managed Domain %s", md->name);
+        APR_ARRAY_PUSH(mc->unused_names, const char*)  = md->name;
+    }
+    return rv;
+}
+
+static apr_status_t md_calc_md_list(apr_pool_t *p, apr_pool_t *plog,
+                                    apr_pool_t *ptemp, server_rec *base_server)
+{
+    md_srv_conf_t *sc;
+    md_mod_conf_t *mc;
+    md_t *md, *omd;
+    const char *domain;
+    apr_status_t rv = APR_SUCCESS;
+    ap_listen_rec *lr;
+    apr_sockaddr_t *sa;
+    int i, j;
+
+    sc = md_config_get(base_server);
+    mc = sc->mc;
+    
+    mc->can_http = 0;
+    mc->can_https = 0;
+
+    for (lr = ap_listeners; lr; lr = lr->next) {
+        for (sa = lr->bind_addr; sa; sa = sa->next) {
+            if  (sa->port == mc->local_80 
+                 && (!lr->protocol || !strncmp("http", lr->protocol, 4))) {
+                mc->can_http = 1;
+            }
+            else if (sa->port == mc->local_443
+                     && (!lr->protocol || !strncmp("http", lr->protocol, 4))) {
+                mc->can_https = 1;
+            }
+        }
+    }
+    
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10037)
+                 "server seems%s reachable via http: (port 80->%d) "
+                 "and%s reachable via https: (port 443->%d) ",
+                 mc->can_http? "" : " not", mc->local_80,
+                 mc->can_https? "" : " not", mc->local_443);
+    
+    /* Complete the properties of the MDs, now that we have the complete, merged
+     * server configurations. 
+     */
+    for (i = 0; i < mc->mds->nelts; ++i) {
+        md = APR_ARRAY_IDX(mc->mds, i, md_t*);
+        md_merge_srv(md, sc, p);
+
+        /* Check that we have no overlap with the MDs already completed */
+        for (j = 0; j < i; ++j) {
+            omd = APR_ARRAY_IDX(mc->mds, j, md_t*);
+            if ((domain = md_common_name(md, omd)) != NULL) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server, APLOGNO(10038)
+                             "two Managed Domains have an overlap in domain '%s'"
+                             ", first definition in %s(line %d), second in %s(line %d)",
+                             domain, md->defn_name, md->defn_line_number,
+                             omd->defn_name, omd->defn_line_number);
+                return APR_EINVAL;
+            }
         }
+
+        /* Apply to the vhost(s) that this MD matches - if any. Perform some
+         * last finishing touches on the MD. */
+        if (APR_SUCCESS != (rv = apply_to_servers(md, base_server, p, ptemp))) {
+            return rv;
+        }
+
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10039)
+                     "COmpleted MD[%s, CA=%s, Proto=%s, Agreement=%s, Drive=%d, renew=%ld]",
+                     md->name, md->ca_url, md->ca_proto, md->ca_agreement,
+                     md->drive_mode, (long)md->renew_window);
     }
+    
     return rv;
 }
 
@@ -325,17 +323,14 @@ static apr_status_t check_group_dir(md_store_t *store, md_store_group_t group,
     return rv;
 }
 
-static apr_status_t setup_store(md_store_t **pstore, apr_pool_t *p, server_rec *s,
+static apr_status_t setup_store(md_mod_conf_t *mc, apr_pool_t *p, server_rec *s,
                                 int post_config)
 {
     const char *base_dir;
-    md_config_t *config;
     md_store_t *store;
     apr_status_t rv;
     
-    config = (md_config_t *)md_config_get(s);
-    base_dir = md_config_gets(config, MD_CONFIG_BASE_DIR);
-    base_dir = ap_server_root_relative(p, base_dir);
+    base_dir = ap_server_root_relative(p, mc->base_dir);
     
     if (APR_SUCCESS != (rv = md_store_fs_init(&store, p, base_dir))) {
         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10046)"setup store for %s", base_dir);
@@ -359,28 +354,24 @@ static apr_status_t setup_store(md_store_t **pstore, apr_pool_t *p, server_rec *
                          "setup accounts directory");
             goto out;
         }
-        
     }
     
-    config->store = store;
-    for (s = s->next; s; s = s->next) {
-        config = (md_config_t *)md_config_get(s);
-        config->store = store;
-    }
+    mc->store = store;
 out:
-    *pstore = (APR_SUCCESS == rv)? store : NULL;
     return rv;
 }
 
 static apr_status_t setup_reg(md_reg_t **preg, apr_pool_t *p, server_rec *s, int post_config)
 {
-    md_config_t *config;
+    md_srv_conf_t *sc;
+    md_mod_conf_t *mc;
     apr_status_t rv;
     
-    config = (md_config_t *)md_config_get(s);
-    if (config->store 
-        || APR_SUCCESS == (rv = setup_store(&config->store, p, s, post_config))) {
-        return md_reg_init(preg, p, config->store);
+    sc = md_config_get(s);
+    mc = sc->mc;
+    
+    if (mc->store || APR_SUCCESS == (rv = setup_store(mc, p, s, post_config))) {
+        return md_reg_init(preg, p, mc->store);
     }
     return rv;
 }
@@ -706,7 +697,8 @@ static apr_status_t md_post_config(apr_pool_t *p, apr_pool_t *plog,
 {
     const char *mod_md_init_key = "mod_md_init_counter";
     void *data = NULL;
-    md_ctx ctx;
+    md_srv_conf_t *sc;
+    md_mod_conf_t *mc;
     apr_array_header_t *drive_names;
     md_reg_t *reg;
     apr_status_t rv = APR_SUCCESS;
@@ -726,38 +718,33 @@ static apr_status_t md_post_config(apr_pool_t *p, apr_pool_t *plog,
     }
 
     init_setups(p, s);
-    memset(&ctx, 0, sizeof(ctx));
     
     md_log_set(log_is_level, log_print, NULL);
 
+    sc = md_config_get(s);
+    mc = sc->mc;
+    
     /* 1. Check uniqueness of MDs, calculate global, configured MD list.
      * If successful, we have a list of MD definitions that do not overlap. */
     /* We also need to find out if we can be reached on 80/443 from the outside (e.g. the CA) */
-    if (APR_SUCCESS != (rv = md_calc_md_list(&ctx, p, plog, ptemp, s))) {
+    if (APR_SUCCESS != (rv = md_calc_md_list(p, plog, ptemp, s))) {
         goto out;
     }
     
-    /* 2. Check mappings of MDs to VirtulHosts defined.
-     * If successful, we have assigned MDs to server_recs in a unique way. Each server_rec
-     * config will carry 0 or 1 MD record. */
-    if (APR_SUCCESS != (rv = md_check_vhost_mapping(&ctx, p, plog, ptemp, s))) {
-        goto out;
-    }    
-    
-    /* 3. Synchronize the defintions we now have with the store via a registry (reg). */
+    /* 2. Synchronize the defintions we now have with the store via a registry (reg). */
     if (APR_SUCCESS != (rv = setup_reg(&reg, p, s, 1))) {
         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10072)
                      "setup md registry");
         goto out;
     }
-    if (APR_SUCCESS != (rv = md_reg_sync(reg, p, ptemp, ctx.mds, 
-                                         ctx.can_http, ctx.can_https))) {
+    if (APR_SUCCESS != (rv = md_reg_sync(reg, p, ptemp, mc->mds, 
+                                         mc->can_http, mc->can_https))) {
         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10073)
-                     "synching %d mds to registry", ctx.mds->nelts);
+                     "synching %d mds to registry", mc->mds->nelts);
         goto out;
     }
     
-    /* Determine the managed domains that are in auto drive_mode. For those,
+    /* 3. Determine the managed domains that are in auto drive_mode. For those,
      * determine in which state they are:
      *  - UNKNOWN:            should not happen, report, dont drive
      *  - ERROR:              something we do not know how to fix, report, dont drive
@@ -766,12 +753,12 @@ static apr_status_t md_post_config(apr_pool_t *p, apr_pool_t *plog,
      *
      * Start the watchdog if we have anything, now or in the future.
      */
-    drive_names = apr_array_make(ptemp, ctx.mds->nelts+1, sizeof(const char *));
-    for (i = 0; i < ctx.mds->nelts; ++i) {
-        md = APR_ARRAY_IDX(ctx.mds, i, const md_t *);
+    drive_names = apr_array_make(ptemp, mc->mds->nelts+1, sizeof(const char *));
+    for (i = 0; i < mc->mds->nelts; ++i) {
+        md = APR_ARRAY_IDX(mc->mds, i, const md_t *);
         switch (md->drive_mode) {
             case MD_DRIVE_AUTO:
-                if (md_array_str_index(ctx.unused_names, md->name, 0, 0) >= 0) {
+                if (md_array_str_index(mc->unused_names, md->name, 0, 0) >= 0) {
                     break;
                 }
                 /* fall through */
@@ -784,10 +771,11 @@ static apr_status_t md_post_config(apr_pool_t *p, apr_pool_t *plog,
         }
     }
     
+    /* 4. I there are MDs to drive, start a watchdog to check on them regularly */
     if (drive_names->nelts > 0) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(10074)
                      "%d out of %d mds are configured for auto-drive", 
-                     drive_names->nelts, ctx.mds->nelts);
+                     drive_names->nelts, mc->mds->nelts);
     
         load_stage_sets(drive_names, p, reg, s);
         md_http_use_implementation(md_curl_get_impl(p));
@@ -806,7 +794,7 @@ out:
 
 static int md_is_managed(server_rec *s)
 {
-    md_config_t *conf = (md_config_t *)md_config_get(s);
+    md_srv_conf_t *conf = md_config_get(s);
 
     if (conf && conf->md) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(10076) 
@@ -823,18 +811,21 @@ static apr_status_t md_get_credentials(server_rec *s, apr_pool_t *p,
                                        const char **pchainfile)
 {
     apr_status_t rv = APR_ENOENT;    
-    md_config_t *conf;
+    md_srv_conf_t *sc;
     md_reg_t *reg;
     const md_t *md;
     
     *pkeyfile = NULL;
     *pcertfile = NULL;
     *pchainfile = NULL;
-    conf = (md_config_t *)md_config_get(s);
     
-    if (conf && conf->md && conf->store) {
-        if (APR_SUCCESS == (rv = md_reg_init(&reg, p, conf->store))) {
-            md = md_reg_get(reg, conf->md->name, p);
+    sc = md_config_get(s);
+    
+    if (sc && sc->md) {
+        assert(sc->mc);
+        assert(sc->mc->store);
+        if (APR_SUCCESS == (rv = md_reg_init(&reg, p, sc->mc->store))) {
+            md = md_reg_get(reg, sc->md->name, p);
             if (md->state != MD_S_COMPLETE) {
                 return APR_EAGAIN;
             }
@@ -850,7 +841,7 @@ static apr_status_t md_get_credentials(server_rec *s, apr_pool_t *p,
 static int md_is_challenge(conn_rec *c, const char *servername,
                            X509 **pcert, EVP_PKEY **pkey)
 {
-    md_config_t *conf;
+    md_srv_conf_t *sc;
     apr_size_t slen, sufflen = sizeof(MD_TLSSNI01_DNS_SUFFIX) - 1;
     apr_status_t rv;
 
@@ -860,9 +851,9 @@ static int md_is_challenge(conn_rec *c, const char *servername,
         return 0;
     }
     
-    conf = (md_config_t *)md_config_get(c->base_server);
-    if (conf && conf->store) {
-        md_store_t *store = conf->store;
+    sc = md_config_get(c->base_server);
+    if (sc && sc->mc->store) {
+        md_store_t *store = sc->mc->store;
         md_cert_t *mdcert;
         md_pkey_t *mdpkey;
         
@@ -897,23 +888,21 @@ static int md_is_challenge(conn_rec *c, const char *servername,
 static int md_http_challenge_pr(request_rec *r)
 {
     apr_bucket_brigade *bb;
-    const md_config_t *conf;
-    const char *base_dir, *name, *data;
+    const md_srv_conf_t *sc;
+    const char *name, *data;
     apr_status_t rv;
             
     if (!strncmp(ACME_CHALLENGE_PREFIX, r->parsed_uri.path, sizeof(ACME_CHALLENGE_PREFIX)-1)) {
         if (r->method_number == M_GET) {
             md_store_t *store;
         
-            conf = ap_get_module_config(r->server->module_config, &md_module);
-            store = conf->store;
+            sc = ap_get_module_config(r->server->module_config, &md_module);
+            store = sc? sc->mc->store : NULL;
             
-            base_dir = md_config_gets(conf, MD_CONFIG_BASE_DIR);
             name = r->parsed_uri.path + sizeof(ACME_CHALLENGE_PREFIX)-1;
 
             r->status = HTTP_NOT_FOUND;
             if (!ap_strchr_c(name, '/') && store) {
-                base_dir = ap_server_root_relative(r->pool, base_dir);
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
                               "Challenge for %s (%s)", r->hostname, r->uri);
 
@@ -935,7 +924,7 @@ static int md_http_challenge_pr(request_rec *r)
                 }
                 else if (APR_ENOENT != rv) {
                     ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10081)
-                                  "loading challenge %s from store %s", name, base_dir);
+                                  "loading challenge %s from store", name);
                     return HTTP_INTERNAL_SERVER_ERROR;
                 }
             }
index e5823453ff8a37e265328acd32bb2acb35017d2d..b93d96db98fb7c94cb3f38fd4706188bf554ad49 100644 (file)
 
 #define DEF_VAL     (-1)
 
-static md_config_t defconf = {
-    "default",
+/* Default settings for the global conf */
+static md_mod_conf_t defmc = {
+    NULL,
+    "md",
     NULL,
     80,
     443,
+    0,
+    0,
+    NULL
+};
+
+/* Default server specific setting */
+static md_srv_conf_t defconf = {
+    "default",
     NULL,
+    &defmc,
+
+    1,
+    MD_DRIVE_AUTO,
+    0,
+    apr_time_from_sec(14 * MD_SECS_PER_DAY),
+
     MD_ACME_DEF_URL,
     "ACME",
-    NULL, 
     NULL,
-    MD_DRIVE_AUTO,
-    apr_time_from_sec(14 * MD_SECS_PER_DAY),
-    1,  
-    NULL, 
-    "md",
-    NULL
+    NULL,
+    NULL,
 };
 
+static md_mod_conf_t *mod_md_config;
+
+static apr_status_t cleanup_mod_config(void *dummy)
+{
+    (void)dummy;
+    mod_md_config = NULL;
+    return APR_SUCCESS;
+}
+
+static md_mod_conf_t *md_mod_conf_get(apr_pool_t *pool, int create)
+{
+    if (mod_md_config) {
+        return mod_md_config; /* reused for lifetime of the pool */
+    }
+
+    if (create) {
+        mod_md_config = apr_pcalloc(pool, sizeof(*mod_md_config));
+        memcpy(mod_md_config, &defmc, sizeof(*mod_md_config));
+        mod_md_config->mds = apr_array_make(pool, 5, sizeof(const md_t *));
+        mod_md_config->unused_names = apr_array_make(pool, 5, sizeof(const md_t *));
+        
+        apr_pool_cleanup_register(pool, NULL, cleanup_mod_config, apr_pool_cleanup_null);
+    }
+    
+    return mod_md_config;
+}
+
 #define CONF_S_NAME(s)  (s && s->server_hostname? s->server_hostname : "default")
 
+static void srv_conf_props_clear(md_srv_conf_t *sc)
+{
+    sc->transitive = DEF_VAL;
+    sc->drive_mode = DEF_VAL;
+    sc->must_staple = DEF_VAL;
+    sc->renew_window = DEF_VAL;
+    sc->ca_url = NULL;
+    sc->ca_proto = NULL;
+    sc->ca_agreement = NULL;
+    sc->ca_challenges = NULL;
+}
+
+static void srv_conf_props_copy(md_srv_conf_t *to, const md_srv_conf_t *from)
+{
+    to->transitive = from->transitive;
+    to->drive_mode = from->drive_mode;
+    to->must_staple = from->must_staple;
+    to->renew_window = from->renew_window;
+    to->ca_url = from->ca_url;
+    to->ca_proto = from->ca_proto;
+    to->ca_agreement = from->ca_agreement;
+    to->ca_challenges = from->ca_challenges;
+}
+
+static void srv_conf_props_apply(md_t *md, const md_srv_conf_t *from, apr_pool_t *p)
+{
+    if (from->transitive != DEF_VAL) md->transitive = from->transitive;
+    if (from->drive_mode != DEF_VAL) md->drive_mode = from->drive_mode;
+    if (from->must_staple != DEF_VAL) md->must_staple = from->must_staple;
+    if (from->renew_window != DEF_VAL) md->renew_window = from->renew_window;
+
+    if (from->ca_url) md->ca_url = from->ca_url;
+    if (from->ca_proto) md->ca_proto = from->ca_proto;
+    if (from->ca_agreement) md->ca_agreement = from->ca_agreement;
+    if (from->ca_challenges) md->ca_challenges = apr_array_copy(p, from->ca_challenges);
+}
+
 void *md_config_create_svr(apr_pool_t *pool, server_rec *s)
 {
-    md_config_t *conf = (md_config_t *)apr_pcalloc(pool, sizeof(md_config_t));
+    md_srv_conf_t *conf = (md_srv_conf_t *)apr_pcalloc(pool, sizeof(md_srv_conf_t));
 
     conf->name = apr_pstrcat(pool, "srv[", CONF_S_NAME(s), "]", NULL);
     conf->s = s;
-    conf->local_80 = DEF_VAL;
-    conf->local_443 = DEF_VAL;
-    conf->drive_mode = DEF_VAL;
-    conf->mds = apr_array_make(pool, 5, sizeof(const md_t *));
-    conf->renew_window = DEF_VAL;
-    conf->transitive = DEF_VAL;
+    conf->mc = md_mod_conf_get(pool, 1);
+    conf->md = apr_pcalloc(pool, sizeof(*conf->md));
+
+    srv_conf_props_clear(conf);
     
     return conf;
 }
 
 static void *md_config_merge(apr_pool_t *pool, void *basev, void *addv)
 {
-    md_config_t *base = (md_config_t *)basev;
-    md_config_t *add = (md_config_t *)addv;
-    md_config_t *n = (md_config_t *)apr_pcalloc(pool, sizeof(md_config_t));
+    md_srv_conf_t *base = (md_srv_conf_t *)basev;
+    md_srv_conf_t *add = (md_srv_conf_t *)addv;
+    md_srv_conf_t *nsc;
     char *name = apr_pstrcat(pool, "[", CONF_S_NAME(add->s), ", ", CONF_S_NAME(base->s), "]", NULL);
-    md_t *md;
-    int i;
     
-    n->name = name;
-    n->local_80 = (add->local_80 != DEF_VAL)? add->local_80 : base->local_80;
-    n->local_443 = (add->local_443 != DEF_VAL)? add->local_443 : base->local_443;
-
-    /* I think we should not merge md definitions. They should reside where
-     * they were defined */
-    n->mds = apr_array_make(pool, add->mds->nelts, sizeof(const md_t *));
-    for (i = 0; i < add->mds->nelts; ++i) {
-        md = APR_ARRAY_IDX(add->mds, i, md_t*);
-        APR_ARRAY_PUSH(n->mds, md_t *) = md_clone(pool, md);
-    }
-    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 != DEF_VAL)? add->drive_mode : base->drive_mode;
-    n->md = NULL;
-    n->base_dir = add->base_dir? add->base_dir : base->base_dir;
-    n->renew_window = (add->renew_window != DEF_VAL)? add->renew_window : base->renew_window;
-    n->ca_challenges = (add->ca_challenges? apr_array_copy(pool, add->ca_challenges) 
+    nsc = (md_srv_conf_t *)apr_pcalloc(pool, sizeof(md_srv_conf_t));
+    nsc->name = name;
+
+    nsc->transitive = (add->transitive != DEF_VAL)? add->transitive : base->transitive;
+    nsc->drive_mode = (add->drive_mode != DEF_VAL)? add->drive_mode : base->drive_mode;
+    nsc->md = NULL;
+    nsc->renew_window = (add->renew_window != DEF_VAL)? add->renew_window : base->renew_window;
+
+    nsc->ca_url = add->ca_url? add->ca_url : base->ca_url;
+    nsc->ca_proto = add->ca_proto? add->ca_proto : base->ca_proto;
+    nsc->ca_agreement = add->ca_agreement? add->ca_agreement : base->ca_agreement;
+    nsc->ca_challenges = (add->ca_challenges? apr_array_copy(pool, add->ca_challenges) 
                     : (base->ca_challenges? apr_array_copy(pool, base->ca_challenges) : NULL));
-    n->transitive = (add->transitive != DEF_VAL)? add->transitive : base->transitive;
-    return n;
+    return nsc;
 }
 
 void *md_config_merge_svr(apr_pool_t *pool, void *basev, void *addv)
@@ -118,21 +182,6 @@ void *md_config_merge_svr(apr_pool_t *pool, void *basev, void *addv)
     return md_config_merge(pool, basev, addv);
 }
 
-void *md_config_create_dir(apr_pool_t *pool, char *dummy)
-{
-    md_config_dir_t *conf = apr_pcalloc(pool, sizeof(*conf));
-    return conf;
-}
-
-void *md_config_merge_dir(apr_pool_t *pool, void *basev, void *addv)
-{
-    md_config_dir_t *base = basev;
-    md_config_dir_t *add = addv;
-    md_config_dir_t *n = apr_pcalloc(pool, sizeof(*n));
-    n->md = add->md? add->md : base->md;
-    return n;
-}
-
 static int inside_section(cmd_parms *cmd, const char *section) {
     ap_directive_t *d;
     for (d = cmd->directive->parent; d; d = d->parent) {
@@ -158,90 +207,98 @@ static void add_domain_name(apr_array_header_t *domains, const char *name, apr_p
     }
 }
 
+static const char *set_transitive(int *ptransitive, const char *value)
+{
+    if (!apr_strnatcasecmp("auto", value)) {
+        *ptransitive = 1;
+        return NULL;
+    }
+    else if (!apr_strnatcasecmp("manual", value)) {
+        *ptransitive = 0;
+        return NULL;
+    }
+    return "unknown value, use \"auto|manual\"";
+}
+
 static const char *md_config_sec_start(cmd_parms *cmd, void *mconfig, const char *arg)
 {
-    md_config_t *sconf = ap_get_module_config(cmd->server->module_config, &md_module);
-    const char *endp = ap_strrchr_c(arg, '>');
-    ap_conf_vector_t *new_dir_conf = ap_create_per_dir_config(cmd->pool);
-    int old_overrides = cmd->override;
-    char *old_path = cmd->path;
+    md_srv_conf_t *sc;
+    md_srv_conf_t save;
+    const char *endp;
     const char *err, *name;
-    md_config_dir_t *dconf;
+    apr_array_header_t *domains;
     md_t *md;
+    int transitive = -1;
 
-    if (NULL != (err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE))) {
+    if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
         return err;
     }
         
+    sc = md_config_get(cmd->server);
+    endp = ap_strrchr_c(arg, '>');
     if (endp == NULL) {
-        return apr_pstrcat(cmd->pool, cmd->cmd->name, "> directive missing closing '>'", NULL);
+        return  MD_CMD_MD_SECTION "> directive missing closing '>'";
     }
 
     arg = apr_pstrndup(cmd->pool, arg, endp-arg);
     if (!arg || !*arg) {
-        return "<ManagedDomain > block must specify a unique domain name";
+        return MD_CMD_MD_SECTION " > section must specify a unique domain name";
     }
 
-    cmd->path = ap_getword_white(cmd->pool, &arg);
-    name = cmd->path;
-    
-    md = md_create_empty(cmd->pool);
-    md->name = name;
-    APR_ARRAY_PUSH(md->domains, const char*) = name;
-    md->drive_mode = DEF_VAL;
-    
+    name = ap_getword_white(cmd->pool, &arg);
+    domains = apr_array_make(cmd->pool, 5, sizeof(const char *));
     while (*arg != '\0') {
         name = ap_getword_white(cmd->pool, &arg);
-        APR_ARRAY_PUSH(md->domains, const char*) = name;
+        if (NULL != set_transitive(&transitive, name)) {
+            add_domain_name(domains, name, cmd->pool);
+        }
     }
 
-    dconf = ap_set_config_vectors(cmd->server, new_dir_conf, cmd->path, &md_module, cmd->pool);
-    dconf->md = md;
-    
-    if (NULL == (err = ap_walk_config(cmd->directive->first_child, cmd, new_dir_conf))) {
-        APR_ARRAY_PUSH(sconf->mds, const md_t *) = md;
+    if (domains->nelts == 0) {
+        return "needs at least one domain name";
     }
     
-    cmd->path = old_path;
-    cmd->override = old_overrides;
-
-    return err;
-}
-
-static const char *set_transitive(int *ptransitive, const char *value)
-{
-    if (!apr_strnatcasecmp("auto", value)) {
-        *ptransitive = 1;
-        return NULL;
+    md = md_create(cmd->pool, domains);
+    if (transitive >= 0) {
+        md->transitive = transitive;
     }
-    else if (!apr_strnatcasecmp("manual", value)) {
-        *ptransitive = 0;
-        return NULL;
+    
+    /* Save the current settings in this srv_conf and apply+restore at the
+     * end of this section */
+    memcpy(&save, sc, sizeof(save));
+    srv_conf_props_clear(sc);
+    sc->md = md;
+    
+    if (NULL == (err = ap_walk_config(cmd->directive->first_child, cmd, cmd->context))) {
+        srv_conf_props_apply(md, sc, cmd->pool);
+        APR_ARRAY_PUSH(sc->mc->mds, const md_t *) = md;
     }
-    return "unknown value, use \"auto|manual\"";
+    
+    sc->md = NULL;
+    srv_conf_props_copy(sc, &save);
+    
+    return err;
 }
 
 static const char *md_config_sec_add_members(cmd_parms *cmd, void *dc, 
                                              int argc, char *const argv[])
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
-    md_config_dir_t *dconfig = dc;
-    apr_array_header_t *domains;
+    md_srv_conf_t *sc = md_config_get(cmd->server);
     const char *err;
     int i;
     
     if (NULL != (err = md_section_check(cmd, MD_CMD_MD_SECTION))) {
         if (argc == 1) {
-            /* only allowed value outside a section */
-            return set_transitive(&config->transitive, argv[0]);
+            /* only these values are allowed outside a section */
+            return set_transitive(&sc->transitive, argv[0]);
         }
         return err;
     }
     
-    domains = dconfig->md->domains;
+    assert(sc->md);
     for (i = 0; i < argc; ++i) {
-        if (NULL != set_transitive(&dconfig->md->transitive, argv[i])) {
-            add_domain_name(domains, argv[i], cmd->pool);
+        if (NULL != set_transitive(&sc->transitive, argv[i])) {
+            add_domain_name(sc->md->domains, argv[i], cmd->pool);
         }
     }
     return NULL;
@@ -250,7 +307,7 @@ static const char *md_config_sec_add_members(cmd_parms *cmd, void *dc,
 static const char *md_config_set_names(cmd_parms *cmd, void *arg, 
                                        int argc, char *const argv[])
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
+    md_srv_conf_t *sc = md_config_get(cmd->server);
     apr_array_header_t *domains = apr_array_make(cmd->pool, 5, sizeof(const char *));
     const char *err;
     md_t *md;
@@ -266,10 +323,11 @@ static const char *md_config_set_names(cmd_parms *cmd, void *arg,
             add_domain_name(domains, argv[i], cmd->pool);
         }
     }
-    err = md_create(&md, cmd->pool, domains);
-    if (err) {
-        return err;
+    
+    if (domains->nelts == 0) {
+        return "needs at least one domain name";
     }
+    md = md_create(cmd->pool, domains);
 
     if (transitive >= 0) {
         md->transitive = transitive;
@@ -280,68 +338,53 @@ static const char *md_config_set_names(cmd_parms *cmd, void *arg,
         md->defn_line_number = cmd->config_file->line_number;
     }
 
-    APR_ARRAY_PUSH(config->mds, md_t *) = md;
+    APR_ARRAY_PUSH(sc->mc->mds, md_t *) = md;
 
     return NULL;
 }
 
 static const char *md_config_set_ca(cmd_parms *cmd, void *dc, const char *value)
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
+    md_srv_conf_t *sc = md_config_get(cmd->server);
     const char *err;
 
-    if (inside_section(cmd, MD_CMD_MD_SECTION)) {
-        md_config_dir_t *dconf = dc;
-        dconf->md->ca_url = value;
-    }
-    else {
-        if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
-            return err;
-        }
-        config->ca_url = value;
+    if (!inside_section(cmd, MD_CMD_MD_SECTION)
+        && (err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
+        return err;
     }
+    sc->ca_url = value;
     return NULL;
 }
 
 static const char *md_config_set_ca_proto(cmd_parms *cmd, void *dc, const char *value)
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
+    md_srv_conf_t *config = md_config_get(cmd->server);
     const char *err;
 
-    if (inside_section(cmd, MD_CMD_MD_SECTION)) {
-        md_config_dir_t *dconf = dc;
-        dconf->md->ca_proto = value;
-    }
-    else {
-        if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
-            return err;
-        }
-        config->ca_proto = value;
+    if (!inside_section(cmd, MD_CMD_MD_SECTION)
+        && (err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
+        return err;
     }
+    config->ca_proto = value;
     return NULL;
 }
 
 static const char *md_config_set_agreement(cmd_parms *cmd, void *dc, const char *value)
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
+    md_srv_conf_t *config = md_config_get(cmd->server);
     const char *err;
 
-    if (inside_section(cmd, MD_CMD_MD_SECTION)) {
-        md_config_dir_t *dconf = dc;
-        dconf->md->ca_agreement = value;
-    }
-    else {
-        if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
-            return err;
-        }
-        config->ca_agreement = value;
+    if (!inside_section(cmd, MD_CMD_MD_SECTION)
+        && (err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
+        return err;
     }
+    config->ca_agreement = value;
     return NULL;
 }
 
 static const char *md_config_set_drive_mode(cmd_parms *cmd, void *dc, const char *value)
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
+    md_srv_conf_t *config = md_config_get(cmd->server);
     const char *err;
     md_drive_mode_t drive_mode;
 
@@ -358,16 +401,11 @@ static const char *md_config_set_drive_mode(cmd_parms *cmd, void *dc, const char
         return apr_pstrcat(cmd->pool, "unknown MDDriveMode ", value, NULL);
     }
     
-    if (inside_section(cmd, MD_CMD_MD_SECTION)) {
-        md_config_dir_t *dconf = dc;
-        dconf->md->drive_mode = drive_mode;
-    }
-    else {
-        if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
-            return err;
-        }
-        config->drive_mode = drive_mode;
+    if (!inside_section(cmd, MD_CMD_MD_SECTION)
+        && (err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
+        return err;
     }
+    config->drive_mode = drive_mode;
     return NULL;
 }
 
@@ -405,7 +443,7 @@ static apr_status_t duration_parse(const char *value, apr_interval_time_t *ptime
 
 static const char *md_config_set_renew_window(cmd_parms *cmd, void *dc, const char *value)
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
+    md_srv_conf_t *config = md_config_get(cmd->server);
     const char *err;
     apr_interval_time_t timeout;
 
@@ -414,33 +452,28 @@ static const char *md_config_set_renew_window(cmd_parms *cmd, void *dc, const ch
         return "MDRenewWindow has wrong format";
     }
         
-    if (inside_section(cmd, MD_CMD_MD_SECTION)) {
-        md_config_dir_t *dconf = dc;
-        dconf->md->renew_window = timeout;
-    }
-    else {
-        if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
-            return err;
-        }
-        config->renew_window = timeout;
+    if (!inside_section(cmd, MD_CMD_MD_SECTION)
+        && (err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
+        return err;
     }
+    config->renew_window = timeout;
     return NULL;
 }
 
 static const char *md_config_set_store_dir(cmd_parms *cmd, void *arg, const char *value)
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
+    md_srv_conf_t *sc = md_config_get(cmd->server);
     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
     if (err) {
         return err;
     }
-    config->base_dir = value;
+    sc->mc->base_dir = value;
     (void)arg;
     return NULL;
 }
 
-static const char *set_port_map(md_config_t *config, const char *value)
+static const char *set_port_map(md_mod_conf_t *mc, const char *value)
 {
     int net_port, local_port;
     char *endp;
@@ -467,10 +500,10 @@ static const char *set_port_map(md_config_t *config, const char *value)
     }
     switch (net_port) {
         case 80:
-            config->local_80 = local_port;
+            mc->local_80 = local_port;
             break;
         case 443:
-            config->local_443 = local_port;
+            mc->local_443 = local_port;
             break;
         default:
             return "mapped port number must be 80 or 443";
@@ -481,15 +514,15 @@ static const char *set_port_map(md_config_t *config, const char *value)
 static const char *md_config_set_port_map(cmd_parms *cmd, void *arg, 
                                           const char *v1, const char *v2)
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
+    md_srv_conf_t *sc = md_config_get(cmd->server);
     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
     (void)arg;
     if (!err) {
-        err = set_port_map(config, v1);
+        err = set_port_map(sc->mc, v1);
     }
     if (!err && v2) {
-        err = set_port_map(config, v2);
+        err = set_port_map(sc->mc, v2);
     }
     return err;
 }
@@ -497,21 +530,16 @@ static const char *md_config_set_port_map(cmd_parms *cmd, void *arg,
 static const char *md_config_set_cha_tyes(cmd_parms *cmd, void *dc, 
                                           int argc, char *const argv[])
 {
-    md_config_t *config = (md_config_t *)md_config_get(cmd->server);
+    md_srv_conf_t *config = md_config_get(cmd->server);
     apr_array_header_t **pcha, *ca_challenges;
     const char *err;
     int i;
 
-    if (inside_section(cmd, MD_CMD_MD_SECTION)) {
-        md_config_dir_t *dconf = dc;
-        pcha = &dconf->md->ca_challenges;
-    }
-    else {
-        if (NULL != (err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
-            return err;
-        }
-        pcha = &config->ca_challenges; 
+    if (!inside_section(cmd, MD_CMD_MD_SECTION)
+        && (err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
+        return err;
     }
+    pcha = &config->ca_challenges; 
     
     ca_challenges = *pcha;
     if (!ca_challenges) {
@@ -559,71 +587,72 @@ const command_rec md_cmds[] = {
 };
 
 
-static const md_config_t *config_get_int(server_rec *s, apr_pool_t *p)
+static md_srv_conf_t *config_get_int(server_rec *s, apr_pool_t *p)
 {
-    md_config_t *cfg = (md_config_t *)ap_get_module_config(s->module_config, &md_module);
-    ap_assert(cfg);
-    if (cfg->s != s && p) {
-        cfg = md_config_merge(p, &defconf, cfg);
-        cfg->name = apr_pstrcat(p, CONF_S_NAME(s), cfg->name, NULL);
-        ap_set_module_config(s->module_config, &md_module, cfg);
-    }
-    return cfg;
+    md_srv_conf_t *sc = (md_srv_conf_t *)ap_get_module_config(s->module_config, &md_module);
+    ap_assert(sc);
+    if (sc->s != s && p) {
+        sc = md_config_merge(p, &defconf, sc);
+        sc->name = apr_pstrcat(p, CONF_S_NAME(s), sc->name, NULL);
+        sc->mc = md_mod_conf_get(p, 1);
+        ap_set_module_config(s->module_config, &md_module, sc);
+    }
+    return sc;
 }
 
-const md_config_t *md_config_get(server_rec *s)
+md_srv_conf_t *md_config_get(server_rec *s)
 {
     return config_get_int(s, NULL);
 }
 
-const md_config_t *md_config_get_unique(server_rec *s, apr_pool_t *p)
+md_srv_conf_t *md_config_get_unique(server_rec *s, apr_pool_t *p)
 {
     assert(p);
     return config_get_int(s, p);
 }
 
-const md_config_t *md_config_cget(conn_rec *c)
+md_srv_conf_t *md_config_cget(conn_rec *c)
 {
     return md_config_get(c->base_server);
 }
 
-const char *md_config_gets(const md_config_t *config, md_config_var_t var)
+const char *md_config_gets(const md_srv_conf_t *sc, md_config_var_t var)
 {
     switch (var) {
         case MD_CONFIG_CA_URL:
-            return config->ca_url? config->ca_url : defconf.ca_url;
+            return sc->ca_url? sc->ca_url : defconf.ca_url;
         case MD_CONFIG_CA_PROTO:
-            return config->ca_proto? config->ca_proto : defconf.ca_proto;
+            return sc->ca_proto? sc->ca_proto : defconf.ca_proto;
         case MD_CONFIG_BASE_DIR:
-            return config->base_dir? config->base_dir : defconf.base_dir;
+            return sc->mc->base_dir;
         case MD_CONFIG_CA_AGREEMENT:
-            return config->ca_agreement? config->ca_agreement : defconf.ca_agreement;
+            return sc->ca_agreement? sc->ca_agreement : defconf.ca_agreement;
         default:
             return NULL;
     }
 }
 
-int md_config_geti(const md_config_t *config, md_config_var_t var)
+int md_config_geti(const md_srv_conf_t *sc, md_config_var_t var)
 {
     switch (var) {
         case MD_CONFIG_DRIVE_MODE:
-            return (config->drive_mode != DEF_VAL)? config->drive_mode : defconf.drive_mode;
+            return (sc->drive_mode != DEF_VAL)? sc->drive_mode : defconf.drive_mode;
         case MD_CONFIG_LOCAL_80:
-            return (config->local_80 != DEF_VAL)? config->local_80 : 80;
+            return sc->mc->local_80;
         case MD_CONFIG_LOCAL_443:
-            return (config->local_443 != DEF_VAL)? config->local_443 : 443;
+            return sc->mc->local_443;
         case MD_CONFIG_TRANSITIVE:
-            return (config->transitive != DEF_VAL)? config->transitive : defconf.transitive;
+            return (sc->transitive != DEF_VAL)? sc->transitive : defconf.transitive;
         default:
             return 0;
     }
 }
 
-apr_interval_time_t md_config_get_interval(const md_config_t *config, md_config_var_t var)
+apr_interval_time_t md_config_get_interval(const md_srv_conf_t *sc, md_config_var_t var)
 {
     switch (var) {
         case MD_CONFIG_RENEW_WINDOW:
-            return (config->renew_window != DEF_VAL)? config->renew_window : defconf.renew_window;
+            return (sc->renew_window != DEF_VAL)? sc->renew_window : defconf.renew_window;
         default:
             return 0;
     }
index c0ec6cc6cf77b926b115fa7f0f727b8e0c6f6732..3407c5512c694dbfacd9de441fc8178cb2432217 100644 (file)
@@ -31,49 +31,51 @@ typedef enum {
 } md_config_var_t;
 
 typedef struct {
+    apr_array_header_t *mds;           /* all md_t* defined in the config, shared */
+    const char *base_dir;              /* base dir for store */
+    struct md_store_t *store;          /* store instance, singleton, shared */
+
+    int local_80;                      /* On which port http:80 arrives */
+    int local_443;                     /* On which port https:443 arrives */
+    int can_http;                      /* Does someone listen to the local port 80 equivalent? */
+    int can_https;                     /* Does someone listen to the local port 443 equivalent? */
+
+    apr_array_header_t *unused_names;  /* post config, names of all MDs not linked to a vhost */
+} md_mod_conf_t;
+
+typedef struct md_srv_conf_t {
     const char *name;
-    const server_rec *s;
-    
-    int local_80;
-    int local_443;
+    const server_rec *s;               /* server this config belongs to */
+    md_mod_conf_t *mc;                 /* global config settings */
     
-    apr_array_header_t *mds;           /* array of md_t pointers */
-    const char *ca_url;
-    const char *ca_proto;
-    const char *ca_agreement;
-    apr_array_header_t *ca_challenges; /* challenge types allowed */
+    int transitive;                    /* != 0 iff VirtualHost names/aliases are auto-added */
+    int drive_mode;                    /* mode of obtaining credentials */
+    int must_staple;                   /* certificates should set the OCSP Must Staple extension */
+    apr_interval_time_t renew_window;  /* time before expiration that starts renewal */
     
-    int drive_mode;
-    apr_interval_time_t renew_window;  /* time for renewal before expiry */
-    int transitive;
-    
-    const md_t *md;
-    const char *base_dir;
-    struct md_store_t *store;
-
-} md_config_t;
+    const char *ca_url;                /* url of CA certificate service */
+    const char *ca_proto;              /* protocol used vs CA (e.g. ACME) */
+    const char *ca_agreement;          /* accepted agreement uri between CA and user */ 
+    struct apr_array_header_t *ca_challenges; /* challenge types configured */
 
-typedef struct {
-    md_t *md;
-} md_config_dir_t;
+    md_t *md;                          /* post_config: MD that applies to this server or NULL */
+} md_srv_conf_t;
 
 void *md_config_create_svr(apr_pool_t *pool, server_rec *s);
 void *md_config_merge_svr(apr_pool_t *pool, void *basev, void *addv);
-void *md_config_create_dir(apr_pool_t *pool, char *dummy);
-void *md_config_merge_dir(apr_pool_t *pool, void *basev, void *addv);
 
 extern const command_rec md_cmds[];
 
 /* Get the effective md configuration for the connection */
-const md_config_t *md_config_cget(conn_rec *c);
+md_srv_conf_t *md_config_cget(conn_rec *c);
 /* Get the effective md configuration for the server */
-const md_config_t *md_config_get(server_rec *s);
+md_srv_conf_t *md_config_get(server_rec *s);
 /* Get the effective md configuration for the server, but make it
  * unique to this server_rec, so that any changes only affect this server */
-const md_config_t *md_config_get_unique(server_rec *s, apr_pool_t *p);
+md_srv_conf_t *md_config_get_unique(server_rec *s, apr_pool_t *p);
 
-const char *md_config_gets(const md_config_t *config, md_config_var_t var);
-int md_config_geti(const md_config_t *config, md_config_var_t var);
-apr_interval_time_t md_config_get_interval(const md_config_t *config, md_config_var_t var);
+const char *md_config_gets(const md_srv_conf_t *config, md_config_var_t var);
+int md_config_geti(const md_srv_conf_t *config, md_config_var_t var);
+apr_interval_time_t md_config_get_interval(const md_srv_conf_t *config, md_config_var_t var);
 
 #endif /* md_config_h */