From: Stefan Eissing Date: Mon, 19 Mar 2018 09:16:00 +0000 (+0000) Subject: mod_md: /.well-known/acme-challenge requests that cannot be answered for hostnames X-Git-Tag: 2.5.0-alpha2-ci-test-only~2777 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b2af278e657ab6190e887d70e90e4c086776fd7;p=thirdparty%2Fapache%2Fhttpd.git mod_md: /.well-known/acme-challenge requests that cannot be answered for hostnames outside the configured MDs are free to be answered by other handlers. This allows co-existance between mod_md and other ACME clients on the same server (implements PR62189). [Stefan Eissing, Arkadiusz Miskiewicz ] Fixes PR62189. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1827175 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 4eb0a92c61d..729baf3688f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,11 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.1 + *) mod_md: /.well-known/acme-challenge requests that cannot be answered for hostnames + outside the configured MDs are free to be answered by other handlers. This allows + co-existance between mod_md and other ACME clients on the same server (implements PR62189). + [Stefan Eissing, Arkadiusz Miskiewicz ] + *) mod_md: Fix compilation with OpenSSL before version 1.0.2. [Rainer Jung] *) core: Create a conn_config_t structure to hold an extendable core config rather diff --git a/modules/md/md_version.h b/modules/md/md_version.h index f28cd037812..6cf20ea444e 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 "1.1.8" +#define MOD_MD_VERSION "1.1.10" /** * @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 0x010108 +#define MOD_MD_VERSION_NUM 0x01010a #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 1b8446df4f1..ae13118e237 100644 --- a/modules/md/mod_md.c +++ b/modules/md/mod_md.c @@ -1302,48 +1302,61 @@ static int md_http_challenge_pr(request_rec *r) const md_srv_conf_t *sc; const char *name, *data; md_reg_t *reg; + int configured; apr_status_t rv; if (!strncmp(ACME_CHALLENGE_PREFIX, r->parsed_uri.path, sizeof(ACME_CHALLENGE_PREFIX)-1)) { - if (r->method_number == M_GET) { - - sc = ap_get_module_config(r->server->module_config, &md_module); - 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, '/') && 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); - - rv = md_store_load(store, MD_SG_CHALLENGES, r->hostname, - MD_FN_HTTP01, MD_SV_TEXT, (void**)&data, r->pool); - if (APR_SUCCESS == rv) { - apr_size_t len = strlen(data); - - r->status = HTTP_OK; - apr_table_setn(r->headers_out, "Content-Length", apr_ltoa(r->pool, (long)len)); + sc = ap_get_module_config(r->server->module_config, &md_module); + if (sc && sc->mc) { + configured = (NULL != md_get_by_domain(sc->mc->mds, r->hostname)); + if (r->method_number == M_GET) { + name = r->parsed_uri.path + sizeof(ACME_CHALLENGE_PREFIX)-1; + reg = sc && sc->mc? sc->mc->reg : NULL; + + r->status = HTTP_NOT_FOUND; + 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); - bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); - apr_brigade_write(bb, NULL, NULL, data, len); - ap_pass_brigade(r->output_filters, bb); - apr_brigade_cleanup(bb); - } - else if (APR_STATUS_IS_ENOENT(rv)) { - return HTTP_NOT_FOUND; - } - else if (APR_ENOENT != rv) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10081) - "loading challenge %s from store", name); - return HTTP_INTERNAL_SERVER_ERROR; + rv = md_store_load(store, MD_SG_CHALLENGES, r->hostname, + MD_FN_HTTP01, MD_SV_TEXT, (void**)&data, r->pool); + if (APR_SUCCESS == rv) { + apr_size_t len = strlen(data); + + r->status = HTTP_OK; + apr_table_setn(r->headers_out, "Content-Length", apr_ltoa(r->pool, (long)len)); + + bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); + apr_brigade_write(bb, NULL, NULL, data, len); + ap_pass_brigade(r->output_filters, bb); + apr_brigade_cleanup(bb); + } + else if (!configured) { + /* The request hostname is not for a configured domain. We are not + * the sole authority here for /.well-known/acme-challenge (see PR62189). + * So, we decline to handle this and let others step in. + */ + return DECLINED; + } + else if (APR_STATUS_IS_ENOENT(rv)) { + return HTTP_NOT_FOUND; + } + else if (APR_ENOENT != rv) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10081) + "loading challenge %s from store", name); + return HTTP_INTERNAL_SERVER_ERROR; + } } + return r->status; + } + else if (configured) { + /* See comment above, we prevent any other access only for domains + * the have been configured for mod_md. */ + return HTTP_NOT_IMPLEMENTED; } - return r->status; - } - else { - return HTTP_NOT_IMPLEMENTED; } + } return DECLINED; }