[mod_gnutls] support OCSP responses in sni backends
Change-Id: I7ec08bf6e414140b53019885eb906bdfe3251a2e
This commit is contained in:
parent
e0e96ae377
commit
8c68b120da
|
@ -185,11 +185,11 @@
|
|||
|
||||
<section title="OCSP stapling">
|
||||
<textile>
|
||||
"OCSP stapling":https://en.wikipedia.org/wiki/OCSP_stapling is used to assure a client the certificate is still valid (i.e. not revoked); you can put an OCSP response into the certificate file in an "OCSP RESPNSE"-PEM block (there is probably no standard for this, juse base64-encode the DER-response you have), or specify the (DER or PEM formatted) OCSP response as separate file using "ocsp" in a "pemfile" block.
|
||||
"OCSP stapling":https://en.wikipedia.org/wiki/OCSP_stapling is used to assure a client the certificate is still valid (i.e. not revoked); you can put an OCSP response into the certificate file in an "OCSP RESPONSE"-PEM block (there is probably no standard for this, juse base64-encode the DER-response you have), or specify the (DER or PEM formatted) OCSP response as separate file using "ocsp" in a "pemfile" block.
|
||||
|
||||
Server Name Indication (SNI) should work fine, as an OCSP response is only used if it matches the certificate in use for the connection.
|
||||
|
||||
The fetch backends do NOT support OCSP stapling yet (in the future they should support the "OCSP RESPNSE"-PEM block).
|
||||
The fetch backends do support OCSP stapling if the OCSP response is appended as PEM block.
|
||||
|
||||
Lighttpd does NOT automatically reload OCSP responses; you have to restart to load new OCSP responses (a cron job is probably the right way to do it).
|
||||
|
||||
|
|
|
@ -286,3 +286,30 @@ error:
|
|||
gnutls_free(decoded.data);
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean li_gnutls_ocsp_search_datum(liServer *srv, liGnuTLSOCSP *ocsp, gnutls_datum_t const* file) {
|
||||
int r;
|
||||
gnutls_datum_t decoded = { NULL, 0 };
|
||||
gboolean result = FALSE;
|
||||
|
||||
r = gnutls_pem_base64_decode_alloc("OCSP RESPONSE", file, &decoded);
|
||||
|
||||
if (GNUTLS_E_SUCCESS <= r) {
|
||||
result = add_response(srv, ocsp, &decoded);
|
||||
if (!result) {
|
||||
ERROR(srv, "%s", "Failed loading OCSP response from PEM block");
|
||||
goto error;
|
||||
}
|
||||
} else if (GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR == r) {
|
||||
/* ignore GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR */
|
||||
} else {
|
||||
ERROR(srv, "gnutls_pem_base64_decode_alloc failed to decode OCSP RESPONSE from PEM block (%s): %s",
|
||||
gnutls_strerror_name(r), gnutls_strerror(r));
|
||||
/* continue anyway */
|
||||
}
|
||||
result = TRUE;
|
||||
|
||||
error:
|
||||
gnutls_free(decoded.data);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -22,4 +22,9 @@ LI_API gboolean li_gnutls_ocsp_add(liServer *srv, liGnuTLSOCSP *ocsp, const char
|
|||
*/
|
||||
LI_API gboolean li_gnutls_ocsp_search(liServer *srv, liGnuTLSOCSP *ocsp, const char* filename);
|
||||
|
||||
/* search in PEM datum for a OCSP RESPONSE block and add it if there is one;
|
||||
* returns only FALSE if a block was found which COULDN'T be loaded
|
||||
*/
|
||||
LI_API gboolean li_gnutls_ocsp_search_datum(liServer *srv, liGnuTLSOCSP *ocsp, gnutls_datum_t const* file);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -61,6 +61,8 @@ struct mod_connection_ctx {
|
|||
struct mod_context {
|
||||
gint refcount;
|
||||
|
||||
liServer *srv;
|
||||
|
||||
liSSLSessionDB *session_db;
|
||||
|
||||
gnutls_certificate_credentials_t server_cert;
|
||||
|
@ -89,6 +91,12 @@ struct fetch_cert_backend_lookup {
|
|||
liFetchEntry *entry;
|
||||
mod_context *ctx;
|
||||
};
|
||||
|
||||
typedef struct sni_cert_data sni_cert_data;
|
||||
struct sni_cert_data {
|
||||
gnutls_certificate_credentials_t creds;
|
||||
liGnuTLSOCSP* ocsp;
|
||||
};
|
||||
#endif
|
||||
|
||||
static void mod_gnutls_context_release(mod_context *ctx);
|
||||
|
@ -116,8 +124,10 @@ static int pin_callback(void *user, int attempt, const char *token_url, const ch
|
|||
#endif /* defined(HAVE_PIN) */
|
||||
|
||||
#ifdef USE_SNI
|
||||
static gnutls_certificate_credentials_t creds_from_gstring(mod_context *ctx, GString *str) {
|
||||
static sni_cert_data* creds_from_gstring(mod_context *ctx, GString *str) {
|
||||
sni_cert_data* data = NULL;
|
||||
gnutls_certificate_credentials_t creds = NULL;
|
||||
liGnuTLSOCSP* ocsp = NULL;
|
||||
gnutls_datum_t pemfile;
|
||||
int r;
|
||||
|
||||
|
@ -133,15 +143,26 @@ static gnutls_certificate_credentials_t creds_from_gstring(mod_context *ctx, GSt
|
|||
#endif
|
||||
|
||||
if (GNUTLS_E_SUCCESS > (r = gnutls_certificate_set_x509_key_mem(creds, &pemfile, &pemfile, GNUTLS_X509_FMT_PEM))) {
|
||||
goto error_free_creds;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gnutls_certificate_set_dh_params(creds, ctx->dh_params);
|
||||
|
||||
return creds;
|
||||
ocsp = li_gnutls_ocsp_new();
|
||||
if (!li_gnutls_ocsp_search_datum(ctx->srv, ocsp, &pemfile)) {
|
||||
goto error;
|
||||
}
|
||||
li_gnutls_ocsp_use(ocsp, creds);
|
||||
|
||||
error_free_creds:
|
||||
gnutls_certificate_free_credentials(creds);
|
||||
data = g_slice_new0(sni_cert_data);
|
||||
data->creds = creds;
|
||||
data->ocsp = ocsp;
|
||||
|
||||
return data;
|
||||
|
||||
error:
|
||||
if (NULL != creds) gnutls_certificate_free_credentials(creds);
|
||||
if (NULL != ocsp) li_gnutls_ocsp_free(ocsp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -179,10 +200,14 @@ static void fetch_cert_refresh(liFetchDatabase* db, gpointer data, liFetchEntry
|
|||
li_fetch_entry_refresh_skip(new_entry);
|
||||
}
|
||||
static void fetch_cert_free_entry(gpointer data, liFetchEntry *entry) {
|
||||
gnutls_certificate_credentials_t creds = entry->data;
|
||||
sni_cert_data* sni_data = entry->data;
|
||||
UNUSED(data);
|
||||
|
||||
if (NULL != creds) gnutls_certificate_free_credentials(creds);
|
||||
if (NULL != sni_data) {
|
||||
if (NULL != sni_data->creds) gnutls_certificate_free_credentials(sni_data->creds);
|
||||
if (NULL != sni_data->ocsp) li_gnutls_ocsp_free(sni_data->ocsp);
|
||||
g_slice_free(sni_cert_data, sni_data);
|
||||
}
|
||||
li_fetch_entry_release((liFetchEntry*) entry->backend_data);
|
||||
}
|
||||
static void fetch_cert_free_db(gpointer data) {
|
||||
|
@ -288,6 +313,8 @@ static mod_context *mod_gnutls_context_new(liServer *srv) {
|
|||
}
|
||||
#endif
|
||||
|
||||
ctx->srv = srv;
|
||||
|
||||
ctx->ocsp = li_gnutls_ocsp_new();
|
||||
|
||||
ctx->refcount = 1;
|
||||
|
@ -490,9 +517,9 @@ static void sni_job_cb(liJob *job) {
|
|||
|
||||
conctx->sni_entry = li_fetch_get(conctx->ctx->sni_db, conctx->sni_server_name, conctx->sni_jobref, &conctx->sni_db_wait);
|
||||
if (conctx->sni_entry != NULL) {
|
||||
gnutls_certificate_credentials_t creds = conctx->sni_entry->data;
|
||||
if (NULL != creds) {
|
||||
gnutls_credentials_set(conctx->session, GNUTLS_CRD_CERTIFICATE, creds);
|
||||
sni_cert_data* data = conctx->sni_entry->data;
|
||||
if (NULL != data) {
|
||||
gnutls_credentials_set(conctx->session, GNUTLS_CRD_CERTIFICATE, data->creds);
|
||||
} else if (NULL != conctx->ctx->sni_fallback_cert) {
|
||||
gnutls_credentials_set(conctx->session, GNUTLS_CRD_CERTIFICATE, conctx->ctx->sni_fallback_cert);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue