mirror of
https://github.com/apache/httpd.git
synced 2025-07-25 17:01:22 +00:00
*) mod_md: update to version 2.5.2
- Fixed TLS-ALPN-01 challenges when multiple `MDPrivateKeys` are specified with EC keys before RSA ones. Fixes #377. [Stefan Eissing] - Fixed missing newlines in the status page output. [Andreas Groth] git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1925979 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
4
changes-entries/md_v2.5.2.txt
Normal file
4
changes-entries/md_v2.5.2.txt
Normal file
@ -0,0 +1,4 @@
|
||||
*) mod_md: update to version 2.5.2
|
||||
- Fixed TLS-ALPN-01 challenges when multiple `MDPrivateKeys` are specified
|
||||
with EC keys before RSA ones. Fixes #377. [Stefan Eissing]
|
||||
- Fixed missing newlines in the status page output. [Andreas Groth]
|
@ -69,6 +69,10 @@
|
||||
#define MD_HAVE_CT 0
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
#define MD_OPENSSL_10x
|
||||
#endif
|
||||
|
||||
static int initialized;
|
||||
|
||||
struct md_pkey_t {
|
||||
@ -257,9 +261,9 @@ static apr_time_t md_asn1_time_get(const ASN1_TIME* time)
|
||||
#endif
|
||||
}
|
||||
|
||||
apr_time_t md_asn1_generalized_time_get(void *ASN1_GENERALIZEDTIME)
|
||||
apr_time_t md_asn1_generalized_time_get(void *asn1_gtime)
|
||||
{
|
||||
return md_asn1_time_get(ASN1_GENERALIZEDTIME);
|
||||
return md_asn1_time_get(asn1_gtime);
|
||||
}
|
||||
|
||||
/**************************************************************************************************/
|
||||
@ -566,7 +570,7 @@ static md_pkey_spec_t PkeySpecDef = { MD_PKEY_TYPE_DEFAULT, {{ 0 }} };
|
||||
md_pkey_spec_t *md_pkeys_spec_get(const md_pkeys_spec_t *pks, int index)
|
||||
{
|
||||
if (md_pkeys_spec_is_empty(pks)) {
|
||||
return index == 1? &PkeySpecDef : NULL;
|
||||
return index == 0? &PkeySpecDef : NULL;
|
||||
}
|
||||
else if (pks && index >= 0 && index < pks->specs->nelts) {
|
||||
return APR_ARRAY_IDX(pks->specs, index, md_pkey_spec_t*);
|
||||
@ -803,7 +807,11 @@ static apr_status_t check_EC_curve(int nid, apr_pool_t *p) {
|
||||
int rv = APR_ENOENT;
|
||||
|
||||
nc = EC_get_builtin_curves(NULL, 0);
|
||||
#ifdef MD_OPENSSL_10x
|
||||
if (NULL == (curves = OPENSSL_malloc((int)(sizeof(*curves) * nc))) ||
|
||||
#else
|
||||
if (NULL == (curves = OPENSSL_malloc(sizeof(*curves) * nc)) ||
|
||||
#endif
|
||||
nc != EC_get_builtin_curves(curves, nc)) {
|
||||
rv = APR_EGENERAL;
|
||||
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p,
|
||||
@ -1515,7 +1523,11 @@ apr_status_t md_cert_read_chain(apr_array_header_t *chain, apr_pool_t *p,
|
||||
md_cert_t *cert;
|
||||
int added = 0;
|
||||
|
||||
#ifdef MD_OPENSSL_10x
|
||||
if (NULL == (bf = BIO_new_mem_buf((char *)pem, (int)pem_len))) {
|
||||
#else
|
||||
if (NULL == (bf = BIO_new_mem_buf(pem, (int)pem_len))) {
|
||||
#endif
|
||||
rv = APR_ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
* @macro
|
||||
* Version number of the md module as c string
|
||||
*/
|
||||
#define MOD_MD_VERSION "2.5.1"
|
||||
#define MOD_MD_VERSION "2.5.2"
|
||||
|
||||
/**
|
||||
* @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 0x020501
|
||||
#define MOD_MD_VERSION_NUM 0x020502
|
||||
|
||||
#define MD_ACME_DEF_URL "https://acme-v02.api.letsencrypt.org/directory"
|
||||
#define MD_TAILSCALE_DEF_URL "file://localhost/var/run/tailscale/tailscaled.sock"
|
||||
|
@ -1292,17 +1292,59 @@ static int md_add_fallback_cert_files(server_rec *s, apr_pool_t *p,
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
static int md_get_challenge_cert(conn_rec *c, const char *servername,
|
||||
md_srv_conf_t *sc,
|
||||
md_pkey_type_t key_type,
|
||||
const char **pcert_pem,
|
||||
const char **pkey_pem)
|
||||
{
|
||||
apr_status_t rv = APR_ENOENT;
|
||||
int i;
|
||||
char *cert_name, *pkey_name;
|
||||
const char *cert_pem, *key_pem;
|
||||
md_store_t *store = md_reg_store_get(sc->mc->reg);
|
||||
md_pkey_spec_t *key_spec;
|
||||
|
||||
for (i = 0; i < md_pkeys_spec_count(sc->pks); i++) {
|
||||
key_spec = md_pkeys_spec_get(sc->pks, i);
|
||||
if (key_spec->type != key_type)
|
||||
continue;
|
||||
|
||||
tls_alpn01_fnames(c->pool, key_spec, &pkey_name, &cert_name);
|
||||
|
||||
rv = md_store_load(store, MD_SG_CHALLENGES, servername, cert_name, MD_SV_TEXT,
|
||||
(void**)&cert_pem, c->pool);
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c,
|
||||
"Load challenge: cert %s", cert_name);
|
||||
if (APR_STATUS_IS_ENOENT(rv)) continue;
|
||||
if (APR_SUCCESS != rv) goto cleanup;
|
||||
|
||||
rv = md_store_load(store, MD_SG_CHALLENGES, servername, pkey_name, MD_SV_TEXT,
|
||||
(void**)&key_pem, c->pool);
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c,
|
||||
"Load challenge: key %s", pkey_name);
|
||||
if (APR_STATUS_IS_ENOENT(rv)) continue;
|
||||
if (APR_SUCCESS != rv) goto cleanup;
|
||||
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
|
||||
"Found challenge: cert %s, key %s for %s",
|
||||
cert_name, pkey_name, servername);
|
||||
*pcert_pem = cert_pem;
|
||||
*pkey_pem = key_pem;
|
||||
return OK;
|
||||
}
|
||||
cleanup:
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
static int md_answer_challenge(conn_rec *c, const char *servername,
|
||||
const char **pcert_pem, const char **pkey_pem)
|
||||
{
|
||||
const char *protocol;
|
||||
int hook_rv = DECLINED;
|
||||
apr_status_t rv = APR_ENOENT;
|
||||
md_srv_conf_t *sc;
|
||||
md_store_t *store;
|
||||
char *cert_name, *pkey_name;
|
||||
const char *cert_pem, *key_pem;
|
||||
int i;
|
||||
|
||||
*pcert_pem = *pkey_pem = NULL;
|
||||
|
||||
if (!servername
|
||||
|| !(protocol = md_protocol_get(c))
|
||||
@ -1314,33 +1356,31 @@ static int md_answer_challenge(conn_rec *c, const char *servername,
|
||||
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
|
||||
"Answer challenge[tls-alpn-01] for %s", servername);
|
||||
store = md_reg_store_get(sc->mc->reg);
|
||||
|
||||
for (i = 0; i < md_pkeys_spec_count( sc->pks ); i++) {
|
||||
tls_alpn01_fnames(c->pool, md_pkeys_spec_get(sc->pks,i),
|
||||
&pkey_name, &cert_name);
|
||||
|
||||
rv = md_store_load(store, MD_SG_CHALLENGES, servername, cert_name, MD_SV_TEXT,
|
||||
(void**)&cert_pem, c->pool);
|
||||
if (APR_STATUS_IS_ENOENT(rv)) continue;
|
||||
if (APR_SUCCESS != rv) goto cleanup;
|
||||
|
||||
rv = md_store_load(store, MD_SG_CHALLENGES, servername, pkey_name, MD_SV_TEXT,
|
||||
(void**)&key_pem, c->pool);
|
||||
if (APR_STATUS_IS_ENOENT(rv)) continue;
|
||||
if (APR_SUCCESS != rv) goto cleanup;
|
||||
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
|
||||
"Found challenge cert %s, key %s for %s",
|
||||
cert_name, pkey_name, servername);
|
||||
*pcert_pem = cert_pem;
|
||||
*pkey_pem = key_pem;
|
||||
hook_rv = OK;
|
||||
break;
|
||||
}
|
||||
/* A challenge for TLS-ALPN-01 used to have a single certificate,
|
||||
* overriding the single fallback certificate already installed in
|
||||
* the connections SSL* instance.
|
||||
* Since the addition of `MDPrivateKeys`, there can be more than one,
|
||||
* but the server API for a challenge cert can return only one. This
|
||||
* is a short coming of the API.
|
||||
* This means we cannot override all fallback certificates present, just
|
||||
* a single one. If there is an RSA cert in fallback, we need to override
|
||||
* that, because the ACME server has a preference for that (at least LE
|
||||
* has). So we look for an RSA challenge cert first.
|
||||
* The fallback is an EC cert and that works since without RSA challenges,
|
||||
* there should also be no RSA fallbacks.
|
||||
* Bit of a mess. */
|
||||
hook_rv = md_get_challenge_cert(c, servername, sc, MD_PKEY_TYPE_DEFAULT,
|
||||
pcert_pem, pkey_pem);
|
||||
if (hook_rv == DECLINED)
|
||||
hook_rv = md_get_challenge_cert(c, servername, sc, MD_PKEY_TYPE_RSA,
|
||||
pcert_pem, pkey_pem);
|
||||
if (hook_rv == DECLINED)
|
||||
hook_rv = md_get_challenge_cert(c, servername, sc, MD_PKEY_TYPE_EC,
|
||||
pcert_pem, pkey_pem);
|
||||
|
||||
if (DECLINED == hook_rv) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_INFO, rv, c, APLOGNO(10080)
|
||||
ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(10080)
|
||||
"%s: unknown tls-alpn-01 challenge host", servername);
|
||||
}
|
||||
|
||||
|
@ -543,7 +543,7 @@ static void si_val_activity(status_ctx *ctx, md_json_t *mdj, const status_info *
|
||||
apr_brigade_puts(ctx->bb, NULL, NULL, "Pending");
|
||||
}
|
||||
else {
|
||||
apr_brigade_printf(ctx->bb, NULL, NULL, "%s: %s", ctx->prefix, "Pending");
|
||||
apr_brigade_printf(ctx->bb, NULL, NULL, "%s: %s", ctx->prefix, "Pending\n");
|
||||
}
|
||||
}
|
||||
else if (MD_RENEW_MANUAL == md_json_getl(mdj, MD_KEY_RENEW_MODE, NULL)) {
|
||||
@ -551,7 +551,7 @@ static void si_val_activity(status_ctx *ctx, md_json_t *mdj, const status_info *
|
||||
apr_brigade_puts(ctx->bb, NULL, NULL, "Manual renew");
|
||||
}
|
||||
else {
|
||||
apr_brigade_printf(ctx->bb, NULL, NULL, "%s: %s", ctx->prefix, "Manual renew");
|
||||
apr_brigade_printf(ctx->bb, NULL, NULL, "%s: %s", ctx->prefix, "Manual renew\n");
|
||||
}
|
||||
}
|
||||
if (!HTML_STATUS(ctx)) {
|
||||
|
Reference in New Issue
Block a user