summaryrefslogtreecommitdiff
path: root/modules/md
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2021-07-12 07:52:28 +0000
committerStefan Eissing <icing@apache.org>2021-07-12 07:52:28 +0000
commitc07608101f0700fb93001eb32935445777c6dab5 (patch)
tree5dc8ee307619310ccafc2fc18627661de5ec48a3 /modules/md
parentf087735b4d6e0dbefb74abe583b0ca44a9d81d37 (diff)
downloadhttpd-c07608101f0700fb93001eb32935445777c6dab5.tar.gz
*) mod_md: fixed a potential null pointer dereference if ACME/OCSP
server returned 2xx responses without content type. Reported by chuangwen. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1891470 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/md')
-rw-r--r--modules/md/md_acme.c3
-rw-r--r--modules/md/md_acme_authz.c4
-rw-r--r--modules/md/md_crypt.c57
-rw-r--r--modules/md/md_crypt.h4
-rw-r--r--modules/md/md_curl.c6
-rw-r--r--modules/md/md_json.c11
-rw-r--r--modules/md/md_jws.c8
-rw-r--r--modules/md/md_ocsp.c126
-rw-r--r--modules/md/md_store_fs.c57
-rw-r--r--modules/md/md_util.c57
-rw-r--r--modules/md/md_util.h37
-rw-r--r--modules/md/md_version.h4
-rw-r--r--modules/md/mod_md.c9
-rw-r--r--modules/md/mod_md.h27
-rw-r--r--modules/md/mod_md_ocsp.c68
-rw-r--r--modules/md/mod_md_ocsp.h6
16 files changed, 246 insertions, 238 deletions
diff --git a/modules/md/md_acme.c b/modules/md/md_acme.c
index 52fab0af1e..82e16125a4 100644
--- a/modules/md/md_acme.c
+++ b/modules/md/md_acme.c
@@ -227,7 +227,8 @@ static apr_status_t inspect_problem(md_acme_req_t *req, const md_http_response_t
static apr_status_t acmev2_req_init(md_acme_req_t *req, md_json_t *jpayload)
{
md_data_t payload;
-
+
+ md_data_null(&payload);
if (!req->acme->acct) {
return APR_EINVAL;
}
diff --git a/modules/md/md_acme_authz.c b/modules/md/md_acme_authz.c
index 883e319b48..bfbd67c11c 100644
--- a/modules/md/md_acme_authz.c
+++ b/modules/md/md_acme_authz.c
@@ -321,7 +321,7 @@ static apr_status_t cha_tls_alpn_01_setup(md_acme_authz_cha_t *cha, md_acme_auth
* The server will need to answer a TLS connection with SNI == authz->domain
* and ALPN procotol "acme-tls/1" with this certificate.
*/
- MD_DATA_SET_STR(&data, cha->key_authz);
+ md_data_init_str(&data, cha->key_authz);
rv = md_crypt_sha256_digest_hex(&token, p, &data);
if (APR_SUCCESS != rv) {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: create tls-alpn-01 validation token",
@@ -420,7 +420,7 @@ static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *
goto out;
}
- MD_DATA_SET_STR(&data, cha->key_authz);
+ md_data_init_str(&data, cha->key_authz);
rv = md_crypt_sha256_digest64(&token, p, &data);
if (APR_SUCCESS != rv) {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: create dns-01 token for %s",
diff --git a/modules/md/md_crypt.c b/modules/md/md_crypt.c
index 3992c6b12e..13c7edde5b 100644
--- a/modules/md/md_crypt.c
+++ b/modules/md/md_crypt.c
@@ -677,6 +677,7 @@ static apr_status_t pkey_to_buffer(md_data_t *buf, md_pkey_t *pkey, apr_pool_t *
return APR_EINVAL;
}
+ md_data_null(buf);
i = BIO_pending(bio);
if (i > 0) {
buf->data = apr_palloc(p, (apr_size_t)i);
@@ -904,8 +905,7 @@ static const char *bn64(const BIGNUM *b, apr_pool_t *p)
if (b) {
md_data_t buffer;
- buffer.len = (apr_size_t)BN_num_bytes(b);
- buffer.data = apr_pcalloc(p, buffer.len);
+ md_data_pinit(&buffer, (apr_size_t)BN_num_bytes(b), p);
if (buffer.data) {
BN_bn2bin(b, (unsigned char *)buffer.data);
return md_util_base64url_encode(&buffer, p);
@@ -946,9 +946,8 @@ apr_status_t md_crypt_sign64(const char **psign64, md_pkey_t *pkey, apr_pool_t *
unsigned int blen;
const char *sign64 = NULL;
apr_status_t rv = APR_ENOMEM;
-
- buffer.len = (apr_size_t)EVP_PKEY_size(pkey->pkey);
- buffer.data = apr_pcalloc(p, buffer.len);
+
+ md_data_pinit(&buffer, (apr_size_t)EVP_PKEY_size(pkey->pkey), p);
if (buffer.data) {
ctx = EVP_MD_CTX_create();
if (ctx) {
@@ -987,11 +986,9 @@ static apr_status_t sha256_digest(md_data_t **pdigest, apr_pool_t *p, const md_d
apr_status_t rv = APR_ENOMEM;
unsigned int dlen;
- digest = apr_palloc(p, sizeof(*digest));
+ digest = md_data_pmake(EVP_MAX_MD_SIZE, p);
if (!digest) goto leave;
- digest->data = apr_pcalloc(p, EVP_MAX_MD_SIZE);
- if (!digest->data) goto leave;
-
+
ctx = EVP_MD_CTX_create();
if (ctx) {
rv = APR_ENOTIMPL;
@@ -1303,7 +1300,8 @@ apr_status_t md_cert_fsave(md_cert_t *cert, apr_pool_t *p,
{
md_data_t buffer;
apr_status_t rv;
-
+
+ md_data_null(&buffer);
if (APR_SUCCESS == (rv = cert_to_buffer(&buffer, cert, p))) {
return md_util_freplace(fname, perms, p, fwrite_buffer, &buffer);
}
@@ -1314,7 +1312,8 @@ apr_status_t md_cert_to_base64url(const char **ps64, const md_cert_t *cert, apr_
{
md_data_t buffer;
apr_status_t rv;
-
+
+ md_data_null(&buffer);
if (APR_SUCCESS == (rv = cert_to_buffer(&buffer, cert, p))) {
*ps64 = md_util_base64url_encode(&buffer, p);
return APR_SUCCESS;
@@ -1328,11 +1327,9 @@ apr_status_t md_cert_to_sha256_digest(md_data_t **pdigest, const md_cert_t *cert
md_data_t *digest;
unsigned int dlen;
apr_status_t rv = APR_ENOMEM;
-
- digest = apr_palloc(p, sizeof(*digest));
+
+ digest = md_data_pmake(EVP_MAX_MD_SIZE, p);
if (!digest) goto leave;
- digest->data = apr_pcalloc(p, EVP_MAX_MD_SIZE);
- if (!digest->data) goto leave;
X509_digest(cert->x509, EVP_sha256(), (unsigned char*)digest->data, &dlen);
digest->len = dlen;
@@ -1346,7 +1343,7 @@ apr_status_t md_cert_to_sha256_fingerprint(const char **pfinger, const md_cert_t
{
md_data_t *digest;
apr_status_t rv;
-
+
rv = md_cert_to_sha256_digest(&digest, cert, p);
if (APR_SUCCESS == rv) {
return md_data_to_hex(pfinger, 0, p, digest);
@@ -1679,7 +1676,8 @@ apr_status_t md_cert_req_create(const char **pcsr_der_64, const char *name,
int csr_der_len;
assert(domains->nelts > 0);
-
+ md_data_null(&csr_der);
+
if (NULL == (csr = X509_REQ_new())
|| NULL == (exts = sk_X509_EXTENSION_new_null())
|| NULL == (n = X509_NAME_new())) {
@@ -1975,10 +1973,10 @@ apr_status_t md_cert_get_ct_scts(apr_array_header_t *scts, apr_pool_t *p, const
sct->version = SCT_get_version(sct_handle);
sct->timestamp = apr_time_from_msec(SCT_get_timestamp(sct_handle));
len = SCT_get0_log_id(sct_handle, (unsigned char**)&data);
- sct->logid = md_data_create(p, data, len);
+ sct->logid = md_data_make_pcopy(p, data, len);
sct->signature_type_nid = SCT_get_signature_nid(sct_handle);
len = SCT_get0_signature(sct_handle, (unsigned char**)&data);
- sct->signature = md_data_create(p, data, len);
+ sct->signature = md_data_make_pcopy(p, data, len);
APR_ARRAY_PUSH(scts, md_sct*) = sct;
}
@@ -1995,3 +1993,24 @@ apr_status_t md_cert_get_ct_scts(apr_array_header_t *scts, apr_pool_t *p, const
return APR_ENOTIMPL;
#endif
}
+
+apr_status_t md_cert_get_ocsp_responder_url(const char **purl, apr_pool_t *p, const md_cert_t *cert)
+{
+ STACK_OF(OPENSSL_STRING) *ssk;
+ apr_status_t rv = APR_SUCCESS;
+ const char *url = NULL;
+
+ ssk = X509_get1_ocsp(md_cert_get_X509(cert));
+ if (!ssk) {
+ rv = APR_ENOENT;
+ goto cleanup;
+ }
+ url = apr_pstrdup(p, sk_OPENSSL_STRING_value(ssk, 0));
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, p, "ocsp responder found '%s'", url);
+
+cleanup:
+ if (ssk) X509_email_free(ssk);
+ *purl = url;
+ return rv;
+}
+
diff --git a/modules/md/md_crypt.h b/modules/md/md_crypt.h
index cd1db29441..3aa03fc5a8 100644
--- a/modules/md/md_crypt.h
+++ b/modules/md/md_crypt.h
@@ -41,8 +41,6 @@ apr_status_t md_crypt_sha256_digest64(const char **pdigest64, apr_pool_t *p,
apr_status_t md_crypt_sha256_digest_hex(const char **pdigesthex, apr_pool_t *p,
const struct md_data_t *data);
-#define MD_DATA_SET_STR(d, s) do { (d)->data = (s); (d)->len = strlen(s); } while(0)
-
/**************************************************************************************************/
/* private keys */
@@ -218,6 +216,8 @@ apr_status_t md_cert_make_tls_alpn_01(md_cert_t **pcert, const char *domain,
apr_status_t md_cert_get_ct_scts(apr_array_header_t *scts, apr_pool_t *p, const md_cert_t *cert);
+apr_status_t md_cert_get_ocsp_responder_url(const char **purl, apr_pool_t *p, const md_cert_t *cert);
+
/**************************************************************************************************/
/* X509 certificate transparency */
diff --git a/modules/md/md_curl.c b/modules/md/md_curl.c
index e93bea4d42..59d83e52e8 100644
--- a/modules/md/md_curl.c
+++ b/modules/md/md_curl.c
@@ -213,8 +213,7 @@ static int curl_debug_log(CURL *curl, curl_infotype type, char *data, size_t siz
if (md_log_is_level(req->pool, MD_LOG_TRACE5)) {
md_data_t d;
const char *s;
- d.data = data;
- d.len = size;
+ md_data_init(&d, data, size);
md_data_to_hex(&s, 0, req->pool, &d);
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE5, 0, req->pool,
"req[%d]: data(hex) --> %s", req->id, s);
@@ -226,8 +225,7 @@ static int curl_debug_log(CURL *curl, curl_infotype type, char *data, size_t siz
if (md_log_is_level(req->pool, MD_LOG_TRACE5)) {
md_data_t d;
const char *s;
- d.data = data;
- d.len = size;
+ md_data_init(&d, data, size);
md_data_to_hex(&s, 0, req->pool, &d);
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE5, 0, req->pool,
"req[%d]: data(hex) <-- %s", req->id, s);
diff --git a/modules/md/md_json.c b/modules/md/md_json.c
index c81fb0f786..52187168cd 100644
--- a/modules/md/md_json.c
+++ b/modules/md/md_json.c
@@ -1185,15 +1185,18 @@ apr_status_t md_json_readf(md_json_t **pjson, apr_pool_t *p, const char *fpath)
apr_status_t md_json_read_http(md_json_t **pjson, apr_pool_t *pool, const md_http_response_t *res)
{
apr_status_t rv = APR_ENOENT;
- const char *ctype = apr_table_get(res->headers, "content-type"), *p;
+ const char *ctype, *p;
*pjson = NULL;
- ctype = md_util_parse_ct(res->req->pool, ctype);
+ if (!res->body) goto cleanup;
+ ctype = md_util_parse_ct(res->req->pool, apr_table_get(res->headers, "content-type"));
+ if (!ctype) goto cleanup;
p = ctype + strlen(ctype) +1;
- if (ctype && res->body && (!strcmp(p - sizeof("/json"), "/json") ||
- !strcmp(p - sizeof("+json"), "+json"))) {
+ if (!strcmp(p - sizeof("/json"), "/json")
+ || !strcmp(p - sizeof("+json"), "+json")) {
rv = md_json_readb(pjson, pool, res->body);
}
+cleanup:
return rv;
}
diff --git a/modules/md/md_jws.c b/modules/md/md_jws.c
index cfbe8da89b..4bdd99a125 100644
--- a/modules/md/md_jws.c
+++ b/modules/md/md_jws.c
@@ -38,7 +38,6 @@ apr_status_t md_jws_sign(md_json_t **pmsg, apr_pool_t *p,
md_json_t *msg, *jprotected;
const char *prot64, *pay64, *sign64, *sign, *prot;
apr_status_t rv = APR_SUCCESS;
- md_data_t data;
*pmsg = NULL;
@@ -64,8 +63,9 @@ apr_status_t md_jws_sign(md_json_t **pmsg, apr_pool_t *p,
}
if (rv == APR_SUCCESS) {
- data.data = prot;
- data.len = strlen(prot);
+ md_data_t data;
+
+ md_data_init(&data, prot, strlen(prot));
prot64 = md_util_base64url_encode(&data, p);
md_json_sets(prot64, msg, "protected", NULL);
pay64 = md_util_base64url_encode(payload, p);
@@ -104,7 +104,7 @@ apr_status_t md_jws_pkey_thumb(const char **pthumb, apr_pool_t *p, struct md_pke
/* whitespace and order is relevant, since we hand out a digest of this */
s = apr_psprintf(p, "{\"e\":\"%s\",\"kty\":\"RSA\",\"n\":\"%s\"}", e64, n64);
- MD_DATA_SET_STR(&data, s);
+ md_data_init_str(&data, s);
rv = md_crypt_sha256_digest64(pthumb, p, &data);
return rv;
}
diff --git a/modules/md/md_ocsp.c b/modules/md/md_ocsp.c
index d3f0e1577e..95ecaa3a68 100644
--- a/modules/md/md_ocsp.c
+++ b/modules/md/md_ocsp.c
@@ -99,6 +99,11 @@ struct md_ocsp_id_map_t {
md_data_t external_id;
};
+static void md_openssl_free(void *d)
+{
+ OPENSSL_free(d);
+}
+
const char *md_ocsp_cert_stat_name(md_ocsp_cert_stat_t stat)
{
switch (stat) {
@@ -121,11 +126,11 @@ apr_status_t md_ocsp_init_id(md_data_t *id, apr_pool_t *p, const md_cert_t *cert
X509 *x = md_cert_get_X509(cert);
unsigned int ulen = 0;
+ md_data_null(id);
if (X509_digest(x, EVP_sha1(), iddata, &ulen) != 1) {
return APR_EGENERAL;
}
- id->len = ulen;
- id->data = apr_pmemdup(p, iddata, id->len);
+ md_data_assign_pcopy(id, (const char*)iddata, ulen, p);
return APR_SUCCESS;
}
@@ -135,11 +140,7 @@ static void ostat_req_cleanup(md_ocsp_status_t *ostat)
OCSP_REQUEST_free(ostat->ocsp_req);
ostat->ocsp_req = NULL;
}
- if (ostat->req_der.data) {
- OPENSSL_free((void*)ostat->req_der.data);
- ostat->req_der.data = NULL;
- ostat->req_der.len = 0;
- }
+ md_data_clear(&ostat->req_der);
}
static int ostat_cleanup(void *ctx, const void *key, apr_ssize_t klen, const void *val)
@@ -155,11 +156,7 @@ static int ostat_cleanup(void *ctx, const void *key, apr_ssize_t klen, const voi
OCSP_CERTID_free(ostat->certid);
ostat->certid = NULL;
}
- if (ostat->resp_der.data) {
- OPENSSL_free((void*)ostat->resp_der.data);
- ostat->resp_der.data = NULL;
- ostat->resp_der.len = 0;
- }
+ md_data_clear(&ostat->resp_der);
return 1;
}
@@ -174,27 +171,12 @@ static int ostat_should_renew(md_ocsp_status_t *ostat)
static apr_status_t ostat_set(md_ocsp_status_t *ostat, md_ocsp_cert_stat_t stat,
md_data_t *der, md_timeperiod_t *valid, apr_time_t mtime)
{
- apr_status_t rv = APR_SUCCESS;
- char *s = (char*)der->data;
-
- if (der->len) {
- s = OPENSSL_malloc(der->len);
- if (!s) {
- rv = APR_ENOMEM;
- goto cleanup;
- }
- memcpy((char*)s, der->data, der->len);
- }
-
- if (ostat->resp_der.data) {
- OPENSSL_free((void*)ostat->resp_der.data);
- ostat->resp_der.data = NULL;
- ostat->resp_der.len = 0;
- }
-
+ apr_status_t rv;
+
+ rv = md_data_assign_copy(&ostat->resp_der, der->data, der->len);
+ if (APR_SUCCESS != rv) goto cleanup;
+
ostat->resp_stat = stat;
- ostat->resp_der.data = s;
- ostat->resp_der.len = der->len;
ostat->resp_valid = *valid;
ostat->resp_mtime = mtime;
@@ -328,8 +310,7 @@ apr_status_t md_ocsp_prime(md_ocsp_reg_t *reg, const char *ext_id, apr_size_t ex
md_cert_t *cert, md_cert_t *issuer, const md_t *md)
{
md_ocsp_status_t *ostat;
- STACK_OF(OPENSSL_STRING) *ssk = NULL;
- const char *name, *s;
+ const char *name;
md_data_t id;
apr_status_t rv = APR_SUCCESS;
@@ -355,19 +336,13 @@ apr_status_t md_ocsp_prime(md_ocsp_reg_t *reg, const char *ext_id, apr_size_t ex
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, reg->p,
"md[%s]: getting ocsp responder from cert", name);
- ssk = X509_get1_ocsp(md_cert_get_X509(cert));
- if (!ssk) {
- rv = APR_ENOENT;
- md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, reg->p,
- "md[%s]: certificate with serial %s has not OCSP responder URL",
+ rv = md_cert_get_ocsp_responder_url(&ostat->responder_url, reg->p, cert);
+ if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, reg->p,
+ "md[%s]: certificate with serial %s has not OCSP responder URL",
name, md_cert_get_serial_number(cert, reg->p));
goto cleanup;
}
- s = sk_OPENSSL_STRING_value(ssk, 0);
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, reg->p,
- "md[%s]: ocsp responder found '%s'", name, s);
- ostat->responder_url = apr_pstrdup(reg->p, s);
- X509_email_free(ssk);
ostat->certid = OCSP_cert_to_id(NULL, md_cert_get_X509(cert), md_cert_get_X509(issuer));
if (!ostat->certid) {
@@ -529,8 +504,9 @@ static const char *certid_as_hex(const OCSP_CERTID *certid, apr_pool_t *p)
memset(&der, 0, sizeof(der));
der.len = (apr_size_t)i2d_OCSP_CERTID((OCSP_CERTID*)certid, (unsigned char**)&der.data);
+ der.free_data = md_openssl_free;
md_data_to_hex(&hex, 0, p, &der);
- OPENSSL_free((void*)der.data);
+ md_data_clear(&der);
return hex;
}
@@ -716,8 +692,9 @@ static apr_status_t ostat_on_resp(const md_http_response_t *resp, void *baton)
md_result_log(update->result, MD_LOG_WARNING);
goto cleanup;
}
- nstat = (bstatus == V_OCSP_CERTSTATUS_GOOD)? MD_OCSP_CERT_ST_GOOD : MD_OCSP_CERT_ST_REVOKED;
new_der.len = (apr_size_t)n;
+ new_der.free_data = md_openssl_free;
+ nstat = (bstatus == V_OCSP_CERTSTATUS_GOOD)? MD_OCSP_CERT_ST_GOOD : MD_OCSP_CERT_ST_REVOKED;
valid.start = bup? md_asn1_generalized_time_get(bup) : apr_time_now();
valid.end = md_asn1_generalized_time_get(bnextup);
@@ -740,7 +717,7 @@ static apr_status_t ostat_on_resp(const md_http_response_t *resp, void *baton)
md_result_log(update->result, MD_LOG_DEBUG);
cleanup:
- if (new_der.data) OPENSSL_free((void*)new_der.data);
+ md_data_clear(&new_der);
if (basic_resp) OCSP_BASICRESP_free(basic_resp);
if (ocsp_resp) OCSP_RESPONSE_free(ocsp_resp);
return rv;
@@ -781,18 +758,52 @@ typedef struct {
int max_parallel;
} md_ocsp_todo_ctx_t;
+static apr_status_t ocsp_req_make(OCSP_REQUEST **pocsp_req, OCSP_CERTID *certid)
+{
+ OCSP_REQUEST *req = NULL;
+ OCSP_CERTID *id_copy = NULL;
+ apr_status_t rv = APR_ENOMEM;
+
+ req = OCSP_REQUEST_new();
+ if (!req) goto cleanup;
+ id_copy = OCSP_CERTID_dup(certid);
+ if (!id_copy) goto cleanup;
+ if (!OCSP_request_add0_id(req, id_copy)) goto cleanup;
+ id_copy = NULL;
+ OCSP_request_add1_nonce(req, 0, -1);
+ rv = APR_SUCCESS;
+cleanup:
+ if (id_copy) OCSP_CERTID_free(id_copy);
+ if (APR_SUCCESS != rv && req) {
+ OCSP_REQUEST_free(req);
+ req = NULL;
+ }
+ *pocsp_req = req;
+ return rv;
+}
+
+static apr_status_t ocsp_req_assign_der(md_data_t *d, OCSP_REQUEST *ocsp_req)
+{
+ int len;
+
+ md_data_clear(d);
+ len = i2d_OCSP_REQUEST(ocsp_req, (unsigned char**)&d->data);
+ if (len < 0) return APR_ENOMEM;
+ d->len = (apr_size_t)len;
+ d->free_data = md_openssl_free;
+ return APR_SUCCESS;
+}
+
static apr_status_t next_todo(md_http_request_t **preq, void *baton,
md_http_t *http, int in_flight)
{
md_ocsp_todo_ctx_t *ctx = baton;
md_ocsp_update_t *update, **pupdate;
md_ocsp_status_t *ostat;
- OCSP_CERTID *certid = NULL;
md_http_request_t *req = NULL;
apr_status_t rv = APR_ENOENT;
apr_table_t *headers;
- int len;
-
+
if (in_flight < ctx->max_parallel) {
pupdate = apr_array_pop(ctx->todos);
if (pupdate) {
@@ -804,18 +815,12 @@ static apr_status_t next_todo(md_http_request_t **preq, void *baton,
md_job_start_run(update->job, update->result, ctx->reg->store);
if (!ostat->ocsp_req) {
- ostat->ocsp_req = OCSP_REQUEST_new();
- if (!ostat->ocsp_req) goto cleanup;
- certid = OCSP_CERTID_dup(ostat->certid);
- if (!certid) goto cleanup;
- if (!OCSP_request_add0_id(ostat->ocsp_req, certid)) goto cleanup;
- OCSP_request_add1_nonce(ostat->ocsp_req, 0, -1);
- certid = NULL;
+ rv = ocsp_req_make(&ostat->ocsp_req, ostat->certid);
+ if (APR_SUCCESS != rv) goto cleanup;
}
if (0 == ostat->req_der.len) {
- len = i2d_OCSP_REQUEST(ostat->ocsp_req, (unsigned char**)&ostat->req_der.data);
- if (len < 0) goto cleanup;
- ostat->req_der.len = (apr_size_t)len;
+ rv = ocsp_req_assign_der(&ostat->req_der, ostat->ocsp_req);
+ if (APR_SUCCESS != rv) goto cleanup;
}
md_result_activity_printf(update->result, "status of certid %s, "
"contacting %s", ostat->hexid, ostat->responder_url);
@@ -831,7 +836,6 @@ static apr_status_t next_todo(md_http_request_t **preq, void *baton,
}
cleanup:
*preq = (APR_SUCCESS == rv)? req : NULL;
- if (certid) OCSP_CERTID_free(certid);
return rv;
}
diff --git a/modules/md/md_store_fs.c b/modules/md/md_store_fs.c
index 7ba822a4e2..038bcc50c4 100644
--- a/modules/md/md_store_fs.c
+++ b/modules/md/md_store_fs.c
@@ -110,8 +110,7 @@ static apr_status_t init_store_file(md_store_fs_t *s_fs, const char *fname,
md_json_setn(MD_STORE_VERSION, json, MD_KEY_STORE, MD_KEY_VERSION, NULL);
- s_fs->key.len = FS_STORE_KLEN;
- s_fs->key.data = apr_pcalloc(p, FS_STORE_KLEN);
+ md_data_pinit(&s_fs->key, FS_STORE_KLEN, p);
if (APR_SUCCESS != (rv = md_rand_bytes((unsigned char*)s_fs->key.data, s_fs->key.len, p))) {
return rv;
}
@@ -316,18 +315,29 @@ apr_status_t md_store_fs_init(md_store_t **pstore, apr_pool_t *p, const char *pa
s_fs->group_perms[MD_SG_OCSP].file = MD_FPROT_F_UALL_WREAD;
s_fs->base = apr_pstrdup(p, path);
-
- if (APR_STATUS_IS_ENOENT(rv = md_util_is_dir(s_fs->base, p))
- && MD_OK(apr_dir_make_recursive(s_fs->base, s_fs->def_perms.dir, p))) {
+
+ rv = md_util_is_dir(s_fs->base, p);
+ if (APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, p,
+ "store directory does not exist, creating %s", s_fs->base);
+ rv = apr_dir_make_recursive(s_fs->base, s_fs->def_perms.dir, p);
+ if (APR_SUCCESS != rv) goto cleanup;
rv = apr_file_perms_set(s_fs->base, MD_FPROT_D_UALL_WREAD);
if (APR_STATUS_IS_ENOTIMPL(rv)) {
rv = APR_SUCCESS;
}
+ if (APR_SUCCESS != rv) goto cleanup;
}
-
- if ((APR_SUCCESS != rv) || !MD_OK(md_util_pool_vdo(setup_store_file, s_fs, p, NULL))) {
- md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "init fs store at %s", path);
+ else if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
+ "not a plain directory, maybe a symlink? %s", s_fs->base);
}
+
+ rv = md_util_pool_vdo(setup_store_file, s_fs, p, NULL);
+ if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "init fs store at %s", s_fs->base);
+ }
+cleanup:
*pstore = (rv == APR_SUCCESS)? &(s_fs->s) : NULL;
return rv;
}
@@ -493,21 +503,24 @@ static apr_status_t mk_group_dir(const char **pdir, md_store_fs_t *s_fs,
perms = gperms(s_fs, group);
- if (MD_OK(fs_get_dname(pdir, &s_fs->s, group, name, p)) && (MD_SG_NONE != group)) {
- if ( !MD_OK(md_util_is_dir(*pdir, p))
- && MD_OK(apr_dir_make_recursive(*pdir, perms->dir, p))) {
- rv = dispatch(s_fs, MD_S_FS_EV_CREATED, group, *pdir, APR_DIR, p);
- }
-
- if (APR_SUCCESS == rv) {
- rv = apr_file_perms_set(*pdir, perms->dir);
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p, "mk_group_dir %s perm set", *pdir);
- if (APR_STATUS_IS_ENOTIMPL(rv)) {
- rv = APR_SUCCESS;
- }
- }
+ rv = fs_get_dname(pdir, &s_fs->s, group, name, p);
+ if ((APR_SUCCESS != rv) || (MD_SG_NONE == group)) goto cleanup;
+
+ rv = md_util_is_dir(*pdir, p);
+ if (APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "not a directory, creating %s", *pdir);
+ rv = apr_dir_make_recursive(*pdir, perms->dir, p);
+ if (APR_SUCCESS != rv) goto cleanup;
+ dispatch(s_fs, MD_S_FS_EV_CREATED, group, *pdir, APR_DIR, p);
+ }
+
+ rv = apr_file_perms_set(*pdir, perms->dir);
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "mk_group_dir %s perm set", *pdir);
+ if (APR_STATUS_IS_ENOTIMPL(rv)) {
+ rv = APR_SUCCESS;
}
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p, "mk_group_dir %d %s", group, name);
+cleanup:
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "mk_group_dir %d %s", group, name);
return rv;
}
diff --git a/modules/md/md_util.c b/modules/md/md_util.c
index 34e891d1ce..23923c8b2e 100644
--- a/modules/md/md_util.c
+++ b/modules/md/md_util.c
@@ -76,28 +76,73 @@ apr_status_t md_util_pool_vdo(md_util_vaction *cb, void *baton, apr_pool_t *p, .
/**************************************************************************************************/
/* data chunks */
-md_data_t *md_data_create(apr_pool_t *p, const char *data, apr_size_t len)
+void md_data_pinit(md_data_t *d, apr_size_t len, apr_pool_t *p)
+{
+ md_data_null(d);
+ d->data = apr_pcalloc(p, len);
+ d->len = len;
+}
+
+md_data_t *md_data_pmake(apr_size_t len, apr_pool_t *p)
{
md_data_t *d;
d = apr_palloc(p, sizeof(*d));
- d->len = len;
- d->data = len? apr_pstrndup(p, data, len) : NULL;
+ md_data_pinit(d, len, p);
return d;
}
-md_data_t *md_data_make(apr_pool_t *p, apr_size_t len)
+void md_data_init(md_data_t *d, const char *data, apr_size_t len)
+{
+ md_data_null(d);
+ d->len = len;
+ d->data = data;
+}
+
+void md_data_init_str(md_data_t *d, const char *str)
+{
+ md_data_init(d, str, strlen(str));
+}
+
+void md_data_null(md_data_t *d)
+{
+ memset(d, 0, sizeof(*d));
+}
+
+void md_data_clear(md_data_t *d)
+{
+ if (d) {
+ if (d->data && d->free_data) d->free_data((void*)d->data);
+ memset(d, 0, sizeof(*d));
+ }
+}
+
+md_data_t *md_data_make_pcopy(apr_pool_t *p, const char *data, apr_size_t len)
{
md_data_t *d;
-
+
d = apr_palloc(p, sizeof(*d));
d->len = len;
- d->data = apr_pcalloc(p, len);
+ d->data = len? apr_pmemdup(p, data, len) : NULL;
return d;
}
+apr_status_t md_data_assign_copy(md_data_t *dest, const char *src, apr_size_t src_len)
+{
+ md_data_clear(dest);
+ if (src && src_len) {
+ dest->data = malloc(src_len);
+ if (!dest->data) return APR_ENOMEM;
+ memcpy((void*)dest->data, src, src_len);
+ dest->len = src_len;
+ dest->free_data = free;
+ }
+ return APR_SUCCESS;
+}
+
void md_data_assign_pcopy(md_data_t *dest, const char *src, apr_size_t src_len, apr_pool_t *p)
{
+ md_data_clear(dest);
dest->data = (src && src_len)? apr_pmemdup(p, src, src_len) : NULL;
dest->len = dest->data? src_len : 0;
}
diff --git a/modules/md/md_util.h b/modules/md/md_util.h
index 67d0e5128a..71e66eb500 100644
--- a/modules/md/md_util.h
+++ b/modules/md/md_util.h
@@ -35,17 +35,48 @@ apr_status_t md_util_pool_vdo(md_util_vaction *cb, void *baton, apr_pool_t *p, .
/**************************************************************************************************/
/* data chunks */
+typedef void md_data_free_fn(void *data);
+
typedef struct md_data_t md_data_t;
struct md_data_t {
const char *data;
apr_size_t len;
+ md_data_free_fn *free_data;
};
-#define MD_DATA_CWRAP(d, buffer) md_data_t d = { buffer, sizeof(buffer) }
+/**
+ * Init the data to empty, overwriting any content.
+ */
+void md_data_null(md_data_t *d);
+
+/**
+ * Create a new md_data_t, providing `len` bytes allocated from pool `p`.
+ */
+md_data_t *md_data_pmake(apr_size_t len, apr_pool_t *p);
+/**
+ * Initialize md_data_t 'd', providing `len` bytes allocated from pool `p`.
+ */
+void md_data_pinit(md_data_t *d, apr_size_t len, apr_pool_t *p);
+/**
+ * Initialize md_data_t 'd', by borrowing 'len' bytes in `data` without copying.
+ * `d` will not take ownership.
+ */
+void md_data_init(md_data_t *d, const char *data, apr_size_t len);
+
+/**
+ * Initialize md_data_t 'd', by borrowing the NUL-terminated `str`.
+ * `d` will not take ownership.
+ */
+void md_data_init_str(md_data_t *d, const char *str);
+
+/**
+ * Free any present data and clear (NULL) it. Passing NULL is permitted.
+ */
+void md_data_clear(md_data_t *d);
-md_data_t *md_data_make(apr_pool_t *p, apr_size_t len);
-md_data_t *md_data_create(apr_pool_t *p, const char *data, apr_size_t len);
+md_data_t *md_data_make_pcopy(apr_pool_t *p, const char *data, apr_size_t len);
+apr_status_t md_data_assign_copy(md_data_t *dest, const char *src, apr_size_t src_len);
void md_data_assign_pcopy(md_data_t *dest, const char *src, apr_size_t src_len, apr_pool_t *p);
apr_status_t md_data_to_hex(const char **phex, char separator,
diff --git a/modules/md/md_version.h b/modules/md/md_version.h
index 909258c3f8..5cef365c3d 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 "2.4.2"
+#define MOD_MD_VERSION "2.4.3"
/**
* @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 0x020402
+#define MOD_MD_VERSION_NUM 0x020403
#define MD_ACME_DEF_URL "https://acme-v02.api.letsencrypt.org/directory"
diff --git a/modules/md/mod_md.c b/modules/md/mod_md.c
index 647b5ba2ee..180cfd2c68 100644
--- a/modules/md/mod_md.c
+++ b/modules/md/mod_md.c
@@ -1501,16 +1501,11 @@ static void md_hooks(apr_pool_t *pool)
ap_hook_ssl_add_cert_files(md_add_cert_files, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_ssl_add_fallback_cert_files(md_add_fallback_cert_files, NULL, NULL, APR_HOOK_MIDDLE);
-#if AP_MODULE_MAGIC_AT_LEAST(20210420, 0)
+#if AP_MODULE_MAGIC_AT_LEAST(20120211, 105)
ap_hook_ssl_ocsp_prime_hook(md_ocsp_prime_status, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_ssl_ocsp_get_resp_hook(md_ocsp_provide_status, NULL, NULL, APR_HOOK_MIDDLE);
#else
-
-#ifndef SSL_CERT_HOOKS
-#error "This version of mod_md requires Apache httpd 2.4.41 or newer."
-#endif
- APR_OPTIONAL_HOOK(ssl, init_stapling_status, md_ocsp_init_stapling_status, NULL, NULL, APR_HOOK_MIDDLE);
- APR_OPTIONAL_HOOK(ssl, get_stapling_status, md_ocsp_get_stapling_status, NULL, NULL, APR_HOOK_MIDDLE);
+#error "This version of mod_md requires Apache httpd 2.4.48 or newer."
#endif /* AP_MODULE_MAGIC_AT_LEAST() */
}
diff --git a/modules/md/mod_md.h b/modules/md/mod_md.h
index 39b62f853f..805737d19e 100644
--- a/modules/md/mod_md.h
+++ b/modules/md/mod_md.h
@@ -17,31 +17,4 @@
#ifndef mod_md_mod_md_h
#define mod_md_mod_md_h
-#include <openssl/evp.h>
-#include <openssl/x509v3.h>
-
-struct server_rec;
-
-APR_DECLARE_OPTIONAL_FN(int,
- md_is_managed, (struct server_rec *));
-
-/**
- * Get the certificate/key for the managed domain (md_is_managed != 0).
- *
- * @return APR_EAGAIN if the real certificate is not available yet
- */
-APR_DECLARE_OPTIONAL_FN(apr_status_t,
- md_get_certificate, (struct server_rec *, apr_pool_t *,
- const char **pkeyfile,
- const char **pcertfile));
-
-APR_DECLARE_OPTIONAL_FN(int,
- md_is_challenge, (struct conn_rec *, const char *,
- X509 **pcert, EVP_PKEY **pkey));
-
-APR_DECLARE_OPTIONAL_FN(apr_status_t,
- md_answer_challenges, (conn_rec *c, const char *servername,
- apr_array_header_t *certs,
- apr_array_header_t *pkeys));
-
#endif /* mod_md_mod_md_h */
diff --git a/modules/md/mod_md_ocsp.c b/modules/md/mod_md_ocsp.c
index 0f64676025..1d1e2827de 100644
--- a/modules/md/mod_md_ocsp.c
+++ b/modules/md/mod_md_ocsp.c
@@ -53,29 +53,6 @@ static int staple_here(md_srv_conf_t *sc)
&& md_config_geti(sc, MD_CONFIG_STAPLE_OTHERS));
}
-int md_ocsp_init_stapling_status(server_rec *s, apr_pool_t *p,
- X509 *cert, X509 *issuer)
-{
- md_srv_conf_t *sc;
- const md_t *md;
- apr_status_t rv;
-
- sc = md_config_get(s);
- if (!staple_here(sc)) goto declined;
- md = ((sc->assigned && sc->assigned->nelts == 1)?
- APR_ARRAY_IDX(sc->assigned, 0, const md_t*) : NULL);
-
- rv = md_ocsp_prime(sc->mc->ocsp, NULL, 0, md_cert_wrap(p, cert),
- md_cert_wrap(p, issuer), md);
- ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, s, "init stapling for: %s",
- md? md->name : s->server_hostname);
- if (APR_SUCCESS == rv) {
- return OK;
- }
-declined:
- return DECLINED;
-}
-
int md_ocsp_prime_status(server_rec *s, apr_pool_t *p,
const char *id, apr_size_t id_len, const char *pem)
{
@@ -118,51 +95,6 @@ typedef struct {
apr_size_t der_len;
} ocsp_copy_ctx_t;
-static void ocsp_copy_der(const unsigned char *der, apr_size_t der_len, void *userdata)
-{
- ocsp_copy_ctx_t *ctx = userdata;
-
- memset(ctx, 0, sizeof(*ctx));
- if (der && der_len > 0) {
- ctx->der = OPENSSL_malloc(der_len);
- if (ctx->der != NULL) {
- ctx->der_len = der_len;
- memcpy(ctx->der, der, der_len);
- }
- }
-}
-
-int md_ocsp_get_stapling_status(unsigned char **pder, int *pderlen,
- conn_rec *c, server_rec *s, X509 *x)
-{
- md_srv_conf_t *sc;
- const md_t *md;
- md_cert_t *cert;
- md_data_t id;
- apr_status_t rv;
- ocsp_copy_ctx_t ctx;
-
- sc = md_config_get(s);
- if (!staple_here(sc)) goto declined;
-
- md = ((sc->assigned && sc->assigned->nelts == 1)?
- APR_ARRAY_IDX(sc->assigned, 0, const md_t*) : NULL);
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "get stapling for: %s",
- md? md->name : s->server_hostname);
- cert = md_cert_wrap(c->pool, x);
- rv = md_ocsp_init_id(&id, c->pool, cert);
- if (APR_SUCCESS != rv) goto declined;
-
- rv = md_ocsp_get_status(ocsp_copy_der, &ctx, sc->mc->ocsp, id.data, id.len, c->pool, md);
- if (APR_STATUS_IS_ENOENT(rv)) goto declined;
- *pder = ctx.der;
- *pderlen = (int)ctx.der_len;
- return OK;
-
-declined:
- return DECLINED;
-}
-
int md_ocsp_provide_status(server_rec *s, conn_rec *c,
const char *id, apr_size_t id_len,
ap_ssl_ocsp_copy_resp *cb, void *userdata)
diff --git a/modules/md/mod_md_ocsp.h b/modules/md/mod_md_ocsp.h
index dcc6e49c5a..a3f95027cb 100644
--- a/modules/md/mod_md_ocsp.h
+++ b/modules/md/mod_md_ocsp.h
@@ -18,12 +18,6 @@
#define mod_md_md_ocsp_h
-int md_ocsp_init_stapling_status(server_rec *s, apr_pool_t *p,
- X509 *cert, X509 *issuer);
-
-int md_ocsp_get_stapling_status(unsigned char **pder, int *pderlen,
- conn_rec *c, server_rec *s, X509 *cert);
-
int md_ocsp_prime_status(server_rec *s, apr_pool_t *p,
const char *id, apr_size_t id_len, const char *pem);