From: Stefan Eissing Date: Fri, 29 Jun 2018 10:52:07 +0000 (+0000) Subject: mod_md: more robust handling of http-01 challenges and hands-off when module X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b9214a43f9bad64bf6ca6cf085e41d7e47729a3a;p=apache mod_md: more robust handling of http-01 challenges and hands-off when module should not be involved, e.g. challenge setup by another ACME client. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1834667 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 6e9f075c93..f3416d8786 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.1 + *) mod_md: more robust handling of http-01 challenges and hands-off when module + should not be involved, e.g. challenge setup by another ACME client. [Stefan Eissing] + *) core: Re-allow '_' (underscore) in hostnames. [Eric Covener] diff --git a/modules/md/md_crypt.c b/modules/md/md_crypt.c index 7e3e2e27e1..ae541bfed9 100644 --- a/modules/md/md_crypt.c +++ b/modules/md/md_crypt.c @@ -50,6 +50,13 @@ #include #endif +#if defined(LIBRESSL_VERSION_NUMBER) +/* Missing from LibreSSL */ +#define MD_USE_OPENSSL_PRE_1_1_API (LIBRESSL_VERSION_NUMBER < 0x2080000f) +#else /* defined(LIBRESSL_VERSION_NUMBER) */ +#define MD_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L) +#endif + static int initialized; struct md_pkey_t { @@ -471,8 +478,8 @@ apr_status_t md_pkey_gen(md_pkey_t **ppkey, apr_pool_t *p, md_pkey_spec_t *spec) } } -#if MODSSL_USE_OPENSSL_PRE_1_1_API || (defined(LIBRESSL_VERSION_NUMBER) && \ - LIBRESSL_VERSION_NUMBER < 0x2070000f) +#if MD_USE_OPENSSL_PRE_1_1_API || (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x2070000f) #ifndef NID_tlsfeature #define NID_tlsfeature 1020 diff --git a/modules/md/md_version.h b/modules/md/md_version.h index 8dbbaa3666..b87f19c1db 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.12" +#define MOD_MD_VERSION "1.1.15" /** * @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 0x01010c +#define MOD_MD_VERSION_NUM 0x01010f #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 bb02566334..249a0f000e 100644 --- a/modules/md/mod_md.c +++ b/modules/md/mod_md.c @@ -1313,55 +1313,55 @@ static int md_http_challenge_pr(request_rec *r) && !strncmp(ACME_CHALLENGE_PREFIX, r->parsed_uri.path, sizeof(ACME_CHALLENGE_PREFIX)-1)) { sc = ap_get_module_config(r->server->module_config, &md_module); if (sc && sc->mc) { + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, + "access inside /.well-known/acme-challenge for %s%s", + r->hostname, r->parsed_uri.path); 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; + name = r->parsed_uri.path + sizeof(ACME_CHALLENGE_PREFIX)-1; + reg = sc && sc->mc? sc->mc->reg : NULL; + + if (strlen(name) && !ap_strchr_c(name, '/') && reg) { + md_store_t *store = md_reg_store_get(reg); - 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); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, + "loading challenge for %s (%s)", r->hostname, r->uri); + if (APR_SUCCESS == rv) { + apr_size_t len = strlen(data); - 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; + if (r->method_number != M_GET) { + return HTTP_NOT_IMPLEMENTED; } + /* A GET on a challenge resource for a hostname we are + * configured for. Let's send the content back */ + 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); + + return DONE; + } + 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 { + 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 DECLINED; }