struct md_cert_t;
struct md_pkey_t;
struct md_store_t;
+struct md_srv_conf_t;
#define MD_TLSSNI01_DNS_SUFFIX ".acme.invalid"
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 */
};
/**
* 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.
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;
}
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;
}
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;
}
/**************************************************************************************************/
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)
}
}
-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;
}
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);
"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;
}
{
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;
}
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(®, 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
*
* 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 */
}
}
+ /* 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));
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)
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(®, 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(®, p, sc->mc->store))) {
+ md = md_reg_get(reg, sc->md->name, p);
if (md->state != MD_S_COMPLETE) {
return APR_EAGAIN;
}
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;
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;
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);
}
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;
}
}
#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)
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) {
}
}
+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;
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;
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;
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;
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;
}
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;
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;
}
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";
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;
}
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) {
};
-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;
}
} 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 */