"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/md_ocsp.c" between
mod_md-2.4.2.tar.gz and mod_md-2.4.4.tar.gz

About: mod_md is an Apache module that adds Let's Encrypt (ACME) support.

md_ocsp.c  (mod_md-2.4.2):md_ocsp.c  (mod_md-2.4.4)
skipping to change at line 102 skipping to change at line 102
apr_time_t resp_mtime; apr_time_t resp_mtime;
apr_time_t resp_last_check; apr_time_t resp_last_check;
}; };
typedef struct md_ocsp_id_map_t md_ocsp_id_map_t; typedef struct md_ocsp_id_map_t md_ocsp_id_map_t;
struct md_ocsp_id_map_t { struct md_ocsp_id_map_t {
md_data_t id; md_data_t id;
md_data_t external_id; 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) const char *md_ocsp_cert_stat_name(md_ocsp_cert_stat_t stat)
{ {
switch (stat) { switch (stat) {
case MD_OCSP_CERT_ST_GOOD: return "good"; case MD_OCSP_CERT_ST_GOOD: return "good";
case MD_OCSP_CERT_ST_REVOKED: return "revoked"; case MD_OCSP_CERT_ST_REVOKED: return "revoked";
default: return "unknown"; default: return "unknown";
} }
} }
md_ocsp_cert_stat_t md_ocsp_cert_stat_value(const char *name) md_ocsp_cert_stat_t md_ocsp_cert_stat_value(const char *name)
skipping to change at line 124 skipping to change at line 129
if (name && !strcmp("revoked", name)) return MD_OCSP_CERT_ST_REVOKED; if (name && !strcmp("revoked", name)) return MD_OCSP_CERT_ST_REVOKED;
return MD_OCSP_CERT_ST_UNKNOWN; return MD_OCSP_CERT_ST_UNKNOWN;
} }
apr_status_t md_ocsp_init_id(md_data_t *id, apr_pool_t *p, const md_cert_t *cert ) apr_status_t md_ocsp_init_id(md_data_t *id, apr_pool_t *p, const md_cert_t *cert )
{ {
unsigned char iddata[SHA_DIGEST_LENGTH]; unsigned char iddata[SHA_DIGEST_LENGTH];
X509 *x = md_cert_get_X509(cert); X509 *x = md_cert_get_X509(cert);
unsigned int ulen = 0; unsigned int ulen = 0;
md_data_null(id);
if (X509_digest(x, EVP_sha1(), iddata, &ulen) != 1) { if (X509_digest(x, EVP_sha1(), iddata, &ulen) != 1) {
return APR_EGENERAL; return APR_EGENERAL;
} }
id->len = ulen; md_data_assign_pcopy(id, (const char*)iddata, ulen, p);
id->data = apr_pmemdup(p, iddata, id->len);
return APR_SUCCESS; return APR_SUCCESS;
} }
static void ostat_req_cleanup(md_ocsp_status_t *ostat) static void ostat_req_cleanup(md_ocsp_status_t *ostat)
{ {
if (ostat->ocsp_req) { if (ostat->ocsp_req) {
OCSP_REQUEST_free(ostat->ocsp_req); OCSP_REQUEST_free(ostat->ocsp_req);
ostat->ocsp_req = NULL; ostat->ocsp_req = NULL;
} }
if (ostat->req_der.data) { md_data_clear(&ostat->req_der);
OPENSSL_free((void*)ostat->req_der.data);
ostat->req_der.data = NULL;
ostat->req_der.len = 0;
}
} }
static int ostat_cleanup(void *ctx, const void *key, apr_ssize_t klen, const voi d *val) static int ostat_cleanup(void *ctx, const void *key, apr_ssize_t klen, const voi d *val)
{ {
md_ocsp_reg_t *reg = ctx; md_ocsp_reg_t *reg = ctx;
md_ocsp_status_t *ostat = (md_ocsp_status_t *)val; md_ocsp_status_t *ostat = (md_ocsp_status_t *)val;
(void)reg; (void)reg;
(void)key; (void)key;
(void)klen; (void)klen;
ostat_req_cleanup(ostat); ostat_req_cleanup(ostat);
if (ostat->certid) { if (ostat->certid) {
OCSP_CERTID_free(ostat->certid); OCSP_CERTID_free(ostat->certid);
ostat->certid = NULL; ostat->certid = NULL;
} }
if (ostat->resp_der.data) { md_data_clear(&ostat->resp_der);
OPENSSL_free((void*)ostat->resp_der.data);
ostat->resp_der.data = NULL;
ostat->resp_der.len = 0;
}
return 1; return 1;
} }
static int ostat_should_renew(md_ocsp_status_t *ostat) static int ostat_should_renew(md_ocsp_status_t *ostat)
{ {
md_timeperiod_t renewal; md_timeperiod_t renewal;
renewal = md_timeperiod_slice_before_end(&ostat->resp_valid, &ostat->reg->re new_window); renewal = md_timeperiod_slice_before_end(&ostat->resp_valid, &ostat->reg->re new_window);
return md_timeperiod_has_started(&renewal, apr_time_now()); return md_timeperiod_has_started(&renewal, apr_time_now());
} }
static apr_status_t ostat_set(md_ocsp_status_t *ostat, md_ocsp_cert_stat_t stat, 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) md_data_t *der, md_timeperiod_t *valid, apr_time_t mtime)
{ {
apr_status_t rv = APR_SUCCESS; apr_status_t rv;
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) { rv = md_data_assign_copy(&ostat->resp_der, der->data, der->len);
OPENSSL_free((void*)ostat->resp_der.data); if (APR_SUCCESS != rv) goto cleanup;
ostat->resp_der.data = NULL;
ostat->resp_der.len = 0;
}
ostat->resp_stat = stat; ostat->resp_stat = stat;
ostat->resp_der.data = s;
ostat->resp_der.len = der->len;
ostat->resp_valid = *valid; ostat->resp_valid = *valid;
ostat->resp_mtime = mtime; ostat->resp_mtime = mtime;
ostat->errors = 0; ostat->errors = 0;
ostat->next_run = md_timeperiod_slice_before_end( ostat->next_run = md_timeperiod_slice_before_end(
&ostat->resp_valid, &ostat->reg->renew_window).start; &ostat->resp_valid, &ostat->reg->renew_window).start;
cleanup: cleanup:
return rv; return rv;
} }
skipping to change at line 330 skipping to change at line 312
apr_pool_cleanup_register(p, reg, ocsp_reg_cleanup, apr_pool_cleanup_null); apr_pool_cleanup_register(p, reg, ocsp_reg_cleanup, apr_pool_cleanup_null);
cleanup: cleanup:
*preg = (APR_SUCCESS == rv)? reg : NULL; *preg = (APR_SUCCESS == rv)? reg : NULL;
return rv; return rv;
} }
apr_status_t md_ocsp_prime(md_ocsp_reg_t *reg, const char *ext_id, apr_size_t ex t_id_len, apr_status_t md_ocsp_prime(md_ocsp_reg_t *reg, const char *ext_id, apr_size_t ex t_id_len,
md_cert_t *cert, md_cert_t *issuer, const md_t *md) md_cert_t *cert, md_cert_t *issuer, const md_t *md)
{ {
md_ocsp_status_t *ostat; md_ocsp_status_t *ostat;
STACK_OF(OPENSSL_STRING) *ssk = NULL; const char *name;
const char *name, *s;
md_data_t id; md_data_t id;
apr_status_t rv = APR_SUCCESS; apr_status_t rv = APR_SUCCESS;
/* Called during post_config. no mutex protection needed */ /* Called during post_config. no mutex protection needed */
name = md? md->name : MD_OTHER; name = md? md->name : MD_OTHER;
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, reg->p, md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, reg->p,
"md[%s]: priming OCSP status", name); "md[%s]: priming OCSP status", name);
rv = md_ocsp_init_id(&id, reg->p, cert); rv = md_ocsp_init_id(&id, reg->p, cert);
if (APR_SUCCESS != rv) goto cleanup; if (APR_SUCCESS != rv) goto cleanup;
skipping to change at line 357 skipping to change at line 338
ostat->id = id; ostat->id = id;
ostat->reg = reg; ostat->reg = reg;
ostat->md_name = name; ostat->md_name = name;
md_data_to_hex(&ostat->hexid, 0, reg->p, &ostat->id); md_data_to_hex(&ostat->hexid, 0, reg->p, &ostat->id);
ostat->file_name = apr_psprintf(reg->p, "ocsp-%s.json", ostat->hexid); ostat->file_name = apr_psprintf(reg->p, "ocsp-%s.json", ostat->hexid);
rv = md_cert_to_sha256_fingerprint(&ostat->hex_sha256, cert, reg->p); rv = md_cert_to_sha256_fingerprint(&ostat->hex_sha256, cert, reg->p);
if (APR_SUCCESS != rv) goto cleanup; if (APR_SUCCESS != rv) goto cleanup;
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, reg->p, md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, reg->p,
"md[%s]: getting ocsp responder from cert", name); "md[%s]: getting ocsp responder from cert", name);
ssk = X509_get1_ocsp(md_cert_get_X509(cert)); rv = md_cert_get_ocsp_responder_url(&ostat->responder_url, reg->p, cert);
if (!ssk) { if (APR_SUCCESS != rv) {
rv = APR_ENOENT;
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, reg->p, md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, reg->p,
"md[%s]: certificate with serial %s has not OCSP responder URL", "md[%s]: certificate with serial %s has not OCSP responder URL",
name, md_cert_get_serial_number(cert, reg->p)); name, md_cert_get_serial_number(cert, reg->p));
goto cleanup; 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_X5 09(issuer)); ostat->certid = OCSP_cert_to_id(NULL, md_cert_get_X509(cert), md_cert_get_X5 09(issuer));
if (!ostat->certid) { if (!ostat->certid) {
rv = APR_EGENERAL; rv = APR_EGENERAL;
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, reg->p, md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, reg->p,
"md[%s]: unable to create OCSP certid for certificate with serial %s", "md[%s]: unable to create OCSP certid for certificate with serial %s",
name, md_cert_get_serial_number(cert, reg->p)); name, md_cert_get_serial_number(cert, reg->p));
goto cleanup; goto cleanup;
} }
skipping to change at line 531 skipping to change at line 506
return apr_hash_count(reg->ostat_by_id); return apr_hash_count(reg->ostat_by_id);
} }
static const char *certid_as_hex(const OCSP_CERTID *certid, apr_pool_t *p) static const char *certid_as_hex(const OCSP_CERTID *certid, apr_pool_t *p)
{ {
md_data_t der; md_data_t der;
const char *hex; const char *hex;
memset(&der, 0, sizeof(der)); memset(&der, 0, sizeof(der));
der.len = (apr_size_t)i2d_OCSP_CERTID((OCSP_CERTID*)certid, (unsigned char** )&der.data); 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); md_data_to_hex(&hex, 0, p, &der);
OPENSSL_free((void*)der.data); md_data_clear(&der);
return hex; return hex;
} }
static const char *certid_summary(const OCSP_CERTID *certid, apr_pool_t *p) static const char *certid_summary(const OCSP_CERTID *certid, apr_pool_t *p)
{ {
const char *serial, *issuer, *key, *s; const char *serial, *issuer, *key, *s;
ASN1_INTEGER *aserial; ASN1_INTEGER *aserial;
ASN1_OCTET_STRING *aname_hash, *akey_hash; ASN1_OCTET_STRING *aname_hash, *akey_hash;
ASN1_OBJECT *amd_nid; ASN1_OBJECT *amd_nid;
BIGNUM *bn; BIGNUM *bn;
skipping to change at line 718 skipping to change at line 694
/* Coming here, we have a response for our certid and it is either GOOD /* Coming here, we have a response for our certid and it is either GOOD
* or REVOKED. Both cases we want to remember and use in stapling. */ * or REVOKED. Both cases we want to remember and use in stapling. */
n = i2d_OCSP_RESPONSE(ocsp_resp, (unsigned char**)&new_der.data); n = i2d_OCSP_RESPONSE(ocsp_resp, (unsigned char**)&new_der.data);
if (n <= 0) { if (n <= 0) {
rv = APR_EGENERAL; rv = APR_EGENERAL;
md_result_set(update->result, rv, "error DER encoding OCSP response"); md_result_set(update->result, rv, "error DER encoding OCSP response");
md_result_log(update->result, MD_LOG_WARNING); md_result_log(update->result, MD_LOG_WARNING);
goto cleanup; 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.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.start = bup? md_asn1_generalized_time_get(bup) : apr_time_now();
valid.end = md_asn1_generalized_time_get(bnextup); valid.end = md_asn1_generalized_time_get(bnextup);
/* First, update the instance with a copy */ /* First, update the instance with a copy */
apr_thread_mutex_lock(ostat->reg->mutex); apr_thread_mutex_lock(ostat->reg->mutex);
ostat_set(ostat, nstat, &new_der, &valid, apr_time_now()); ostat_set(ostat, nstat, &new_der, &valid, apr_time_now());
apr_thread_mutex_unlock(ostat->reg->mutex); apr_thread_mutex_unlock(ostat->reg->mutex);
/* Next, save the original response */ /* Next, save the original response */
rv = ocsp_status_save(nstat, &new_der, &valid, ostat, req->pool); rv = ocsp_status_save(nstat, &new_der, &valid, ostat, req->pool);
skipping to change at line 742 skipping to change at line 719
md_result_log(update->result, MD_LOG_ERR); md_result_log(update->result, MD_LOG_ERR);
goto cleanup; goto cleanup;
} }
md_result_printf(update->result, rv, "certificate status is %s, status valid %s", md_result_printf(update->result, rv, "certificate status is %s, status valid %s",
(nstat == MD_OCSP_CERT_ST_GOOD)? "GOOD" : "REVOKED", (nstat == MD_OCSP_CERT_ST_GOOD)? "GOOD" : "REVOKED",
md_timeperiod_print(req->pool, &ostat->resp_valid)); md_timeperiod_print(req->pool, &ostat->resp_valid));
md_result_log(update->result, MD_LOG_DEBUG); md_result_log(update->result, MD_LOG_DEBUG);
cleanup: 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 (basic_resp) OCSP_BASICRESP_free(basic_resp);
if (ocsp_resp) OCSP_RESPONSE_free(ocsp_resp); if (ocsp_resp) OCSP_RESPONSE_free(ocsp_resp);
return rv; return rv;
} }
static apr_status_t ostat_on_req_status(const md_http_request_t *req, apr_status _t status, static apr_status_t ostat_on_req_status(const md_http_request_t *req, apr_status _t status,
void *baton) void *baton)
{ {
md_ocsp_update_t *update = baton; md_ocsp_update_t *update = baton;
md_ocsp_status_t *ostat = update->ostat; md_ocsp_status_t *ostat = update->ostat;
skipping to change at line 783 skipping to change at line 760
} }
typedef struct { typedef struct {
md_ocsp_reg_t *reg; md_ocsp_reg_t *reg;
apr_array_header_t *todos; apr_array_header_t *todos;
apr_pool_t *ptemp; apr_pool_t *ptemp;
apr_time_t time; apr_time_t time;
int max_parallel; int max_parallel;
} md_ocsp_todo_ctx_t; } 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, static apr_status_t next_todo(md_http_request_t **preq, void *baton,
md_http_t *http, int in_flight) md_http_t *http, int in_flight)
{ {
md_ocsp_todo_ctx_t *ctx = baton; md_ocsp_todo_ctx_t *ctx = baton;
md_ocsp_update_t *update, **pupdate; md_ocsp_update_t *update, **pupdate;
md_ocsp_status_t *ostat; md_ocsp_status_t *ostat;
OCSP_CERTID *certid = NULL;
md_http_request_t *req = NULL; md_http_request_t *req = NULL;
apr_status_t rv = APR_ENOENT; apr_status_t rv = APR_ENOENT;
apr_table_t *headers; apr_table_t *headers;
int len;
if (in_flight < ctx->max_parallel) { if (in_flight < ctx->max_parallel) {
pupdate = apr_array_pop(ctx->todos); pupdate = apr_array_pop(ctx->todos);
if (pupdate) { if (pupdate) {
update = *pupdate; update = *pupdate;
ostat = update->ostat; ostat = update->ostat;
update->job = md_ocsp_job_make(ctx->reg, ostat->md_name, update->p); update->job = md_ocsp_job_make(ctx->reg, ostat->md_name, update->p);
md_job_load(update->job); md_job_load(update->job);
md_job_start_run(update->job, update->result, ctx->reg->store); md_job_start_run(update->job, update->result, ctx->reg->store);
if (!ostat->ocsp_req) { if (!ostat->ocsp_req) {
ostat->ocsp_req = OCSP_REQUEST_new(); rv = ocsp_req_make(&ostat->ocsp_req, ostat->certid);
if (!ostat->ocsp_req) goto cleanup; if (APR_SUCCESS != rv) 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;
} }
if (0 == ostat->req_der.len) { if (0 == ostat->req_der.len) {
len = i2d_OCSP_REQUEST(ostat->ocsp_req, (unsigned char**)&ostat- rv = ocsp_req_assign_der(&ostat->req_der, ostat->ocsp_req);
>req_der.data); if (APR_SUCCESS != rv) goto cleanup;
if (len < 0) goto cleanup;
ostat->req_der.len = (apr_size_t)len;
} }
md_result_activity_printf(update->result, "status of certid %s, " md_result_activity_printf(update->result, "status of certid %s, "
"contacting %s", ostat->hexid, ostat->resp onder_url); "contacting %s", ostat->hexid, ostat->resp onder_url);
headers = apr_table_make(ctx->ptemp, 5); headers = apr_table_make(ctx->ptemp, 5);
apr_table_set(headers, "Expect", ""); apr_table_set(headers, "Expect", "");
rv = md_http_POSTd_create(&req, http, ostat->responder_url, headers, rv = md_http_POSTd_create(&req, http, ostat->responder_url, headers,
"application/ocsp-request", &ostat->req_de r); "application/ocsp-request", &ostat->req_de r);
if (APR_SUCCESS != rv) goto cleanup; if (APR_SUCCESS != rv) goto cleanup;
md_http_set_on_status_cb(req, ostat_on_req_status, update); md_http_set_on_status_cb(req, ostat_on_req_status, update);
md_http_set_on_response_cb(req, ostat_on_resp, update); md_http_set_on_response_cb(req, ostat_on_resp, update);
rv = APR_SUCCESS; rv = APR_SUCCESS;
} }
} }
cleanup: cleanup:
*preq = (APR_SUCCESS == rv)? req : NULL; *preq = (APR_SUCCESS == rv)? req : NULL;
if (certid) OCSP_CERTID_free(certid);
return rv; return rv;
} }
static int select_updates(void *baton, const void *key, apr_ssize_t klen, const void *val) static int select_updates(void *baton, const void *key, apr_ssize_t klen, const void *val)
{ {
md_ocsp_todo_ctx_t *ctx = baton; md_ocsp_todo_ctx_t *ctx = baton;
md_ocsp_status_t *ostat = (md_ocsp_status_t *)val; md_ocsp_status_t *ostat = (md_ocsp_status_t *)val;
md_ocsp_update_t *update; md_ocsp_update_t *update;
(void)key; (void)key;
 End of changes. 22 change blocks. 
58 lines changed or deleted 61 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)