summaryrefslogtreecommitdiff
path: root/debian/patches
diff options
context:
space:
mode:
authorStefan Fritsch <sf@sfritsch.de>2014-11-18 15:16:04 +0100
committerStefan Fritsch <sf@sfritsch.de>2014-11-18 15:16:04 +0100
commit8d29fbc6663c7dc55d6dbe36d84950a71ea99822 (patch)
tree1c3906a8fc080b9516f3cbeadf21d3a1aa0844e4 /debian/patches
parent1cc103cf25f223071a6be87dbe4a87c3d6a3e7e0 (diff)
downloadapache2-8d29fbc6663c7dc55d6dbe36d84950a71ea99822.tar.gz
mod_ssl: Avoid crashes due to stapling callback
Diffstat (limited to 'debian/patches')
-rw-r--r--debian/patches/mod_ssl-oscp_stapling_crash.diff298
-rw-r--r--debian/patches/series1
2 files changed, 299 insertions, 0 deletions
diff --git a/debian/patches/mod_ssl-oscp_stapling_crash.diff b/debian/patches/mod_ssl-oscp_stapling_crash.diff
new file mode 100644
index 00000000..c2de4eb6
--- /dev/null
+++ b/debian/patches/mod_ssl-oscp_stapling_crash.diff
@@ -0,0 +1,298 @@
+# http://svn.apache.org/viewvc?view=revision&revision=1634529
+#
+# Avoid registering a cleanup function with openssl for the OCSP
+# stapling information. During startup or graceful restart mod_ssl
+# may be reloaded without libssl being reloaded. In this case
+# libssl may still use the cleanup that now points to invalid memory,
+# causing a crash.
+#
+# =================================
+# commit 1046d0c01b67d50af9d4570e975ba418dff3fa96
+# Author: Jim Jagielski <jim@apache.org>
+# Date: Mon Oct 27 12:50:05 2014 +0000
+#
+# Merge r1629372, r1629485, r1629519 from trunk:
+#
+# Move OCSP stapling information from a per-certificate store
+# (ex_data attached to an X509 *) to a per-server hash which is
+# allocated from the pconf pool. Fixes PR 54357, PR 56919 and
+# a leak with the certinfo_free cleanup function (missing
+# OCSP_CERTID_free).
+#
+# * modules/ssl/ssl_util_stapling.c: drop certinfo_free, and add
+# ssl_stapling_certid_free (used with apr_pool_cleanup_register).
+# Switch to a stapling_certinfo hash which is keyed by the SHA-1
+# digest of the certificate's DER encoding, rework ssl_stapling_init_cert
+# to only store info once per certificate (allocated from the pconf
+# to the extent possible) and extend the logging.
+#
+# * modules/ssl/ssl_private.h: adjust prototype for
+# ssl_stapling_init_cert, replace ssl_stapling_ex_init with
+# ssl_stapling_certinfo_hash_init
+#
+# * modules/ssl/ssl_engine_init.c: adjust ssl_stapling_* calls
+#
+# Based on initial work by Alex Bligh <alex alex.org.uk>
+#
+# Follow up to r1629372: ensure compatibily with OpenSSL < 1.0 (sk_OPENSSL_STRING_value).
+#
+# Follow up to r1629372 and r1629485: ensure compatibily with OpenSSL < 1.0 (sk_OPENSSL_STRING_[num|value|pop] macros).
+# Submitted by: kbrand, ylavic, ylavic
+# Reviewed/backported by: jim
+--- apache2.orig/modules/ssl/ssl_util_stapling.c
++++ apache2/modules/ssl/ssl_util_stapling.c
+@@ -43,36 +43,32 @@
+
+ #define MAX_STAPLING_DER 10240
+
+-/* Cached info stored in certificate ex_info. */
++/* Cached info stored in the global stapling_certinfo hash. */
+ typedef struct {
+- /* Index in session cache SHA1 hash of certificate */
+- UCHAR idx[20];
+- /* Certificate ID for OCSP requests or NULL if ID cannot be determined */
++ /* Index in session cache (SHA-1 digest of DER encoded certificate) */
++ UCHAR idx[SHA_DIGEST_LENGTH];
++ /* Certificate ID for OCSP request */
+ OCSP_CERTID *cid;
+- /* Responder details */
++ /* URI of the OCSP responder */
+ char *uri;
+ } certinfo;
+
+-static void certinfo_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+- int idx, long argl, void *argp)
++static apr_status_t ssl_stapling_certid_free(void *data)
+ {
+- certinfo *cinf = ptr;
++ OCSP_CERTID *cid = data;
+
+- if (!cinf)
+- return;
+- if (cinf->uri)
+- OPENSSL_free(cinf->uri);
+- OPENSSL_free(cinf);
++ if (cid) {
++ OCSP_CERTID_free(cid);
++ }
++
++ return APR_SUCCESS;
+ }
+
+-static int stapling_ex_idx = -1;
++static apr_hash_t *stapling_certinfo;
+
+-void ssl_stapling_ex_init(void)
++void ssl_stapling_certinfo_hash_init(apr_pool_t *p)
+ {
+- if (stapling_ex_idx != -1)
+- return;
+- stapling_ex_idx = X509_get_ex_new_index(0, "X509 cached OCSP info", 0, 0,
+- certinfo_free);
++ stapling_certinfo = apr_hash_make(p);
+ }
+
+ static X509 *stapling_get_issuer(modssl_ctx_t *mctx, X509 *x)
+@@ -106,70 +102,96 @@ static X509 *stapling_get_issuer(modssl_
+
+ }
+
+-int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x)
++int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
++ modssl_ctx_t *mctx, X509 *x)
+ {
+- certinfo *cinf;
++ UCHAR idx[SHA_DIGEST_LENGTH];
++ certinfo *cinf = NULL;
+ X509 *issuer = NULL;
++ OCSP_CERTID *cid = NULL;
+ STACK_OF(OPENSSL_STRING) *aia = NULL;
+
+- if (x == NULL)
++ if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1))
+ return 0;
+- cinf = X509_get_ex_data(x, stapling_ex_idx);
++
++ cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
+ if (cinf) {
+- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02215)
+- "ssl_stapling_init_cert: certificate already initialized!");
+- return 0;
+- }
+- cinf = OPENSSL_malloc(sizeof(certinfo));
+- if (!cinf) {
+- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02216)
+- "ssl_stapling_init_cert: error allocating memory!");
+- return 0;
++ /*
++ * We already parsed the certificate, and no OCSP URI was found.
++ * The certificate might be used for multiple vhosts, though,
++ * so we check for a ForceURL for this vhost.
++ */
++ if (!cinf->uri && !mctx->stapling_force_url) {
++ ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x,
++ APLOGNO(02814) "ssl_stapling_init_cert: no OCSP URI "
++ "in certificate and no SSLStaplingForceURL "
++ "configured for server %s", mctx->sc->vhost_id);
++ return 0;
++ }
++ return 1;
+ }
+- cinf->cid = NULL;
+- cinf->uri = NULL;
+- X509_set_ex_data(x, stapling_ex_idx, cinf);
+-
+- issuer = stapling_get_issuer(mctx, x);
+-
+- if (issuer == NULL) {
+- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02217)
+- "ssl_stapling_init_cert: Can't retrieve issuer certificate!");
++
++ 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;
+ }
+
+- cinf->cid = OCSP_cert_to_id(NULL, x, issuer);
++ cid = OCSP_cert_to_id(NULL, x, issuer);
+ X509_free(issuer);
+- if (!cinf->cid)
++ if (!cid) {
++ ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x, APLOGNO(02815)
++ "ssl_stapling_init_cert: can't create CertID "
++ "for OCSP request");
+ return 0;
+- X509_digest(x, EVP_sha1(), cinf->idx, NULL);
++ }
+
+ aia = X509_get1_ocsp(x);
+- if (aia) {
+- cinf->uri = sk_OPENSSL_STRING_pop(aia);
+- X509_email_free(aia);
+- }
+- if (!cinf->uri && !mctx->stapling_force_url) {
+- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02218)
+- "ssl_stapling_init_cert: no responder URL");
++ if (!aia && !mctx->stapling_force_url) {
++ OCSP_CERTID_free(cid);
++ ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x,
++ APLOGNO(02218) "ssl_stapling_init_cert: no OCSP URI "
++ "in certificate and no SSLStaplingForceURL set");
+ return 0;
+ }
++
++ /* At this point, we have determined that there's something to store */
++ cinf = apr_pcalloc(p, sizeof(certinfo));
++ memcpy (cinf->idx, idx, sizeof(idx));
++ cinf->cid = cid;
++ /* make sure cid is also freed at pool cleanup */
++ apr_pool_cleanup_register(p, cid, ssl_stapling_certid_free,
++ apr_pool_cleanup_null);
++ if (aia) {
++ /* allocate uri from the pconf pool */
++ cinf->uri = apr_pstrdup(p, sk_OPENSSL_STRING_value(aia, 0));
++ X509_email_free(aia);
++ }
++
++ ssl_log_xerror(SSLLOG_MARK, APLOG_TRACE1, 0, ptemp, s, x,
++ "ssl_stapling_init_cert: storing certinfo for server %s",
++ mctx->sc->vhost_id);
++
++ apr_hash_set(stapling_certinfo, cinf->idx, sizeof(cinf->idx), cinf);
++
+ return 1;
+ }
+
+-static certinfo *stapling_get_cert_info(server_rec *s, modssl_ctx_t *mctx,
++static certinfo *stapling_get_certinfo(server_rec *s, modssl_ctx_t *mctx,
+ SSL *ssl)
+ {
+ certinfo *cinf;
+ X509 *x;
++ UCHAR idx[SHA_DIGEST_LENGTH];
+ x = SSL_get_certificate(ssl);
+- if (x == NULL)
++ if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1))
+ return NULL;
+- cinf = X509_get_ex_data(x, stapling_ex_idx);
++ cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
+ if (cinf && cinf->cid)
+ return cinf;
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01926)
+- "stapling_get_cert_info: stapling not supported for certificate");
++ "stapling_get_certinfo: stapling not supported for certificate");
+ return NULL;
+ }
+
+@@ -585,7 +607,7 @@ static int stapling_cb(SSL *ssl, void *a
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951)
+ "stapling_cb: OCSP Stapling callback called");
+
+- cinf = stapling_get_cert_info(s, mctx, ssl);
++ cinf = stapling_get_certinfo(s, mctx, ssl);
+ if (cinf == NULL) {
+ return SSL_TLSEXT_ERR_NOACK;
+ }
+--- apache2.orig/modules/ssl/ssl_private.h
++++ apache2/modules/ssl/ssl_private.h
+@@ -151,6 +151,13 @@
+ /* OCSP stapling */
+ #if !defined(OPENSSL_NO_OCSP) && defined(SSL_CTX_set_tlsext_status_cb)
+ #define HAVE_OCSP_STAPLING
++/* backward compatibility with OpenSSL < 1.0 */
++#ifndef sk_OPENSSL_STRING_num
++#define sk_OPENSSL_STRING_num sk_num
++#endif
++#ifndef sk_OPENSSL_STRING_value
++#define sk_OPENSSL_STRING_value sk_value
++#endif
+ #ifndef sk_OPENSSL_STRING_pop
+ #define sk_OPENSSL_STRING_pop sk_pop
+ #endif
+@@ -812,10 +819,11 @@ const char *ssl_cmd_SSLStaplingErrorCach
+ const char *ssl_cmd_SSLStaplingReturnResponderErrors(cmd_parms *, void *, int);
+ const char *ssl_cmd_SSLStaplingFakeTryLater(cmd_parms *, void *, int);
+ const char *ssl_cmd_SSLStaplingResponderTimeout(cmd_parms *, void *, const char *);
+-const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *, void *, const char *);
++const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *, void *, const char *);
+ apr_status_t modssl_init_stapling(server_rec *, apr_pool_t *, apr_pool_t *, modssl_ctx_t *);
+-void ssl_stapling_ex_init(void);
+-int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x);
++void ssl_stapling_certinfo_hash_init(apr_pool_t *);
++int ssl_stapling_init_cert(server_rec *, apr_pool_t *, apr_pool_t *,
++ modssl_ctx_t *, X509 *);
+ #endif
+ #ifdef HAVE_SRP
+ int ssl_callback_SRPServerParams(SSL *, int *, void *);
+--- apache2.orig/modules/ssl/ssl_engine_init.c
++++ apache2/modules/ssl/ssl_engine_init.c
+@@ -272,7 +272,7 @@ apr_status_t ssl_init_Module(apr_pool_t
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ #ifdef HAVE_OCSP_STAPLING
+- ssl_stapling_ex_init();
++ ssl_stapling_certinfo_hash_init(p);
+ #endif
+
+ /*
+@@ -1067,7 +1067,7 @@ static apr_status_t ssl_init_server_cert
+ * later, we defer to the code in ssl_init_server_ctx.
+ */
+ if ((mctx->stapling_enabled == TRUE) &&
+- !ssl_stapling_init_cert(s, mctx, cert)) {
++ !ssl_stapling_init_cert(s, p, ptemp, mctx, cert)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02567)
+ "Unable to configure certificate %s for stapling",
+ key_id);
+@@ -1425,7 +1425,8 @@ static apr_status_t ssl_init_server_ctx(
+ SSL_CERT_SET_FIRST);
+ while (ret) {
+ cert = SSL_CTX_get0_certificate(sc->server->ssl_ctx);
+- if (!cert || !ssl_stapling_init_cert(s, sc->server, cert)) {
++ if (!cert || !ssl_stapling_init_cert(s, p, ptemp, sc->server,
++ cert)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02604)
+ "Unable to configure certificate %s:%d "
+ "for stapling", sc->vhost_id, i);
diff --git a/debian/patches/series b/debian/patches/series
index eaab7ca6..3be72f8c 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -9,3 +9,4 @@ pull_upstream_2.4.x_branch.patch
CVE-2014-3583_mod_proxy_fcgi.diff
mpm_event_use_after_free.diff
mod_ssl_memleak.diff
+mod_ssl-oscp_stapling_crash.diff