Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix OCSP response handling errors with Let's Encrypt #4

Merged
merged 4 commits into from Jul 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure.ac
Expand Up @@ -234,7 +234,7 @@ AS_IF([test "${APACHE2}" = "no"], [

AC_PATH_PROGS([HTTP_CLI], [curl], [no])

MODULE_CFLAGS="${LIBGNUTLS_CFLAGS} ${GNUTLS_FEAT_CFLAGS} ${MSVA_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES} ${STRICT_CFLAGS} ${COVERAGE_CFLAGS}"
MODULE_CFLAGS="${LIBGNUTLS_CFLAGS} ${GNUTLS_FEAT_CFLAGS} ${MSVA_CFLAGS} ${APR_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES} ${STRICT_CFLAGS} ${COVERAGE_CFLAGS}"
MODULE_LIBS="${LIBGNUTLS_LIBS}"

AC_PATH_PROGS([SOFTHSM], [softhsm2-util], [no])
Expand Down
85 changes: 11 additions & 74 deletions src/gnutls_ocsp.c
Expand Up @@ -183,23 +183,11 @@ static int mgs_create_ocsp_request(server_rec *s,
return ret;
}

/* issuer is set to a reference, so musn't be cleaned up */
gnutls_x509_crt_t issuer;
ret = gnutls_x509_trust_list_get_issuer(*req_data->trust, req_data->cert,
&issuer, 0);
if (ret != GNUTLS_E_SUCCESS)
{
ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
"Could not get issuer from trust list: %s (%d)",
gnutls_strerror(ret), ret);
gnutls_ocsp_req_deinit(r);
return ret;
}

/* GnuTLS doc says that the digest is "normally"
* GNUTLS_DIG_SHA1. */
ret = gnutls_ocsp_req_add_cert(r, GNUTLS_DIG_SHA256,
issuer, req_data->cert);
/* Use SHA1 for issuer name hash and issuer key hash, for
* compliance with "lightweight" OCSP profile specified in RFC
* 5019. */
ret = gnutls_ocsp_req_add_cert(r, GNUTLS_DIG_SHA1,
req_data->issuer, req_data->cert);

if (ret != GNUTLS_E_SUCCESS)
{
Expand Down Expand Up @@ -286,14 +274,6 @@ int check_ocsp_response(server_rec *s, mgs_ocsp_data_t req_data,
mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
ap_get_module_config(s->module_config, &gnutls_module);

if (req_data->trust == NULL)
{
ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
"No OCSP trust list available for server \"%s\"!",
s->server_hostname);
return GNUTLS_E_NO_CERTIFICATE_FOUND;
}

gnutls_ocsp_resp_t resp;
int ret = gnutls_ocsp_resp_init(&resp);
if (ret != GNUTLS_E_SUCCESS)
Expand Down Expand Up @@ -322,7 +302,7 @@ int check_ocsp_response(server_rec *s, mgs_ocsp_data_t req_data,
}

unsigned int verify;
ret = gnutls_ocsp_resp_verify(resp, *(req_data->trust), &verify, 0);
ret = gnutls_ocsp_resp_verify_direct(resp, req_data->issuer, &verify, 0);
if (ret != GNUTLS_E_SUCCESS)
{
ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
Expand Down Expand Up @@ -937,37 +917,6 @@ int mgs_get_ocsp_response(mgs_handle_t *ctxt,



int mgs_create_ocsp_trust_list(gnutls_x509_trust_list_t *tl,
const gnutls_x509_crt_t *chain,
const int num)
{
int added = 0;
int ret = gnutls_x509_trust_list_init(tl, num);

if (ret == GNUTLS_E_SUCCESS)
added = gnutls_x509_trust_list_add_cas(*tl, chain, num, 0);

if (added != num)
ret = GNUTLS_E_CERTIFICATE_ERROR;

/* Clean up trust list in case of error */
if (ret != GNUTLS_E_SUCCESS)
gnutls_x509_trust_list_deinit(*tl, 0);

return ret;
}



apr_status_t mgs_cleanup_trust_list(void *data)
{
gnutls_x509_trust_list_t *tl = (gnutls_x509_trust_list_t *) data;
gnutls_x509_trust_list_deinit(*tl, 0);
return APR_SUCCESS;
}



apr_uri_t * mgs_cert_get_ocsp_uri(apr_pool_t *p, gnutls_x509_crt_t cert)
{
apr_pool_t *tmp;
Expand Down Expand Up @@ -997,7 +946,11 @@ apr_uri_t * mgs_cert_get_ocsp_uri(apr_pool_t *p, gnutls_x509_crt_t cert)
ocsp_uri = apr_palloc(p, sizeof(apr_uri_t));
rv = apr_uri_parse(p, ocsp_str, ocsp_uri);
if (rv == APR_SUCCESS)
{
if (ocsp_uri->path == NULL)
ocsp_uri->path = "/";
break;
}
else
ocsp_uri = NULL;
}
Expand Down Expand Up @@ -1168,23 +1121,7 @@ static const char* configure_cert_staple(mgs_ocsp_data_t ocsp,
if (ocsp->fingerprint.data == NULL)
return "Could not read fingerprint from certificate!";

ocsp->trust = apr_palloc(pconf,
sizeof(gnutls_x509_trust_list_t));
/* Only the direct issuer may sign the OCSP response or an
* OCSP signer. */
int ret = mgs_create_ocsp_trust_list(
ocsp->trust, &(sc->certs_x509_crt_chain[idx + 1]), 1);
if (ret != GNUTLS_E_SUCCESS)
{
ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
"Could not create OCSP trust list: %s (%d)",
gnutls_strerror(ret), ret);
return "Could not build trust list for OCSP stapling!";
}
/* deinit trust list when the config pool is destroyed */
apr_pool_cleanup_register(pconf, ocsp->trust,
mgs_cleanup_trust_list,
apr_pool_cleanup_null);
ocsp->issuer = sc->certs_x509_crt_chain[idx + 1];
return NULL;
}

Expand Down
5 changes: 2 additions & 3 deletions src/gnutls_ocsp.h
Expand Up @@ -43,14 +43,13 @@
struct mgs_ocsp_data {
/** The certificate the following elements refer to. */
gnutls_x509_crt_t cert;
/** Issuer certificate, used for verifying OCSP responses. */
gnutls_x509_crt_t issuer;
/** OCSP URI extracted from the certificate. NULL if unset. */
apr_uri_t *uri;
/** OCSP response file for the certificate. NULL if unset. Takes
* precedence over uri. */
char *response_file;
/** Trust list to verify OCSP responses for stapling. Should
* usually only contain the CA that signed the certificate. */
gnutls_x509_trust_list_t *trust;
/** Certificate fingerprint, used as cache key for the OCSP
* response. */
gnutls_datum_t fingerprint;
Expand Down