From a8d21435e3bfda77953c44d6790909baf33d0984 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Wed, 4 Oct 2017 14:55:26 +0000 Subject: [PATCH] On the trunk: mod_md: v0.9.9, fix for applying challenge type based on available ports. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1811082 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 2 + modules/md/md_acme_drive.c | 15 ++++++ modules/md/md_json.c | 6 ++- modules/md/md_reg.c | 99 +++++++++++++++++++------------------- modules/md/md_reg.h | 4 +- modules/md/md_version.h | 4 +- modules/md/mod_md.c | 83 ++++++++++++++++---------------- modules/md/mod_md_config.h | 3 +- 8 files changed, 119 insertions(+), 97 deletions(-) diff --git a/CHANGES b/CHANGES index 449bd35842..2a174e98a1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_md: v0.9.9, fix for applying challenge type based on available ports. [Stefan Eissing] + *) mod_proxy_uwsgi: New UWSGI mod_proxy (sub)module contributed by unbit.com. *) mod_http2: v0.10.12, removed optimization for mutex handling in bucket beams that diff --git a/modules/md/md_acme_drive.c b/modules/md/md_acme_drive.c index 13cff46c50..430ebedc59 100644 --- a/modules/md/md_acme_drive.c +++ b/modules/md/md_acme_drive.c @@ -632,6 +632,21 @@ static apr_status_t acme_driver_init(md_proto_driver_t *d) return APR_EGENERAL; } + if (!d->can_http) { + ad->ca_challenges = md_array_str_remove(d->p, ad->ca_challenges, MD_AUTHZ_TYPE_HTTP01, 0); + } + if (!d->can_https) { + ad->ca_challenges = md_array_str_remove(d->p, ad->ca_challenges, MD_AUTHZ_TYPE_TLSSNI01, 0); + } + + if (apr_is_empty_array(ad->ca_challenges)) { + md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, d->p, "%s: specific CA challenge methods " + "have been configured, but the server is unable to use any of those. " + "For 'http-01' it needs to be reachable on port 80, for 'tls-sni-01'" + " port 443 is needed.", d->md->name); + return APR_EGENERAL; + } + md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, d->p, "%s: init driver", d->md->name); return rv; diff --git a/modules/md/md_json.c b/modules/md/md_json.c index 686056bd5e..94157a4204 100644 --- a/modules/md/md_json.c +++ b/modules/md/md_json.c @@ -28,7 +28,8 @@ #if defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunreachable-code" -#elif defined(__clang__) +#endif +#if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" #endif @@ -40,7 +41,8 @@ #if defined(__GNUC__) #pragma GCC diagnostic pop -#elif defined(__clang__) +#endif +#if defined(__clang__) #pragma clang diagnostic pop #endif diff --git a/modules/md/md_reg.c b/modules/md/md_reg.c index 95e32a70d1..78d38a9ca0 100644 --- a/modules/md/md_reg.c +++ b/modules/md/md_reg.c @@ -37,7 +37,6 @@ struct md_reg_t { struct md_store_t *store; struct apr_hash_t *protos; - int was_synched; int can_http; int can_https; const char *proxy_url; @@ -46,6 +45,27 @@ struct md_reg_t { /**************************************************************************************************/ /* life cycle */ +static apr_status_t load_props(md_reg_t *reg, apr_pool_t *p) +{ + md_json_t *json; + apr_status_t rv; + + rv = md_store_load(reg->store, MD_SG_NONE, NULL, MD_FN_HTTPD_JSON, + MD_SV_JSON, (void**)&json, p); + if (APR_SUCCESS == rv) { + if (md_json_has_key(json, MD_KEY_PROTO, MD_KEY_HTTP, NULL)) { + reg->can_http = md_json_getb(json, MD_KEY_PROTO, MD_KEY_HTTP, NULL); + } + if (md_json_has_key(json, MD_KEY_PROTO, MD_KEY_HTTPS, NULL)) { + reg->can_https = md_json_getb(json, MD_KEY_PROTO, MD_KEY_HTTPS, NULL); + } + } + else if (APR_STATUS_IS_ENOENT(rv)) { + rv = APR_SUCCESS; + } + return rv; +} + apr_status_t md_reg_init(md_reg_t **preg, apr_pool_t *p, struct md_store_t *store, const char *proxy_url) { @@ -58,7 +78,10 @@ apr_status_t md_reg_init(md_reg_t **preg, apr_pool_t *p, struct md_store_t *stor reg->can_http = 1; reg->can_https = 1; reg->proxy_url = proxy_url? apr_pstrdup(p, proxy_url) : NULL; - rv = md_acme_protos_add(reg->protos, p); + + if (APR_SUCCESS == (rv = md_acme_protos_add(reg->protos, p))) { + rv = load_props(reg, p); + } *preg = (rv == APR_SUCCESS)? reg : NULL; return rv; @@ -618,34 +641,21 @@ static int find_changes(void *baton, md_store_t *store, md_t *md, apr_pool_t *pt return 1; } -static apr_status_t load_props(md_reg_t *reg, apr_pool_t *p) +apr_status_t md_reg_set_props(md_reg_t *reg, apr_pool_t *p, int can_http, int can_https) { - md_json_t *json; - apr_status_t rv; - - rv = md_store_load(reg->store, MD_SG_NONE, NULL, MD_FN_HTTPD_JSON, - MD_SV_JSON, (void**)&json, p); - if (APR_SUCCESS == rv) { - if (md_json_has_key(json, MD_KEY_PROTO, MD_KEY_HTTP, NULL)) { - reg->can_http = md_json_getb(json, MD_KEY_PROTO, MD_KEY_HTTP, NULL); - } - if (md_json_has_key(json, MD_KEY_PROTO, MD_KEY_HTTPS, NULL)) { - reg->can_https = md_json_getb(json, MD_KEY_PROTO, MD_KEY_HTTPS, NULL); - } - } - else if (APR_STATUS_IS_ENOENT(rv)) { - rv = APR_SUCCESS; + if (reg->can_http != can_http || reg->can_https != can_https) { + md_json_t *json; + + reg->can_http = can_http; + reg->can_https = can_https; + + json = md_json_create(p); + md_json_setb(can_http, json, MD_KEY_PROTO, MD_KEY_HTTP, NULL); + md_json_setb(can_https, json, MD_KEY_PROTO, MD_KEY_HTTPS, NULL); + + return md_store_save(reg->store, p, MD_SG_NONE, NULL, MD_FN_HTTPD_JSON, MD_SV_JSON, json, 0); } - return rv; -} - -static apr_status_t sync_props(md_reg_t *reg, apr_pool_t *p, int can_http, int can_https) -{ - md_json_t *json = md_json_create(p); - md_json_setb(can_http, json, MD_KEY_PROTO, MD_KEY_HTTP, NULL); - md_json_setb(can_https, json, MD_KEY_PROTO, MD_KEY_HTTPS, NULL); - - return md_store_save(reg->store, p, MD_SG_NONE, NULL, MD_FN_HTTPD_JSON, MD_SV_JSON, json, 0); + return APR_SUCCESS; } /** @@ -665,19 +675,12 @@ static apr_status_t sync_props(md_reg_t *reg, apr_pool_t *p, int can_http, int c * c. compare MD acme url/protocol, update if changed */ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp, - apr_array_header_t *master_mds, int can_http, int can_https) + apr_array_header_t *master_mds) { sync_ctx ctx; md_store_t *store = reg->store; apr_status_t rv; - if (APR_SUCCESS != (rv = sync_props(reg, ptemp, can_http, can_https))) { - reg->was_synched = 0; - return rv; - } - - reg->was_synched = 1; - ctx.p = ptemp; ctx.conf_mds = master_mds; ctx.store_mds = apr_array_make(ptemp, 100, sizeof(md_t *)); @@ -843,20 +846,16 @@ static apr_status_t init_proto_driver(md_proto_driver_t *driver, const md_proto_ /* If this registry instance was not synched before (and obtained server * properties that way), read them from the store. */ - if (reg->was_synched - || APR_SUCCESS == (rv = load_props(reg, p))) { - - driver->proto = proto; - driver->p = p; - driver->challenge = challenge; - driver->can_http = reg->can_http; - driver->can_https = reg->can_https; - driver->reg = reg; - driver->store = md_reg_store_get(reg); - driver->proxy_url = reg->proxy_url; - driver->md = md; - driver->reset = reset; - } + driver->proto = proto; + driver->p = p; + driver->challenge = challenge; + driver->can_http = reg->can_http; + driver->can_https = reg->can_https; + driver->reg = reg; + driver->store = md_reg_store_get(reg); + driver->proxy_url = reg->proxy_url; + driver->md = md; + driver->reset = reset; return rv; } diff --git a/modules/md/md_reg.h b/modules/md/md_reg.h index 5007c6d888..19682a759d 100644 --- a/modules/md/md_reg.h +++ b/modules/md/md_reg.h @@ -37,6 +37,8 @@ apr_status_t md_reg_init(md_reg_t **preg, apr_pool_t *pm, struct md_store_t *sto struct md_store_t *md_reg_store_get(md_reg_t *reg); +apr_status_t md_reg_set_props(md_reg_t *reg, apr_pool_t *p, int can_http, int can_https); + /** * Add a new md to the registry. This will check the name for uniqueness and * that domain names do not overlap with already existing mds. @@ -119,7 +121,7 @@ apr_status_t md_reg_get_cred_files(md_reg_t *reg, const md_t *md, apr_pool_t *p, * Synchronise the give master mds with the store. */ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp, - apr_array_header_t *master_mds, int can_http, int can_https); + apr_array_header_t *master_mds); /**************************************************************************************************/ /* protocol drivers */ diff --git a/modules/md/md_version.h b/modules/md/md_version.h index e32ab23b50..d29daad4dd 100644 --- a/modules/md/md_version.h +++ b/modules/md/md_version.h @@ -26,7 +26,7 @@ * @macro * Version number of the md module as c string */ -#define MOD_MD_VERSION "0.9.7-git" +#define MOD_MD_VERSION "0.9.9" /** * @macro @@ -34,7 +34,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 0x000907 +#define MOD_MD_VERSION_NUM 0x000909 #define MD_EXPERIMENTAL 0 #define MD_ACME_DEF_URL "https://acme-v01.api.letsencrypt.org/directory" diff --git a/modules/md/mod_md.c b/modules/md/mod_md.c index e1845ca80c..381371bc4d 100644 --- a/modules/md/mod_md.c +++ b/modules/md/mod_md.c @@ -415,55 +415,55 @@ 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_mod_conf_t *mc, apr_pool_t *p, server_rec *s, - int post_config) +static apr_status_t setup_store(md_store_t **pstore, md_mod_conf_t *mc, + apr_pool_t *p, server_rec *s) { const char *base_dir; - md_store_t *store; apr_status_t rv; base_dir = ap_server_root_relative(p, mc->base_dir); - if (APR_SUCCESS != (rv = md_store_fs_init(&store, p, base_dir))) { + if (APR_SUCCESS != (rv = md_store_fs_init(pstore, p, base_dir))) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10046)"setup store for %s", base_dir); goto out; } - if (post_config) { - md_store_fs_set_event_cb(store, store_file_ev, s); - if (APR_SUCCESS != (rv = check_group_dir(store, MD_SG_CHALLENGES, p, s))) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10047) - "setup challenges directory"); - goto out; - } - if (APR_SUCCESS != (rv = check_group_dir(store, MD_SG_STAGING, p, s))) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10048) - "setup staging directory"); - goto out; - } - if (APR_SUCCESS != (rv = check_group_dir(store, MD_SG_ACCOUNTS, p, s))) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10049) - "setup accounts directory"); - goto out; - } + md_store_fs_set_event_cb(*pstore, store_file_ev, s); + if (APR_SUCCESS != (rv = check_group_dir(*pstore, MD_SG_CHALLENGES, p, s))) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10047) + "setup challenges directory"); + goto out; + } + if (APR_SUCCESS != (rv = check_group_dir(*pstore, MD_SG_STAGING, p, s))) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10048) + "setup staging directory"); + goto out; + } + if (APR_SUCCESS != (rv = check_group_dir(*pstore, MD_SG_ACCOUNTS, p, s))) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10049) + "setup accounts directory"); + goto out; } - mc->store = store; out: return rv; } -static apr_status_t setup_reg(md_reg_t **preg, apr_pool_t *p, server_rec *s, int post_config) +static apr_status_t setup_reg(md_reg_t **preg, apr_pool_t *p, server_rec *s, + int can_http, int can_https) { md_srv_conf_t *sc; md_mod_conf_t *mc; + md_store_t *store; apr_status_t rv; 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, mc->proxy_url); + if (APR_SUCCESS == (rv = setup_store(&store, mc, p, s)) + && APR_SUCCESS == (rv = md_reg_init(preg, p, store, mc->proxy_url))) { + mc->reg = *preg; + return md_reg_set_props(*preg, p, can_http, can_https); } return rv; } @@ -896,13 +896,12 @@ static apr_status_t md_post_config(apr_pool_t *p, apr_pool_t *plog, mc = sc->mc; /* Synchronize the defintions we now have with the store via a registry (reg). */ - if (APR_SUCCESS != (rv = setup_reg(®, p, s, 1))) { + if (APR_SUCCESS != (rv = setup_reg(®, p, s, mc->can_http, mc->can_https))) { 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, mc->mds, - mc->can_http, mc->can_https))) { + if (APR_SUCCESS != (rv = md_reg_sync(reg, p, ptemp, mc->mds))) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10073) "synching %d mds to registry", mc->mds->nelts); } @@ -1005,6 +1004,7 @@ static apr_status_t md_get_certificate(server_rec *s, apr_pool_t *p, apr_status_t rv = APR_ENOENT; md_srv_conf_t *sc; md_reg_t *reg; + md_store_t *store; const md_t *md; *pkeyfile = NULL; @@ -1014,11 +1014,10 @@ static apr_status_t md_get_certificate(server_rec *s, apr_pool_t *p, if (sc && sc->assigned) { assert(sc->mc); - assert(sc->mc->store); - if (APR_SUCCESS != (rv = md_reg_init(®, p, sc->mc->store, sc->mc->proxy_url))) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO() "init registry"); - return rv; - } + reg = sc->mc->reg; + assert(reg); + store = md_reg_store_get(reg); + assert(store); md = md_reg_get(reg, sc->assigned->name, p); @@ -1033,12 +1032,12 @@ static apr_status_t md_get_certificate(server_rec *s, apr_pool_t *p, * clients do not get obscure TLS handshake errors or will see a fallback * virtual host that is not intended to be served here. */ - md_store_get_fname(pkeyfile, sc->mc->store, MD_SG_DOMAINS, + md_store_get_fname(pkeyfile, store, MD_SG_DOMAINS, md->name, MD_FN_FALLBACK_PKEY, p); - md_store_get_fname(pcertfile, sc->mc->store, MD_SG_DOMAINS, + md_store_get_fname(pcertfile, store, MD_SG_DOMAINS, md->name, MD_FN_FALLBACK_CERT, p); if (!fexists(*pkeyfile, p) || !fexists(*pcertfile, p)) { - if (APR_SUCCESS != (rv = setup_fallback_cert(sc->mc->store, md, p))) { + if (APR_SUCCESS != (rv = setup_fallback_cert(store, md, p))) { ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, s, "%s: setup fallback certificate", md->name); return rv; @@ -1077,8 +1076,8 @@ static int md_is_challenge(conn_rec *c, const char *servername, } sc = md_config_get(c->base_server); - if (sc && sc->mc->store) { - md_store_t *store = sc->mc->store; + if (sc && sc->mc->reg) { + md_store_t *store = md_reg_store_get(sc->mc->reg); md_cert_t *mdcert; md_pkey_t *mdpkey; @@ -1116,18 +1115,19 @@ static int md_http_challenge_pr(request_rec *r) apr_bucket_brigade *bb; const md_srv_conf_t *sc; const char *name, *data; + md_reg_t *reg; 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; sc = ap_get_module_config(r->server->module_config, &md_module); - store = sc? sc->mc->store : NULL; + reg = sc && sc->mc? sc->mc->reg : NULL; name = r->parsed_uri.path + sizeof(ACME_CHALLENGE_PREFIX)-1; r->status = HTTP_NOT_FOUND; - if (!ap_strchr_c(name, '/') && store) { + if (!ap_strchr_c(name, '/') && reg) { + md_store_t *store = md_reg_store_get(reg); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Challenge for %s (%s)", r->hostname, r->uri); @@ -1253,3 +1253,4 @@ static void md_hooks(apr_pool_t *pool) APR_REGISTER_OPTIONAL_FN(md_get_certificate); APR_REGISTER_OPTIONAL_FN(md_is_challenge); } + diff --git a/modules/md/mod_md_config.h b/modules/md/mod_md_config.h index bfe84c125e..43b8259ee1 100644 --- a/modules/md/mod_md_config.h +++ b/modules/md/mod_md_config.h @@ -17,6 +17,7 @@ #define mod_md_md_config_h struct md_store_t; +struct md_reg_t; struct md_pkey_spec_t; typedef enum { @@ -39,7 +40,7 @@ typedef struct { apr_array_header_t *mds; /* all md_t* defined in the config, shared */ const char *base_dir; /* base dir for store */ const char *proxy_url; /* proxy url to use (or NULL) */ - struct md_store_t *store; /* store instance, singleton, shared */ + struct md_reg_t *reg; /* md registry instance, singleton, shared */ int local_80; /* On which port http:80 arrives */ int local_443; /* On which port https:443 arrives */ -- 2.40.0