Commit 7de2b56a authored by Stefan Eissing's avatar Stefan Eissing
Browse files

On the 2.4.x-mod_md branch:

merged mod_md relevant parts of 1818030,1818120,1818308,1818725,1818792,1818849,1819799,1819854,1819943,1820036,1820310,1820312 from trunk


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x-mod_md@1820314 13f79535-47bb-0310-9956-ffa450edef68
parent d4959145
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -594,4 +594,23 @@ MDRequireHttps permanent
        </usage>
    </directivesynopsis>

    <directivesynopsis>
        <name>MDBaseServer</name>
        <description>Control if base server may be managed or only virtual hosts.</description>
        <syntax>MDBaseServer on|off</syntax>
        <default>MDBaseServer off</default>
        <contextlist>
            <context>server config</context>
        </contextlist>
        <usage>
            <p>
            Controls if the base server, the one outside all VirtualHosts should be managed by 
            <module>mod_md</module> or not. Default is to not do this, for the very reason that 
            it may have confusing side-effects. It is recommended that you have virtual hosts 
            for all managed domains and do not rely on the global, fallback server configuration.
            </p>
        </usage>
    </directivesynopsis>


</modulesynopsis>
+11 −0
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ struct md_t {
#define MD_KEY_CONTACT          "contact"
#define MD_KEY_CONTACTS         "contacts"
#define MD_KEY_CSR              "csr"
#define MD_KEY_DETAIL           "detail"
#define MD_KEY_DISABLED         "disabled"
#define MD_KEY_DIR              "dir"
#define MD_KEY_DOMAIN           "domain"
@@ -275,4 +276,14 @@ struct md_creds_t {
    int expired;
};

/* TODO: not sure this is a good idea, testing some readability and debuggabiltiy of
 * cascaded apr_status_t checks. */
#define MD_CHK_VARS                 const char *md_chk_
#define MD_LAST_CHK                 md_chk_
#define MD_CHK_STEP(c, status, s)   (md_chk_ = s, (void)md_chk_, status == (rv = (c)))
#define MD_CHK(c, status)           MD_CHK_STEP(c, status, #c)
#define MD_IS_ERR(c, err)           (md_chk_ = #c, APR_STATUS_IS_##err((rv = (c))))
#define MD_CHK_SUCCESS(c)           MD_CHK(c, APR_SUCCESS)
#define MD_OK(c)                    MD_CHK_SUCCESS(c)

#endif /* mod_md_md_h */
+2 −2
Original line number Diff line number Diff line
@@ -284,8 +284,8 @@ static apr_status_t inspect_problem(md_acme_req_t *req, const md_http_response_t
            const char *ptype, *pdetail;
            
            req->resp_json = problem;
            ptype = md_json_gets(problem, "type", NULL); 
            pdetail = md_json_gets(problem, "detail", NULL);
            ptype = md_json_gets(problem, MD_KEY_TYPE, NULL); 
            pdetail = md_json_gets(problem, MD_KEY_DETAIL, NULL);
            req->rv = problem_status_get(ptype);
            
            if (APR_STATUS_IS_EAGAIN(req->rv)) {
+49 −47
Original line number Diff line number Diff line
@@ -207,8 +207,10 @@ apr_status_t md_acme_authz_update(md_acme_authz_t *authz, md_acme_t *acme,
                                  md_store_t *store, apr_pool_t *p)
{
    md_json_t *json;
    const char *s;
    const char *s, *err;
    md_log_level_t log_level;
    apr_status_t rv;
    MD_CHK_VARS;
    
    (void)store;
    assert(acme);
@@ -216,46 +218,46 @@ apr_status_t md_acme_authz_update(md_acme_authz_t *authz, md_acme_t *acme,
    assert(authz);
    assert(authz->location);

    if (APR_SUCCESS != (rv = md_acme_get_json(&json, acme, authz->location, p))) {
        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "update authz for %s at %s",
                      authz->domain, authz->location);
        return rv;
    }
    authz->state = MD_ACME_AUTHZ_S_UNKNOWN;
    json = NULL;
    err = "unable to parse response";
    log_level = MD_LOG_ERR;
    
    authz->resource = json;
    s = md_json_gets(json, "identifier", "type", NULL);
    if (!s || strcmp(s, "dns")) return APR_EINVAL;
    s = md_json_gets(json, "identifier", "value", NULL);
    if (!s || strcmp(s, authz->domain)) return APR_EINVAL;
    if (MD_OK(md_acme_get_json(&json, acme, authz->location, p))
        && (s = md_json_gets(json, MD_KEY_IDENTIFIER, MD_KEY_TYPE, NULL))
        && !strcmp(s, "dns")
        && (s = md_json_gets(json, MD_KEY_IDENTIFIER, MD_KEY_VALUE, NULL))
        && !strcmp(s, authz->domain)
        && (s = md_json_gets(json, MD_KEY_STATUS, NULL))) {
        
    authz->state = MD_ACME_AUTHZ_S_UNKNOWN;
    s = md_json_gets(json, "status", NULL);
    if (s && !strcmp(s, "pending")) {
        authz->resource = json;
        if (!strcmp(s, "pending")) {
            authz->state = MD_ACME_AUTHZ_S_PENDING;
            err = "challenge 'pending'";
            log_level = MD_LOG_DEBUG;
        }
    else if (s && !strcmp(s, "valid")) {
        else if (!strcmp(s, "valid")) {
            authz->state = MD_ACME_AUTHZ_S_VALID;
        if (md_log_is_level(p, MD_LOG_DEBUG)) {
            md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "ACME server validated challenge "
                          "for %s in %s, ACME response is: %s", 
                          authz->domain, authz->location, 
                          md_json_writep(json, p, MD_JSON_FMT_COMPACT));
            err = "challenge 'valid'";
            log_level = MD_LOG_DEBUG;
        }
    }
    else if (s && !strcmp(s, "invalid")) {
        else if (!strcmp(s, "invalid")) {
            authz->state = MD_ACME_AUTHZ_S_INVALID;
        md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "ACME server reports challenge "
                      "for %s in %s as 'invalid', ACME response is: %s", 
                      authz->domain, authz->location, 
                      md_json_writep(json, p, MD_JSON_FMT_COMPACT));
    }
    else if (s) {
        md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "ACME server reports unrecognized "
                      "authz state '%s' for %s in %s, ACME response is: %s", 
                      s, authz->domain, authz->location, 
                      md_json_writep(json, p, MD_JSON_FMT_COMPACT));
        return APR_EINVAL;
            err = "challenge 'invalid'";
        }
    }

    if (json && authz->state == MD_ACME_AUTHZ_S_UNKNOWN) {
        err = "unable to understand response";
        rv = APR_EINVAL;
    }
    
    if (md_log_is_level(p, log_level)) {
        md_log_perror(MD_LOG_MARK, log_level, rv, p, "ACME server authz: %s for %s at %s. "
                      "Exact repsonse was: %s", err? err : "", authz->domain, authz->location,
                      json? md_json_writep(json, p, MD_JSON_FMT_COMPACT) : "not available");
    }
    
    return rv;
}

@@ -306,13 +308,14 @@ static apr_status_t setup_key_authz(md_acme_authz_cha_t *cha, md_acme_authz_t *a
{
    const char *thumb64, *key_authz;
    apr_status_t rv;
    MD_CHK_VARS;
    
    (void)authz;
    assert(cha);
    assert(cha->token);
    
    *pchanged = 0;
    if (APR_SUCCESS == (rv = md_jws_pkey_thumb(&thumb64, p, acme->acct_key))) {
    if (MD_OK(md_jws_pkey_thumb(&thumb64, p, acme->acct_key))) {
        key_authz = apr_psprintf(p, "%s.%s", cha->token, thumb64);
        if (cha->key_authz) {
            if (strcmp(key_authz, cha->key_authz)) {
@@ -335,9 +338,10 @@ static apr_status_t cha_http_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t
    const char *data;
    apr_status_t rv;
    int notify_server;
    MD_CHK_VARS;
    
    (void)key_spec;
    if (APR_SUCCESS != (rv = setup_key_authz(cha, authz, acme, p, &notify_server))) {
    if (!MD_OK(setup_key_authz(cha, authz, acme, p, &notify_server))) {
        goto out;
    }
    
@@ -395,9 +399,10 @@ static apr_status_t cha_tls_sni_01_setup(md_acme_authz_cha_t *cha, md_acme_authz
    apr_status_t rv;
    int notify_server;
    apr_array_header_t *domains;
    MD_CHK_VARS;
    
    if (   APR_SUCCESS != (rv = setup_key_authz(cha, authz, acme, p, &notify_server))
        || APR_SUCCESS != (rv = setup_cha_dns(&cha_dns, cha, p))) {
    if (   !MD_OK(setup_key_authz(cha, authz, acme, p, &notify_server))
        || !MD_OK(setup_cha_dns(&cha_dns, cha, p))) {
        goto out;
    }

@@ -415,18 +420,15 @@ static apr_status_t cha_tls_sni_01_setup(md_acme_authz_cha_t *cha, md_acme_authz
        /* setup a certificate containing the challenge dns */
        domains = apr_array_make(p, 5, sizeof(const char*));
        APR_ARRAY_PUSH(domains, const char*) = cha_dns;
        rv = md_cert_self_sign(&cha_cert, authz->domain, domains, cha_key, 
                               apr_time_from_sec(7 * MD_SECS_PER_DAY), p);
        
        if (APR_SUCCESS != rv) {
        if (!MD_OK(md_cert_self_sign(&cha_cert, authz->domain, domains, cha_key, 
                                     apr_time_from_sec(7 * MD_SECS_PER_DAY), p))) {
            md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: setup self signed cert for %s",
                          authz->domain, cha_dns);
            goto out;
        }
        
        rv = md_store_save(store, p, MD_SG_CHALLENGES, cha_dns, MD_FN_TLSSNI01_PKEY,
                           MD_SV_PKEY, (void*)cha_key, 0);
        if (APR_SUCCESS == rv) {
        if (MD_OK(md_store_save(store, p, MD_SG_CHALLENGES, cha_dns, MD_FN_TLSSNI01_PKEY,
                                MD_SV_PKEY, (void*)cha_key, 0))) {
            rv = md_store_save(store, p, MD_SG_CHALLENGES, cha_dns, MD_FN_TLSSNI01_CERT,
                               MD_SV_CERT, (void*)cha_cert, 0);
        }
+42 −21
Original line number Diff line number Diff line
@@ -783,30 +783,26 @@ int md_cert_covers_md(md_cert_t *cert, const md_t *md)

apr_status_t md_cert_get_issuers_uri(const char **puri, md_cert_t *cert, apr_pool_t *p)
{
    int i, ext_idx, nid = NID_info_access;
    X509_EXTENSION *ext;
    X509V3_EXT_METHOD *ext_cls;
    void *ext_data;
    const char *uri = NULL;
    apr_status_t rv = APR_ENOENT;
    STACK_OF(ACCESS_DESCRIPTION) *xinfos;
    const char *uri = NULL;
    unsigned char *buf;
    int i;

    /* Waddle through x509  API history to get someone that may be able
     * to hand us the issuer url for the cert chain */
    ext_idx = X509_get_ext_by_NID(cert->x509, nid, -1);
    ext = (ext_idx >= 0)? X509_get_ext(cert->x509, ext_idx) : NULL;
    ext_cls = ext? (X509V3_EXT_METHOD*)X509V3_EXT_get(ext) : NULL;
    if (ext_cls && (ext_data = X509_get_ext_d2i(cert->x509, nid, 0, 0))) {
        CONF_VALUE *cval;
        STACK_OF(CONF_VALUE) *ext_vals = ext_cls->i2v(ext_cls, ext_data, 0);
        
        for (i = 0; i < sk_CONF_VALUE_num(ext_vals); ++i) {
            cval = sk_CONF_VALUE_value(ext_vals, i);
            if (!strcmp("CA Issuers - URI", cval->name)) {
                uri = apr_pstrdup(p, cval->value);
    xinfos = X509_get_ext_d2i(cert->x509, NID_info_access, NULL, NULL);
    if (xinfos) {
        for (i = 0; i < sk_ACCESS_DESCRIPTION_num(xinfos); i++) {
            ACCESS_DESCRIPTION *val = sk_ACCESS_DESCRIPTION_value(xinfos, i);
            if (OBJ_obj2nid(val->method) == NID_ad_ca_issuers
                    && val->location && val->location->type == GEN_URI) {
                ASN1_STRING_to_UTF8(&buf, val->location->d.uniformResourceIdentifier);
                uri = apr_pstrdup(p, (char *)buf);
                OPENSSL_free(buf);
                rv = APR_SUCCESS;
                break;
            }
        }
        sk_ACCESS_DESCRIPTION_pop_free(xinfos, ACCESS_DESCRIPTION_free);
    } 
    *puri = (APR_SUCCESS == rv)? uri : NULL;
    return rv;
@@ -820,7 +816,7 @@ apr_status_t md_cert_get_alt_names(apr_array_header_t **pnames, md_cert_t *cert,
    unsigned char *buf;
    int i;
    
    xalt_names = (GENERAL_NAMES*)X509_get_ext_d2i(cert->x509, NID_subject_alt_name, NULL, NULL);
    xalt_names = X509_get_ext_d2i(cert->x509, NID_subject_alt_name, NULL, NULL);
    if (xalt_names) {
        GENERAL_NAME *cval;
        
@@ -839,6 +835,7 @@ apr_status_t md_cert_get_alt_names(apr_array_header_t **pnames, md_cert_t *cert,
                    break;
            }
        }
        sk_GENERAL_NAME_pop_free(xalt_names, GENERAL_NAME_free);
        rv = APR_SUCCESS;
    }
    *pnames = (APR_SUCCESS == rv)? names : NULL;
@@ -1106,6 +1103,30 @@ static apr_status_t sk_add_alt_names(STACK_OF(X509_EXTENSION) *exts,
    return APR_SUCCESS;
}

#define MD_OID_MUST_STAPLE_NUM          "1.3.6.1.5.5.7.1.24"
#define MD_OID_MUST_STAPLE_SNAME        "tlsfeature"
#define MD_OID_MUST_STAPLE_LNAME        "TLS Feature" 

static int get_must_staple_nid(void)
{
    /* Funny API, the OID for must staple might be configured or
     * might be not. In the second case, we need to add it. But adding
     * when it already is there is an error... */
    int nid = OBJ_txt2nid(MD_OID_MUST_STAPLE_NUM);
    if (NID_undef == nid) {
        nid = OBJ_create(MD_OID_MUST_STAPLE_NUM, 
                         MD_OID_MUST_STAPLE_SNAME, MD_OID_MUST_STAPLE_LNAME);
    }
    return nid;
}

int md_cert_must_staple(md_cert_t *cert)
{
    /* In case we do not get the NID for it, we treat this as not set. */
    int nid = get_must_staple_nid();
    return ((NID_undef != nid)) && X509_get_ext_by_NID(cert->x509, nid, -1) >= 0;
}

static apr_status_t add_must_staple(STACK_OF(X509_EXTENSION) *exts, const md_t *md, apr_pool_t *p)
{
    
@@ -1113,7 +1134,7 @@ static apr_status_t add_must_staple(STACK_OF(X509_EXTENSION) *exts, const md_t *
        X509_EXTENSION *x;
        int nid;
        
        nid = OBJ_create("1.3.6.1.5.5.7.1.24", "tlsfeature", "TLS Feature");
        nid = get_must_staple_nid();
        if (NID_undef == nid) {
            md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, 
                          "%s: unable to get NID for v3 must-staple TLS feature", md->name);
Loading