diff options
Diffstat (limited to 'modules/md')
-rw-r--r-- | modules/md/md.h | 18 | ||||
-rw-r--r-- | modules/md/md_acme_authz.c | 47 | ||||
-rw-r--r-- | modules/md/md_acme_order.c | 4 | ||||
-rw-r--r-- | modules/md/md_crypt.c | 47 | ||||
-rw-r--r-- | modules/md/md_util.c | 29 | ||||
-rw-r--r-- | modules/md/md_util.h | 7 | ||||
-rw-r--r-- | modules/md/md_version.h | 4 | ||||
-rw-r--r-- | modules/md/mod_md.c | 56 | ||||
-rw-r--r-- | modules/md/mod_md_config.c | 46 | ||||
-rw-r--r-- | modules/md/mod_md_config.h | 6 | ||||
-rw-r--r-- | modules/md/mod_md_status.c | 2 |
11 files changed, 189 insertions, 77 deletions
diff --git a/modules/md/md.h b/modules/md/md.h index 1d75d10..035ccba 100644 --- a/modules/md/md.h +++ b/modules/md/md.h @@ -78,12 +78,7 @@ struct md_t { 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_require_t require_https; /* Iff https: is required for this MD */ - - int renew_mode; /* mode of obtaining credentials */ struct md_pkeys_spec_t *pks; /* specification for generating private keys */ - int must_staple; /* certificates should set the OCSP Must Staple extension */ md_timeslice_t *renew_window; /* time before expiration that starts renewal */ md_timeslice_t *warn_window; /* time before expiration that warnings are sent out */ @@ -98,19 +93,23 @@ struct md_t { const char *ca_eab_kid; /* optional KEYID for external account binding */ const char *ca_eab_hmac; /* optional HMAC for external account binding */ - md_state_t state; /* state of this MD */ const char *state_descr; /* description of state of NULL */ struct apr_array_header_t *acme_tls_1_domains; /* domains supporting "acme-tls/1" protocol */ - int stapling; /* if OCSP stapling is enabled */ const char *dns01_cmd; /* DNS challenge command, override global command */ - int watched; /* if certificate is supervised (renew or expiration warning) */ 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 */ - const char *configured_name; /* name this MD was configured with, if different */ + + int renew_mode; /* mode of obtaining credentials */ + md_require_t require_https; /* Iff https: is required for this MD */ + md_state_t state; /* state of this MD */ + int transitive; /* != 0 iff VirtualHost names/aliases are auto-added */ + int must_staple; /* certificates should set the OCSP Must Staple extension */ + int stapling; /* if OCSP stapling is enabled */ + int watched; /* if certificate is supervised (renew or expiration warning) */ }; #define MD_KEY_ACCOUNT "account" @@ -128,6 +127,7 @@ struct md_t { #define MD_KEY_CHALLENGE "challenge" #define MD_KEY_CHALLENGES "challenges" #define MD_KEY_CMD_DNS01 "cmd-dns-01" +#define MD_KEY_DNS01_VERSION "cmd-dns-01-version" #define MD_KEY_COMPLETE "complete" #define MD_KEY_CONTACT "contact" #define MD_KEY_CONTACTS "contacts" diff --git a/modules/md/md_acme_authz.c b/modules/md/md_acme_authz.c index a55804e..f4579b3 100644 --- a/modules/md/md_acme_authz.c +++ b/modules/md/md_acme_authz.c @@ -244,7 +244,8 @@ static apr_status_t cha_http_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t md_acme_t *acme, md_store_t *store, md_pkeys_spec_t *key_specs, apr_array_header_t *acme_tls_1_domains, const md_t *md, - apr_table_t *env, md_result_t *result, apr_pool_t *p) + apr_table_t *env, md_result_t *result, + const char **psetup_token, apr_pool_t *p) { const char *data; apr_status_t rv; @@ -289,6 +290,8 @@ static apr_status_t cha_http_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t rv = md_acme_POST(acme, cha->uri, on_init_authz_resp, authz_http_set, NULL, NULL, &ctx); } out: + *psetup_token = (APR_SUCCESS == rv)? + apr_psprintf(p, "%s:%s", MD_AUTHZ_TYPE_HTTP01, authz->domain) : NULL; return rv; } @@ -302,7 +305,8 @@ static apr_status_t cha_tls_alpn_01_setup(md_acme_authz_cha_t *cha, md_acme_auth md_acme_t *acme, md_store_t *store, md_pkeys_spec_t *key_specs, apr_array_header_t *acme_tls_1_domains, const md_t *md, - apr_table_t *env, md_result_t *result, apr_pool_t *p) + apr_table_t *env, md_result_t *result, + const char **psetup_token, apr_pool_t *p) { const char *acme_id, *token; apr_status_t rv; @@ -407,6 +411,8 @@ static apr_status_t cha_tls_alpn_01_setup(md_acme_authz_cha_t *cha, md_acme_auth rv = md_acme_POST(acme, cha->uri, on_init_authz_resp, authz_http_set, NULL, NULL, &ctx); } out: + *psetup_token = (APR_SUCCESS == rv)? + apr_psprintf(p, "%s:%s", MD_AUTHZ_TYPE_TLSALPN01, authz->domain) : NULL; return rv; } @@ -414,7 +420,8 @@ static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t * md_acme_t *acme, md_store_t *store, md_pkeys_spec_t *key_specs, apr_array_header_t *acme_tls_1_domains, const md_t *md, - apr_table_t *env, md_result_t *result, apr_pool_t *p) + apr_table_t *env, md_result_t *result, + const char **psetup_token, apr_pool_t *p) { const char *token; const char * const *argv; @@ -456,7 +463,7 @@ static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t * "%s: dns-01 setup command: %s", authz->domain, cmdline); apr_tokenize_to_argv(cmdline, (char***)&argv, p); - if (APR_SUCCESS != (rv = md_util_exec(p, argv[0], argv, NULL, &exit_code))) { + if (APR_SUCCESS != (rv = md_util_exec(p, argv[0], argv, &exit_code))) { md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, "%s: dns-01 setup command failed to execute for %s", md->name, authz->domain); goto out; @@ -486,6 +493,8 @@ static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t * rv = md_acme_POST(acme, cha->uri, on_init_authz_resp, authz_http_set, NULL, NULL, &ctx); out: + *psetup_token = (APR_SUCCESS == rv)? + apr_psprintf(p, "%s:%s %s", MD_AUTHZ_TYPE_DNS01, authz->domain, token) : NULL; return rv; } @@ -493,7 +502,8 @@ static apr_status_t cha_dns_01_teardown(md_store_t *store, const char *domain, c apr_table_t *env, apr_pool_t *p) { const char * const *argv; - const char *cmdline, *dns01_cmd; + const char *cmdline, *dns01_cmd, *dns01v; + char *tmp, *s; apr_status_t rv; int exit_code; @@ -508,10 +518,20 @@ static apr_status_t cha_dns_01_teardown(md_store_t *store, const char *domain, c md->name, domain); goto out; } - + dns01v = apr_table_get(env, MD_KEY_DNS01_VERSION); + if (!dns01v || strcmp(dns01v, "2")) { + /* use older version of teardown args with only domain, remove token */ + tmp = apr_pstrdup(p, domain); + s = strchr(tmp, ' '); + if (s) { + *s = '\0'; + domain = tmp; + } + } + cmdline = apr_psprintf(p, "%s teardown %s", dns01_cmd, domain); apr_tokenize_to_argv(cmdline, (char***)&argv, p); - if (APR_SUCCESS != (rv = md_util_exec(p, argv[0], argv, NULL, &exit_code)) || exit_code) { + if (APR_SUCCESS != (rv = md_util_exec(p, argv[0], argv, &exit_code)) || exit_code) { md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, "%s: dns-01 teardown command failed (exit code=%d) for %s", md->name, exit_code, domain); @@ -532,7 +552,8 @@ typedef apr_status_t cha_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, md_acme_t *acme, md_store_t *store, md_pkeys_spec_t *key_specs, apr_array_header_t *acme_tls_1_domains, const md_t *md, - apr_table_t *env, md_result_t *result, apr_pool_t *p); + apr_table_t *env, md_result_t *result, + const char **psetup_token, apr_pool_t *p); typedef apr_status_t cha_teardown(md_store_t *store, const char *domain, const md_t *md, apr_table_t *env, apr_pool_t *p); @@ -590,8 +611,7 @@ apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, md_acme_t *acme, md_s apr_status_t rv; int i, j; cha_find_ctx fctx; - const char *challenge_setup; - + assert(acme); assert(authz); assert(authz->resource); @@ -613,7 +633,7 @@ apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, md_acme_t *acme, md_s "type, this domain supports %s", authz->domain, apr_array_pstrcat(p, challenges, ' ')); rv = APR_ENOTIMPL; - challenge_setup = NULL; + *psetup_token = NULL; for (i = 0; i < challenges->nelts; ++i) { fctx.type = APR_ARRAY_IDX(challenges, i, const char *); fctx.accepted = NULL; @@ -629,12 +649,12 @@ apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, md_acme_t *acme, md_s md_result_activity_printf(result, "Setting up challenge '%s' for domain %s", fctx.accepted->type, authz->domain); rv = CHA_TYPES[j].setup(fctx.accepted, authz, acme, store, key_specs, - acme_tls_1_domains, md, env, result, p); + acme_tls_1_domains, md, env, result, + psetup_token, p); if (APR_SUCCESS == rv) { md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: set up challenge '%s' for %s", authz->domain, fctx.accepted->type, md->name); - challenge_setup = CHA_TYPES[j].name; goto out; } md_result_printf(result, rv, "error setting up challenge '%s' for %s, " @@ -647,7 +667,6 @@ apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, md_acme_t *acme, md_s } out: - *psetup_token = (APR_SUCCESS == rv)? apr_psprintf(p, "%s:%s", challenge_setup, authz->domain) : NULL; if (!fctx.accepted || APR_ENOTIMPL == rv) { rv = APR_EINVAL; fctx.offered = apr_array_make(p, 5, sizeof(const char*)); diff --git a/modules/md/md_acme_order.c b/modules/md/md_acme_order.c index 9e25e84..061093a 100644 --- a/modules/md/md_acme_order.c +++ b/modules/md/md_acme_order.c @@ -537,8 +537,8 @@ static apr_status_t check_challenges(void *baton, int attempt) } } else { - md_result_printf(ctx->result, rv, "authorization retrieval failed for domain %s", - authz->domain); + md_result_printf(ctx->result, rv, "authorization retrieval failed for %s on <%s>", + ctx->name, url); } } leave: diff --git a/modules/md/md_crypt.c b/modules/md/md_crypt.c index f2b0cd5..4b2af89 100644 --- a/modules/md/md_crypt.c +++ b/modules/md/md_crypt.c @@ -32,6 +32,9 @@ #include <openssl/rand.h> #include <openssl/rsa.h> #include <openssl/x509v3.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include <openssl/core_names.h> +#endif #include "md.h" #include "md_crypt.h" @@ -988,26 +991,42 @@ static const char *bn64(const BIGNUM *b, apr_pool_t *p) const char *md_pkey_get_rsa_e64(md_pkey_t *pkey, apr_pool_t *p) { - const BIGNUM *e; - RSA *rsa = EVP_PKEY_get1_RSA(pkey->pkey); - - if (!rsa) { - return NULL; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const RSA *rsa = EVP_PKEY_get0_RSA(pkey->pkey); + if (rsa) { + const BIGNUM *e; + RSA_get0_key(rsa, NULL, &e, NULL); + return bn64(e, p); } - RSA_get0_key(rsa, NULL, &e, NULL); - return bn64(e, p); +#else + BIGNUM *e = NULL; + if (EVP_PKEY_get_bn_param(pkey->pkey, OSSL_PKEY_PARAM_RSA_E, &e)) { + const char *e64 = bn64(e, p); + BN_free(e); + return e64; + } +#endif + return NULL; } const char *md_pkey_get_rsa_n64(md_pkey_t *pkey, apr_pool_t *p) { - const BIGNUM *n; - RSA *rsa = EVP_PKEY_get1_RSA(pkey->pkey); - - if (!rsa) { - return NULL; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const RSA *rsa = EVP_PKEY_get0_RSA(pkey->pkey); + if (rsa) { + const BIGNUM *n; + RSA_get0_key(rsa, &n, NULL, NULL); + return bn64(n, p); } - RSA_get0_key(rsa, &n, NULL, NULL); - return bn64(n, p); +#else + BIGNUM *n = NULL; + if (EVP_PKEY_get_bn_param(pkey->pkey, OSSL_PKEY_PARAM_RSA_N, &n)) { + const char *n64 = bn64(n, p); + BN_free(n); + return n64; + } +#endif + return NULL; } apr_status_t md_crypt_sign64(const char **psign64, md_pkey_t *pkey, apr_pool_t *p, diff --git a/modules/md/md_util.c b/modules/md/md_util.c index 884c0bb..95ecc27 100644 --- a/modules/md/md_util.c +++ b/modules/md/md_util.c @@ -916,6 +916,19 @@ int md_dns_domains_match(const apr_array_header_t *domains, const char *name) return 0; } +int md_is_wild_match(const apr_array_header_t *domains, const char *name) +{ + const char *domain; + int i; + + for (i = 0; i < domains->nelts; ++i) { + domain = APR_ARRAY_IDX(domains, i, const char*); + if (md_dns_matches(domain, name)) + return (domain[0] == '*' && domain[1] == '.'); + } + return 0; +} + const char *md_util_schemify(apr_pool_t *p, const char *s, const char *def_scheme) { const char *cp = s; @@ -1068,32 +1081,24 @@ apr_status_t md_util_try(md_util_try_fn *fn, void *baton, int ignore_errs, /* execute process ********************************************************************************/ -apr_status_t md_util_exec(apr_pool_t *p, const char *cmd, const char * const *argv, - apr_array_header_t *env, int *exit_code) +apr_status_t md_util_exec(apr_pool_t *p, const char *cmd, + const char * const *argv, int *exit_code) { apr_status_t rv; apr_procattr_t *procattr; apr_proc_t *proc; apr_exit_why_e ewhy; - const char * const *envp = NULL; char buffer[1024]; *exit_code = 0; if (!(proc = apr_pcalloc(p, sizeof(*proc)))) { return APR_ENOMEM; } - if (env && env->nelts > 0) { - apr_array_header_t *nenv; - - nenv = apr_array_copy(p, env); - APR_ARRAY_PUSH(nenv, const char *) = NULL; - envp = (const char * const *)nenv->elts; - } if ( APR_SUCCESS == (rv = apr_procattr_create(&procattr, p)) && APR_SUCCESS == (rv = apr_procattr_io_set(procattr, APR_NO_FILE, APR_NO_PIPE, APR_FULL_BLOCK)) - && APR_SUCCESS == (rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM)) - && APR_SUCCESS == (rv = apr_proc_create(proc, cmd, argv, envp, procattr, p))) { + && APR_SUCCESS == (rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV)) + && APR_SUCCESS == (rv = apr_proc_create(proc, cmd, argv, NULL, procattr, p))) { /* read stderr and log on INFO for possible fault analysis. */ while(APR_SUCCESS == (rv = apr_file_gets(buffer, sizeof(buffer)-1, proc->err))) { diff --git a/modules/md/md_util.h b/modules/md/md_util.h index e430655..d974788 100644 --- a/modules/md/md_util.h +++ b/modules/md/md_util.h @@ -133,7 +133,7 @@ int md_array_str_add_missing(struct apr_array_header_t *dest, /* process execution */ apr_status_t md_util_exec(apr_pool_t *p, const char *cmd, const char * const *argv, - struct apr_array_header_t *env, int *exit_code); + int *exit_code); /**************************************************************************************************/ /* dns name check */ @@ -174,6 +174,11 @@ struct apr_array_header_t *md_dns_make_minimal(apr_pool_t *p, */ int md_dns_domains_match(const apr_array_header_t *domains, const char *name); +/** + * @return != 0 iff `name` is matched by a wildcard pattern in `domains` + */ +int md_is_wild_match(const apr_array_header_t *domains, const char *name); + /**************************************************************************************************/ /* file system related */ diff --git a/modules/md/md_version.h b/modules/md/md_version.h index a8f3ef2..86a1821 100644 --- a/modules/md/md_version.h +++ b/modules/md/md_version.h @@ -27,7 +27,7 @@ * @macro * Version number of the md module as c string */ -#define MOD_MD_VERSION "2.4.21" +#define MOD_MD_VERSION "2.4.25" /** * @macro @@ -35,7 +35,7 @@ * release. This is a 24 bit number with 8 bits for major number, 8 bits * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. */ -#define MOD_MD_VERSION_NUM 0x020415 +#define MOD_MD_VERSION_NUM 0x020419 #define MD_ACME_DEF_URL "https://acme-v02.api.letsencrypt.org/directory" #define MD_TAILSCALE_DEF_URL "file://localhost/var/run/tailscale/tailscaled.sock" diff --git a/modules/md/mod_md.c b/modules/md/mod_md.c index 32dea4f..6d3f5b7 100644 --- a/modules/md/mod_md.c +++ b/modules/md/mod_md.c @@ -183,7 +183,7 @@ static apr_status_t notify(md_job_t *job, const char *reason, if (mc->notify_cmd) { cmdline = apr_psprintf(p, "%s %s", mc->notify_cmd, job->mdomain); apr_tokenize_to_argv(cmdline, (char***)&argv, p); - rv = md_util_exec(p, argv[0], argv, NULL, &exit_code); + rv = md_util_exec(p, argv[0], argv, &exit_code); if (APR_SUCCESS == rv && exit_code) rv = APR_EGENERAL; if (APR_SUCCESS != rv) { @@ -202,7 +202,7 @@ static apr_status_t notify(md_job_t *job, const char *reason, if (mc->message_cmd) { cmdline = apr_psprintf(p, "%s %s %s", mc->message_cmd, reason, job->mdomain); apr_tokenize_to_argv(cmdline, (char***)&argv, p); - rv = md_util_exec(p, argv[0], argv, NULL, &exit_code); + rv = md_util_exec(p, argv[0], argv, &exit_code); if (APR_SUCCESS == rv && exit_code) rv = APR_EGENERAL; if (APR_SUCCESS != rv) { @@ -377,12 +377,12 @@ static apr_status_t check_coverage(md_t *md, const char *domain, server_rec *s, return APR_SUCCESS; } else { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(10040) + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10040) "Virtual Host %s:%d matches Managed Domain '%s', but the " "name/alias %s itself is not managed. A requested MD certificate " "will not match ServerName.", s->server_hostname, s->port, md->name, domain); - return APR_EINVAL; + return APR_SUCCESS; } } @@ -586,18 +586,30 @@ static apr_status_t link_md_to_servers(md_mod_conf_t *mc, md_t *md, server_rec * 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) - || (md_dns_is_wildcard(p, domain) && md_dns_matches(domain, s->server_hostname))) { + if ((mc->match_mode == MD_MATCH_ALL && + ap_matches_request_vhost(&r, domain, s->port)) + || (((mc->match_mode == MD_MATCH_SERVERNAMES) || md_dns_is_wildcard(p, domain)) && + md_dns_matches(domain, s->server_hostname))) { /* Create a unique md_srv_conf_t record for this server, if there is none yet */ sc = md_config_get_unique(s, p); if (!sc->assigned) sc->assigned = apr_array_make(p, 2, sizeof(md_t*)); - + if (sc->assigned->nelts == 1 && mc->match_mode == MD_MATCH_SERVERNAMES) { + /* there is already an MD assigned for this server. But in + * this match mode, wildcard matches are pre-empted by non-wildcards */ + int existing_wild = md_is_wild_match( + APR_ARRAY_IDX(sc->assigned, 0, const md_t*)->domains, + s->server_hostname); + if (!existing_wild && md_dns_is_wildcard(p, domain)) + continue; /* do not add */ + if (existing_wild && !md_dns_is_wildcard(p, domain)) + sc->assigned->nelts = 0; /* overwrite existing */ + } APR_ARRAY_PUSH(sc->assigned, md_t*) = md; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10041) - "Server %s:%d matches md %s (config %s) for domain %s, " - "has now %d MDs", + "Server %s:%d matches md %s (config %s, match-mode=%d) " + "for domain %s, has now %d MDs", s->server_hostname, s->port, md->name, sc->name, - domain, (int)sc->assigned->nelts); + mc->match_mode, domain, (int)sc->assigned->nelts); if (md->contacts && md->contacts->nelts > 0) { /* set explicitly */ @@ -670,17 +682,19 @@ static apr_status_t merge_mds_with_conf(md_mod_conf_t *mc, apr_pool_t *p, md = APR_ARRAY_IDX(mc->mds, i, md_t*); merge_srv_config(md, base_conf, 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; - } + if (mc->match_mode == MD_MATCH_ALL) { + /* 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; + } + } } if (md->cert_files && md->cert_files->nelts) { diff --git a/modules/md/mod_md_config.c b/modules/md/mod_md_config.c index e117b16..31d06b4 100644 --- a/modules/md/mod_md_config.c +++ b/modules/md/mod_md_config.c @@ -88,6 +88,7 @@ static md_mod_conf_t defmc = { 13, /* retry_failover after 14 errors, with 5s delay ~ half a day */ 0, /* store locks, disabled by default */ apr_time_from_sec(5), /* max time to wait to obaint a store lock */ + MD_MATCH_ALL, /* match vhost severname and aliases */ }; static md_timeslice_t def_renew_window = { @@ -684,6 +685,27 @@ static const char *md_config_set_store_locks(cmd_parms *cmd, void *dc, const cha return NULL; } +static const char *md_config_set_match_mode(cmd_parms *cmd, void *dc, const char *s) +{ + md_srv_conf_t *config = md_config_get(cmd->server); + const char *err = md_conf_check_location(cmd, MD_LOC_NOT_MD); + + (void)dc; + if (err) { + return err; + } + else if (!apr_strnatcasecmp("all", s)) { + config->mc->match_mode = MD_MATCH_ALL; + } + else if (!apr_strnatcasecmp("servernames", s)) { + config->mc->match_mode = MD_MATCH_SERVERNAMES; + } + else { + return "invalid argument, must be a 'all' or 'servernames'"; + } + return NULL; +} + static const char *md_config_set_require_https(cmd_parms *cmd, void *dc, const char *value) { md_srv_conf_t *config = md_config_get(cmd->server); @@ -985,6 +1007,24 @@ static const char *md_config_set_dns01_cmd(cmd_parms *cmd, void *mconfig, const return NULL; } +static const char *md_config_set_dns01_version(cmd_parms *cmd, void *mconfig, const char *value) +{ + md_srv_conf_t *sc = md_config_get(cmd->server); + const char *err; + + (void)mconfig; + if ((err = md_conf_check_location(cmd, MD_LOC_NOT_MD))) { + return err; + } + if (!strcmp("1", value) || !strcmp("2", value)) { + apr_table_set(sc->mc->env, MD_KEY_DNS01_VERSION, value); + } + else { + return "Only versions `1` and `2` are supported"; + } + return NULL; +} + static const char *md_config_add_cert_file(cmd_parms *cmd, void *mconfig, const char *arg) { md_srv_conf_t *sc = md_config_get(cmd->server); @@ -1226,7 +1266,9 @@ const command_rec md_cmds[] = { "Allow managing of base server outside virtual hosts."), AP_INIT_RAW_ARGS("MDChallengeDns01", md_config_set_dns01_cmd, NULL, RSRC_CONF, "Set the command for setup/teardown of dns-01 challenges"), - AP_INIT_TAKE1("MDCertificateFile", md_config_add_cert_file, NULL, RSRC_CONF, + AP_INIT_TAKE1("MDChallengeDns01Version", md_config_set_dns01_version, NULL, RSRC_CONF, + "Set the type of arguments to call `MDChallengeDns01` with"), + AP_INIT_TAKE1("MDCertificateFile", md_config_add_cert_file, NULL, RSRC_CONF, "set the static certificate (chain) file to use for this domain."), AP_INIT_TAKE1("MDCertificateKeyFile", md_config_add_key_file, NULL, RSRC_CONF, "set the static private key file to use for this domain."), @@ -1260,6 +1302,8 @@ const command_rec md_cmds[] = { "The number of errors before a failover to another CA is triggered."), AP_INIT_TAKE1("MDStoreLocks", md_config_set_store_locks, NULL, RSRC_CONF, "Configure locking of store for updates."), + AP_INIT_TAKE1("MDMatchNames", md_config_set_match_mode, NULL, RSRC_CONF, + "Determines how DNS names are matched to vhosts."), AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL) }; diff --git a/modules/md/mod_md_config.h b/modules/md/mod_md_config.h index de42169..7e87440 100644 --- a/modules/md/mod_md_config.h +++ b/modules/md/mod_md_config.h @@ -41,6 +41,11 @@ typedef enum { MD_CONFIG_STAPLE_OTHERS, } md_config_var_t; +typedef enum { + MD_MATCH_ALL, + MD_MATCH_SERVERNAMES, +} md_match_mode_t; + typedef struct md_mod_conf_t md_mod_conf_t; struct md_mod_conf_t { apr_array_header_t *mds; /* all md_t* defined in the config, shared */ @@ -74,6 +79,7 @@ struct md_mod_conf_t { int retry_failover; /* number of errors to trigger CA failover */ int use_store_locks; /* use locks when updating store */ apr_time_t lock_wait_timeout; /* fail after this time when unable to obtain lock */ + md_match_mode_t match_mode; /* how dns names are match to vhosts */ }; typedef struct md_srv_conf_t { diff --git a/modules/md/mod_md_status.c b/modules/md/mod_md_status.c index 2286051..6b29256 100644 --- a/modules/md/mod_md_status.c +++ b/modules/md/mod_md_status.c @@ -325,7 +325,7 @@ static void si_val_valid_time(status_ctx *ctx, md_json_t *mdj, const status_info apr_pstrcat(ctx->p, info->label, "From", NULL)); } if (until) { - print_date(ctx, from, + print_date(ctx, until, apr_pstrcat(ctx->p, info->label, "Until", NULL)); } } |