]> granicus.if.org Git - apache/commitdiff
mod_md: more robust handling of http-01 challenges and hands-off when module
authorStefan Eissing <icing@apache.org>
Fri, 29 Jun 2018 10:52:07 +0000 (10:52 +0000)
committerStefan Eissing <icing@apache.org>
Fri, 29 Jun 2018 10:52:07 +0000 (10:52 +0000)
     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

CHANGES
modules/md/md_crypt.c
modules/md/md_version.h
modules/md/mod_md.c

diff --git a/CHANGES b/CHANGES
index 6e9f075c93d02fd41140fb3dafedf0110093a71e..f3416d8786c4daa7e9040a65b30437746828ebd1 100644 (file)
--- 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]
 
index 7e3e2e27e16111bd9e41de3de25944dd685bec37..ae541bfed95dd4741a4686d16f612aa9345d0c98 100644 (file)
 #include <process.h>
 #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
index 8dbbaa3666a6e626fcce4ba99c187e0ccd35cb19..b87f19c1dbb7249380e431540736eb8ed5a2f639 100644 (file)
@@ -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"
 
index bb02566334b4f7d5cf937742723bdb5c27da4cc1..249a0f000e571e51912ce3935520e17b98487a72 100644 (file)
@@ -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;
 }