Commit 11a35b4a authored by Stefan Eissing's avatar Stefan Eissing
Browse files

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
parent 74e71527
Loading
Loading
Loading
Loading
+3 −0
Changes for CHANGES: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
                                                         -*- 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]

+8 −1
Changes for modules/md/md_crypt.c: 8 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -50,6 +50,13 @@
#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,7 +478,7 @@ 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) && \
#if MD_USE_OPENSSL_PRE_1_1_API || (defined(LIBRESSL_VERSION_NUMBER) && \
                                   LIBRESSL_VERSION_NUMBER < 0x2070000f)

#ifndef NID_tlsfeature
+2 −2
Changes for modules/md/md_version.h: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -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"

+14 −14
Changes for modules/md/mod_md.c: 14 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -1313,22 +1313,28 @@ 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;
            
                r->status = HTTP_NOT_FOUND;
                if (!ap_strchr_c(name, '/') && reg) {
            if (strlen(name) && !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);
                    
                    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));
                    
@@ -1336,6 +1342,8 @@ static int md_http_challenge_pr(request_rec *r)
                    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
@@ -1347,21 +1355,13 @@ static int md_http_challenge_pr(request_rec *r)
                else if (APR_STATUS_IS_ENOENT(rv)) {
                    return HTTP_NOT_FOUND;
                }
                    else if (APR_ENOENT != rv) {
                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;
}