summaryrefslogtreecommitdiff
path: root/modules/ssl
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2021-04-13 11:12:00 +0000
committerStefan Eissing <icing@apache.org>2021-04-13 11:12:00 +0000
commitdb5aa786d86e1ef1105f9d9962b496130170bcf6 (patch)
tree1d083d775c397b453c13c5f5be484d1a08ab774f /modules/ssl
parent9e2ed5bb859577184b9dfba1e07ee3a55671532f (diff)
downloadhttpd-db5aa786d86e1ef1105f9d9962b496130170bcf6.tar.gz
*) core/mod_ssl/mod_md: adding OCSP response provisioning as core feature. This
allows modules to access and provide OCSP response data without being tied of each other. The data is exchanged in standard, portable formats (PEM encoded certificates and DER encoded responses), so that the actual SSL/crypto implementations used by the modules are independant of each other. Registration and retrieval happen in the context of a server (server_rec) which modules may use to decide if they are configured for this or not. The area of changes: 1. core: defines 2 functions in include/http_ssl.h, so that modules may register a certificate, together with its issuer certificate for OCSP response provisioning and ask for current response data (DER bytes) later. Also, 2 hooks are defined that allow modules to implement this OCSP provisioning. 2. mod_ssl uses the new functions, in addition to what it did already, to register its certificates this way. If no one is interested in providing OCSP, it falls back to its own (if configured) stapling implementation. 3. mod_md registers itself at the core hooks for OCSP provisioning. Depending on configuration, it will accept registrations of its own certificates only, all certficates or none. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1888723 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/ssl')
-rw-r--r--modules/ssl/ssl_util_ssl.c23
-rw-r--r--modules/ssl/ssl_util_ssl.h13
-rw-r--r--modules/ssl/ssl_util_stapling.c70
3 files changed, 87 insertions, 19 deletions
diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
index d6448957f6..df25c49925 100644
--- a/modules/ssl/ssl_util_ssl.c
+++ b/modules/ssl/ssl_util_ssl.c
@@ -578,3 +578,26 @@ cleanup:
if (in != NULL) BIO_free(in);
return rv;
}
+
+apr_status_t modssl_cert_get_pem(apr_pool_t *p,
+ X509 *cert1, X509 *cert2,
+ const char **ppem)
+{
+ apr_status_t rv = APR_ENOMEM;
+ BIO *bio;
+
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) goto cleanup;
+ if (PEM_write_bio_X509(bio, cert1) != 1) goto cleanup;
+ if (cert2 && PEM_write_bio_X509(bio, cert2) != 1) goto cleanup;
+ rv = APR_SUCCESS;
+
+cleanup:
+ if (rv != APR_SUCCESS) {
+ *ppem = NULL;
+ if (bio) BIO_free(bio);
+ }
+ else {
+ *ppem = modssl_bio_free_read(p, bio);
+ }
+ return rv;
+}
diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h
index 335d6fdde7..0f01128528 100644
--- a/modules/ssl/ssl_util_ssl.h
+++ b/modules/ssl/ssl_util_ssl.h
@@ -90,7 +90,18 @@ apr_status_t modssl_read_cert(apr_pool_t *p,
const char *cert_pem, const char *key_pem,
pem_password_cb *cb, void *ud,
X509 **pcert, EVP_PKEY **pkey);
-
+
+/* Convert a certificate (and optionally a second) into a PEM string.
+ * @param p pool for allocations
+ * @param cert1 the certificate to convert
+ * @param cert2 a second cert to add to the PEM afterwards or NULL.
+ * @param ppem the certificate(s) in PEM format, NUL-terminated.
+ * @return APR_SUCCESS if ppem is valid.
+ */
+apr_status_t modssl_cert_get_pem(apr_pool_t *p,
+ X509 *cert1, X509 *cert2,
+ const char **ppem);
+
#endif /* __SSL_UTIL_SSL_H__ */
/** @} */
diff --git a/modules/ssl/ssl_util_stapling.c b/modules/ssl/ssl_util_stapling.c
index a6ee6e8e6c..54fb4e0415 100644
--- a/modules/ssl/ssl_util_stapling.c
+++ b/modules/ssl/ssl_util_stapling.c
@@ -130,6 +130,8 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
X509 *issuer = NULL;
OCSP_CERTID *cid = NULL;
STACK_OF(OPENSSL_STRING) *aia = NULL;
+ const char *pem = NULL;
+ ap_bytes_t key;
int rv = 1; /* until further notice */
if (x == NULL)
@@ -149,7 +151,20 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
return 1;
}
- if (ssl_run_init_stapling_status(s, p, x, issuer) == OK) {
+ if (X509_digest(x, EVP_sha1(), idx, NULL) != 1) {
+ rv = 0;
+ goto cleanup;
+ }
+
+ if (modssl_cert_get_pem(ptemp, x, issuer, &pem) != APR_SUCCESS) {
+ rv = 0;
+ goto cleanup;
+ }
+
+ key.data = idx;
+ key.len = sizeof(idx);
+ if (ap_ssl_ocsp_prime(s, p, &key, pem) == APR_SUCCESS
+ || ssl_run_init_stapling_status(s, p, x, issuer) == OK) {
/* Someone's taken over or mod_ssl's own implementation is not enabled */
if (mctx->stapling_enabled != TRUE) {
SSL_CTX_set_tlsext_status_cb(mctx->ssl_ctx, stapling_cb);
@@ -163,11 +178,6 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
goto cleanup;
}
- if (X509_digest(x, EVP_sha1(), idx, NULL) != 1) {
- rv = 0;
- goto cleanup;
- }
-
cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
if (cinf) {
/*
@@ -228,14 +238,11 @@ cleanup:
return rv;
}
-static certinfo *stapling_get_certinfo(server_rec *s, X509 *x, modssl_ctx_t *mctx,
- SSL *ssl)
+static certinfo *stapling_get_certinfo(server_rec *s, UCHAR *idx, apr_size_t idx_len,
+ modssl_ctx_t *mctx, SSL *ssl)
{
certinfo *cinf;
- UCHAR idx[SHA_DIGEST_LENGTH];
- if (X509_digest(x, EVP_sha1(), idx, NULL) != 1)
- return NULL;
- cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
+ cinf = apr_hash_get(stapling_certinfo, idx, idx_len);
if (cinf && cinf->cid)
return cinf;
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01926)
@@ -765,6 +772,18 @@ static int get_and_check_cached_response(server_rec *s, modssl_ctx_t *mctx,
return 0;
}
+static void copy_ocsp_resp(const unsigned char *der, apr_size_t der_len, void *userdata)
+{
+ ap_bytes_t *resp = userdata;
+
+ resp->len = 0;
+ resp->data = der? OPENSSL_malloc(der_len) : NULL;
+ if (resp->data) {
+ memcpy(resp->data, der, der_len);
+ resp->len = der_len;
+ }
+}
+
/* Certificate Status callback. This is called when a client includes a
* certificate status request extension.
*
@@ -779,13 +798,14 @@ static int stapling_cb(SSL *ssl, void *arg)
SSLSrvConfigRec *sc = mySrvConfig(s);
SSLConnRec *sslconn = myConnConfig(conn);
modssl_ctx_t *mctx = myCtxConfig(sslconn, sc);
+ UCHAR idx[SHA_DIGEST_LENGTH];
+ ap_bytes_t key, resp;
certinfo *cinf = NULL;
OCSP_RESPONSE *rsp = NULL;
int rv;
BOOL ok = TRUE;
X509 *x;
- unsigned char *rspder = NULL;
- int rspderlen;
+ int rspderlen, provided = 0;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951)
"stapling_cb: OCSP Stapling callback called");
@@ -795,12 +815,26 @@ static int stapling_cb(SSL *ssl, void *arg)
return SSL_TLSEXT_ERR_NOACK;
}
- if (ssl_run_get_stapling_status(&rspder, &rspderlen, conn, s, x) == APR_SUCCESS) {
+ if (X509_digest(x, EVP_sha1(), idx, NULL) != 1) {
+ return SSL_TLSEXT_ERR_NOACK;
+ }
+ key.data = idx;
+ key.len = sizeof(idx);
+
+ if (ap_ssl_ocsp_get_resp(s, conn, &key, copy_ocsp_resp, &resp) == APR_SUCCESS) {
+ provided = 1;
+ }
+ else if (ssl_run_get_stapling_status(&resp.data, &rspderlen, conn, s, x) == APR_SUCCESS) {
+ resp.len = (apr_size_t)rspderlen;
+ provided = 1;
+ }
+
+ if (provided) {
/* a hook handles stapling for this certificate and determines the response */
- if (rspder == NULL || rspderlen <= 0) {
+ if (resp.data == NULL || resp.len == 0) {
return SSL_TLSEXT_ERR_NOACK;
}
- SSL_set_tlsext_status_ocsp_resp(ssl, rspder, rspderlen);
+ SSL_set_tlsext_status_ocsp_resp(ssl, resp.data, (int)resp.len);
return SSL_TLSEXT_ERR_OK;
}
@@ -810,7 +844,7 @@ static int stapling_cb(SSL *ssl, void *arg)
return SSL_TLSEXT_ERR_NOACK;
}
- if ((cinf = stapling_get_certinfo(s, x, mctx, ssl)) == NULL) {
+ if ((cinf = stapling_get_certinfo(s, idx, sizeof(idx), mctx, ssl)) == NULL) {
return SSL_TLSEXT_ERR_NOACK;
}