1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-08 15:02:10 +03:00

*) mod_ssl/mod_md:

Adding 2 new hooks for init/get of OCSP stapling status information when
     other modules want to provide those. Falls back to own implementation with
     same behaviour as before.
 


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1862384 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stefan Eissing
2019-07-01 14:22:04 +00:00
parent f9fb4c48b1
commit 360986b191
4 changed files with 114 additions and 27 deletions

View File

@@ -4,6 +4,9 @@ Changes with Apache 2.5.1
*) mod_ssl/mod_md: reversing dependency by letting mod_ssl offer hooks for *) mod_ssl/mod_md: reversing dependency by letting mod_ssl offer hooks for
adding certificates and keys to a virtual host. An additional hook allows adding certificates and keys to a virtual host. An additional hook allows
answering special TLS connections as used in ACME challenges. answering special TLS connections as used in ACME challenges.
Adding 2 new hooks for init/get of OCSP stapling status information when
other modules want to provide those. Falls back to own implementation with
same behaviour as before.
[Stefan Eissing] [Stefan Eissing]
*) mod_md: bringing over v2.0.6 from github. *) mod_md: bringing over v2.0.6 from github.

View File

@@ -121,10 +121,41 @@ APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, add_fallback_cert_files,
/** On TLS connections that do not relate to a configured virtual host, /** On TLS connections that do not relate to a configured virtual host,
* allow other modules to provide a X509 certificate and EVP_PKEY to * allow other modules to provide a X509 certificate and EVP_PKEY to
* be used on the connection. This first hook which does not * be used on the connection. This first hook which does not
* return DECLINDED will determine the outcome. */ * return DECLINED will determine the outcome. */
APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, answer_challenge, APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, answer_challenge,
(conn_rec *c, const char *server_name, (conn_rec *c, const char *server_name,
void **pX509, void **pEVP_PKEY)) void **pX509, void **pEVP_PKEY))
/** During post_config phase, ask around if someone wants to provide
* OCSP stapling status information for the given cert (with the also
* provided issuer certificate). The first hook which does not
* return DECLINED promises to take responsibility (and respond
* in later calls via hook ssl_get_stapling_status).
* If no hook takes over, mod_ssl's own stapling implementation will
* be applied (if configured).
*/
APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, init_stapling_status,
(server_rec *s, apr_pool_t *p,
void *x509cert, void *x509issuer))
/** Anyone answering positive to ssl_init_stapling_status for a
* certificate, needs to register here and supply the actual OCSP stapling
* status data (OCSP_RESP) for a new connection.
* The data is returned in DER encoded bytes via pder and pderlen. The
* returned pointer may be NULL, which indicates that data is (currently)
* unavailable.
* If DER data is returned, it MUST come from a response with
* status OCSP_RESPONSE_STATUS_SUCCESSFUL and V_OCSP_CERTSTATUS_GOOD
* or V_OCSP_CERTSTATUS_REVOKED, not V_OCSP_CERTSTATUS_UNKNOWN. This means
* errors in OCSP retrieval are to be handled/logged by the hook and
* are not done by mod_ssl.
* Any DER bytes returned MUST be allocated via malloc() and ownership
* passes to mod_ssl. Meaning, the hook must return a malloced copy of
* the data it has. mod_ssl (or OpenSSL) will free it.
*/
APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, get_stapling_status,
(unsigned char **pder, int *pderlen,
conn_rec *c, server_rec *s, void *x509cert))
#endif /* SSL_CERT_HOOKS */ #endif /* SSL_CERT_HOOKS */

View File

@@ -59,7 +59,6 @@ APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, answer_challenge,
DECLINED, DECLINED) DECLINED, DECLINED)
/* _________________________________________________________________ /* _________________________________________________________________
** **
** Module Initialization ** Module Initialization
@@ -1423,8 +1422,7 @@ static apr_status_t ssl_init_server_certs(server_rec *s,
* loaded via SSLOpenSSLConfCmd Certificate), so for 1.0.2 and * loaded via SSLOpenSSLConfCmd Certificate), so for 1.0.2 and
* later, we defer to the code in ssl_init_server_ctx. * later, we defer to the code in ssl_init_server_ctx.
*/ */
if ((mctx->stapling_enabled == TRUE) && if (!ssl_stapling_init_cert(s, p, ptemp, mctx, cert)) {
!ssl_stapling_init_cert(s, p, ptemp, mctx, cert)) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02567) ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02567)
"Unable to configure certificate %s for stapling", "Unable to configure certificate %s for stapling",
key_id); key_id);
@@ -1833,8 +1831,8 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
pks->service_unavailable = 1; pks->service_unavailable = 1;
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10085) ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10085)
"Init: %s will respond with '503 Service Unavailable' for now. This " "Init: %s will respond with '503 Service Unavailable' for now. There "
"has no SSL certificate configured and no other module contributed any.", "are no SSL certificates configured and no other module contributed any.",
ssl_util_vhostid(p, s)); ssl_util_vhostid(p, s));
} }
@@ -1887,7 +1885,7 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
* (late) point makes sure that we catch both certificates loaded * (late) point makes sure that we catch both certificates loaded
* via SSLCertificateFile and SSLOpenSSLConfCmd Certificate. * via SSLCertificateFile and SSLOpenSSLConfCmd Certificate.
*/ */
if (sc->server->stapling_enabled == TRUE) { do {
X509 *cert; X509 *cert;
int i = 0; int i = 0;
int ret = SSL_CTX_set_current_cert(sc->server->ssl_ctx, int ret = SSL_CTX_set_current_cert(sc->server->ssl_ctx,
@@ -1904,7 +1902,7 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
SSL_CERT_SET_NEXT); SSL_CERT_SET_NEXT);
i++; i++;
} }
} } while(0);
#endif #endif
#ifdef HAVE_TLS_SESSION_TICKETS #ifdef HAVE_TLS_SESSION_TICKETS

View File

@@ -31,12 +31,28 @@
#include "ssl_private.h" #include "ssl_private.h"
#include "ap_mpm.h" #include "ap_mpm.h"
#include "apr_thread_mutex.h" #include "apr_thread_mutex.h"
#include "mod_ssl.h"
APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, init_stapling_status,
(server_rec *s, apr_pool_t *p,
void *x509cert, void *x509issuer),
(s, p, x509cert, x509issuer),
DECLINED, DECLINED)
APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, get_stapling_status,
(unsigned char **pder, int *pderlen,
conn_rec *c, server_rec *s, void *x509cert),
(pder, pderlen, c, s, x509cert),
DECLINED, DECLINED)
#ifdef HAVE_OCSP_STAPLING #ifdef HAVE_OCSP_STAPLING
static int stapling_cache_mutex_on(server_rec *s); static int stapling_cache_mutex_on(server_rec *s);
static int stapling_cache_mutex_off(server_rec *s); static int stapling_cache_mutex_off(server_rec *s);
static int stapling_cb(SSL *ssl, void *arg);
/** /**
* Maxiumum OCSP stapling response size. This should be the response for a * Maxiumum OCSP stapling response size. This should be the response for a
* single certificate and will typically include the responder certificate chain * single certificate and will typically include the responder certificate chain
@@ -119,7 +135,38 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
OCSP_CERTID *cid = NULL; OCSP_CERTID *cid = NULL;
STACK_OF(OPENSSL_STRING) *aia = NULL; STACK_OF(OPENSSL_STRING) *aia = NULL;
if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1)) if (x == NULL)
return 0;
if (!(issuer = stapling_get_issuer(mctx, x))) {
/* In Apache pre 2.4.40, we use to come here only when mod_ssl stapling
* was enabled. With the new hooks, we give other modules the chance
* to provide stapling status. However, we do not want to log ssl errors
* where we did not do so in the past. */
if (mctx->stapling_enabled == TRUE) {
ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x, APLOGNO(02217)
"ssl_stapling_init_cert: can't retrieve issuer "
"certificate!");
return 0;
}
return 1;
}
if (ssl_run_init_stapling_status(s, p, x, issuer) == APR_SUCCESS) {
/* 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);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO() "OCSP stapling added via hook");
}
return 1;
}
if (mctx->stapling_enabled != TRUE) {
/* mod_ssl's own implementation is not enabled */
return 1;
}
if (X509_digest(x, EVP_sha1(), idx, NULL) != 1)
return 0; return 0;
cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx)); cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
@@ -139,13 +186,6 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
return 1; return 1;
} }
if (!(issuer = stapling_get_issuer(mctx, x))) {
ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x, APLOGNO(02217)
"ssl_stapling_init_cert: can't retrieve issuer "
"certificate!");
return 0;
}
cid = OCSP_cert_to_id(NULL, x, issuer); cid = OCSP_cert_to_id(NULL, x, issuer);
X509_free(issuer); X509_free(issuer);
if (!cid) { if (!cid) {
@@ -182,18 +222,16 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
mctx->sc->vhost_id); mctx->sc->vhost_id);
apr_hash_set(stapling_certinfo, cinf->idx, sizeof(cinf->idx), cinf); apr_hash_set(stapling_certinfo, cinf->idx, sizeof(cinf->idx), cinf);
return 1; return 1;
} }
static certinfo *stapling_get_certinfo(server_rec *s, modssl_ctx_t *mctx, static certinfo *stapling_get_certinfo(server_rec *s, X509 *x, modssl_ctx_t *mctx,
SSL *ssl) SSL *ssl)
{ {
certinfo *cinf; certinfo *cinf;
X509 *x;
UCHAR idx[SHA_DIGEST_LENGTH]; UCHAR idx[SHA_DIGEST_LENGTH];
x = SSL_get_certificate(ssl); if (X509_digest(x, EVP_sha1(), idx, NULL) != 1)
if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1))
return NULL; return NULL;
cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx)); cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
if (cinf && cinf->cid) if (cinf && cinf->cid)
@@ -751,18 +789,34 @@ static int stapling_cb(SSL *ssl, void *arg)
OCSP_RESPONSE *rsp = NULL; OCSP_RESPONSE *rsp = NULL;
int rv; int rv;
BOOL ok = TRUE; BOOL ok = TRUE;
X509 *x;
unsigned char *rspder = NULL;
int rspderlen;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951)
"stapling_cb: OCSP Stapling callback called");
x = SSL_get_certificate(ssl);
if (x == NULL) {
return SSL_TLSEXT_ERR_NOACK;
}
if (ssl_run_get_stapling_status(&rspder, &rspderlen, conn, s, x) == APR_SUCCESS) {
/* a hook handles stapling for this certicate and determines the response */
if (rspder == NULL || rspderlen <= 0) {
return SSL_TLSEXT_ERR_NOACK;
}
SSL_set_tlsext_status_ocsp_resp(ssl, rspder, rspderlen);
return SSL_TLSEXT_ERR_OK;
}
if (sc->server->stapling_enabled != TRUE) { if (sc->server->stapling_enabled != TRUE) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01950) ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01950)
"stapling_cb: OCSP Stapling disabled"); "stapling_cb: OCSP Stapling disabled");
return SSL_TLSEXT_ERR_NOACK; return SSL_TLSEXT_ERR_NOACK;
} }
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951) if ((cinf = stapling_get_certinfo(s, x, mctx, ssl)) == NULL) {
"stapling_cb: OCSP Stapling callback called");
cinf = stapling_get_certinfo(s, mctx, ssl);
if (cinf == NULL) {
return SSL_TLSEXT_ERR_NOACK; return SSL_TLSEXT_ERR_NOACK;
} }
@@ -865,9 +919,10 @@ apr_status_t modssl_init_stapling(server_rec *s, apr_pool_t *p,
if (mctx->stapling_responder_timeout == UNSET) { if (mctx->stapling_responder_timeout == UNSET) {
mctx->stapling_responder_timeout = 10 * APR_USEC_PER_SEC; mctx->stapling_responder_timeout = 10 * APR_USEC_PER_SEC;
} }
SSL_CTX_set_tlsext_status_cb(ctx, stapling_cb); SSL_CTX_set_tlsext_status_cb(ctx, stapling_cb);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01960) "OCSP stapling initialized"); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01960) "OCSP stapling initialized");
return APR_SUCCESS; return APR_SUCCESS;
} }