Bug#733564: pu: apache2 with ECDHE support
I have just uploaded apache2_2.2.22-13+deb7u2:
apache2 (2.2.22-13+deb7u2) wheezy; urgency=medium
* Backport support for SSL ECC keys and ECDH ciphers.
Bump build-dependency for libssl-dev to 1.0.1e-2+deb7u8 to get the
compatibility fix for older Safari browsers. Apache2 will still
run with older libssl-1.0.0 but without the compatibility fix.
In case of problems, see README.Debian.
* CVE-2013-6438: mod_dav: Fix potential denial of service from
specifically crafted DAV WRITE requests.
* mod_log_config: Fix a bug that cookies whose values contain '=' would
only be logged partially. This is related to CVE-2014-0098, but Apache
2.2.22 is not vulnerable to this issue.
* mod_proxy: Fix crashes under high load with threaded mpms.
https://issues.apache.org/bugzilla/show_bug.cgi?id=50335
-- Stefan Fritsch <sf@debian.org> Sun, 25 May 2014 17:35:34 +0200
Debdiff is attached. Diffstat:
NEWS | 9
README.Debian | 12 +
changelog | 22 +
control | 2
patches/SSL-ECC.patch | 332 ++++++++++++++++++++++++++++++
patches/cookie-logging-CVE-2014-0098.diff | 81 +++++++
patches/mod_dav-CVE-2013-6438.patch | 34 +++
patches/mod_proxy-crash-PR_50335.patch | 46 ++++
patches/series | 4
9 files changed, 541 insertions(+), 1 deletion(-)
Cheers,
Stefan
diff -Nru apache2-2.2.22/debian/changelog apache2-2.2.22/debian/changelog
--- apache2-2.2.22/debian/changelog 2014-01-31 19:54:27.000000000 +0100
+++ apache2-2.2.22/debian/changelog 2014-05-25 17:35:34.000000000 +0200
@@ -1,3 +1,25 @@
+apache2 (2.2.22-13+deb7u2) wheezy; urgency=medium
+
+ * Backport support for SSL ECC keys and ECDH ciphers.
+
+ Bump build-dependency for libssl-dev to 1.0.1e-2+deb7u8 to get the
+ compatibility fix for older Safari browsers. Apache2 will still
+ run with older libssl-1.0.0 but without the compatibility fix.
+
+ In case of problems, see README.Debian.
+
+ * CVE-2013-6438: mod_dav: Fix potential denial of service from
+ specifically crafted DAV WRITE requests.
+
+ * mod_log_config: Fix a bug that cookies whose values contain '=' would
+ only be logged partially. This is related to CVE-2014-0098, but Apache
+ 2.2.22 is not vulnerable to this issue.
+
+ * mod_proxy: Fix crashes under high load with threaded mpms.
+ https://issues.apache.org/bugzilla/show_bug.cgi?id=50335
+
+ -- Stefan Fritsch <sf@debian.org> Sun, 25 May 2014 17:35:34 +0200
+
apache2 (2.2.22-13+deb7u1) wheezy; urgency=medium
Low impact security fixes:
diff -Nru apache2-2.2.22/debian/control apache2-2.2.22/debian/control
--- apache2-2.2.22/debian/control 2014-01-31 19:35:41.000000000 +0100
+++ apache2-2.2.22/debian/control 2014-05-25 17:34:39.000000000 +0200
@@ -3,7 +3,7 @@
Priority: optional
Maintainer: Debian Apache Maintainers <debian-apache@lists.debian.org>
Uploaders: Stefan Fritsch <sf@debian.org>, Steinar H. Gunderson <sesse@debian.org>, Arno Töll <arno@debian.org>
-Build-Depends: debhelper (>= 8.9.7~), lsb-release, libaprutil1-dev (>= 1.3.4), libapr1-dev, openssl, libpcre3-dev, mawk, zlib1g-dev, libssl-dev (>= 0.9.8m), sharutils, libcap-dev [linux-any], autoconf, autotools-dev
+Build-Depends: debhelper (>= 8.9.7~), lsb-release, libaprutil1-dev (>= 1.3.4), libapr1-dev, openssl, libpcre3-dev, mawk, zlib1g-dev, libssl-dev (>= 1.0.1e-2+deb7u8), sharutils, libcap-dev [linux-any], autoconf, autotools-dev
Build-Conflicts: autoconf2.13
Standards-Version: 3.9.3
Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-apache/apache2.git
diff -Nru apache2-2.2.22/debian/NEWS apache2-2.2.22/debian/NEWS
--- apache2-2.2.22/debian/NEWS 2014-01-26 13:13:23.000000000 +0100
+++ apache2-2.2.22/debian/NEWS 2014-05-25 17:34:39.000000000 +0200
@@ -1,3 +1,12 @@
+apache2 (2.2.22-13+deb7u2) stable; urgency=medium
+
+ * This release adds support for SSL/TLS ECC keys and ECDH ciphers.
+
+ If this change causes problems with some older clients, see
+ /usr/share/doc/apache2/README.Debian.gz for a work-around.
+
+ -- Stefan Fritsch <sf@debian.org> Sun, 25 May 2014 13:05:40 +0200
+
apache2 (2.2.15-4) unstable; urgency=low
* Note to people using mod_proxy as forward proxy, i.e. with
diff -Nru apache2-2.2.22/debian/patches/cookie-logging-CVE-2014-0098.diff apache2-2.2.22/debian/patches/cookie-logging-CVE-2014-0098.diff
--- apache2-2.2.22/debian/patches/cookie-logging-CVE-2014-0098.diff 1970-01-01 01:00:00.000000000 +0100
+++ apache2-2.2.22/debian/patches/cookie-logging-CVE-2014-0098.diff 2014-05-25 17:34:39.000000000 +0200
@@ -0,0 +1,81 @@
+#commit 57beef76acf54b147116636b98f9e0ea56ee503f
+#Author: Rainer Jung <rjung@apache.org>
+#Date: Sat Aug 18 09:32:36 2012 +0000
+#
+# mod_log_config: %{abc}C truncates cookies whose values contain '='.
+# PR 53104
+#
+# Backport of r1328133 from trunk resp. r1359690 from 2.4.
+#
+# Submitted by: gregames
+# Reviewed by: trawick, wrowe
+# Backported by: rjung
+#
+#
+# git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@1374538 13f79535-47bb-0310-9956-ffa450edef68
+#
+#commit 4bab699bdccdd3f48943d6ae224a1253a9a1a0d2
+#Author: Ruediger Pluem <rpluem@apache.org>
+#Date: Wed Mar 12 12:41:07 2014 +0000
+#
+# Merge r1575400 from trunk:
+#
+# CVE-2014-0098 (reported by Rainer Canavan <rainer-apache 7val com>)
+# Segfaults w/ truncated cookie logging.
+#
+# Clean up the cookie logging parser to recognize only the cookie=value pairs,
+# not valueless cookies. This refactors multiple passes over the same string
+# buffer into a single pass parser.
+#
+# Submitted by: wrowe
+# Reviewed by: rpluem, jim
+#
+# Reviewed by: wrowe, ylavic, jim
+#
+#
+# git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@1576716 13f79535-47bb-0310-9956-ffa450edef68
+#
+Index: apache2/modules/loggers/mod_log_config.c
+===================================================================
+--- apache2.orig/modules/loggers/mod_log_config.c
++++ apache2/modules/loggers/mod_log_config.c
+@@ -524,14 +524,24 @@
+
+ while ((cookie = apr_strtok(cookies, ";", &last1))) {
+ char *name = apr_strtok(cookie, "=", &last2);
+- if (name) {
+- char *value;
+- apr_collapse_spaces(name, name);
++ /* last2 points to the next char following an '=' delim,
++ or the trailing NUL char of the string */
++ char *value = last2;
++ if (name && *name && value && *value) {
++ char *last = value - 2;
++ /* Move past leading WS */
++ name += strspn(name, " \t");
++ while (last >= name && apr_isspace(*last)) {
++ *last = '\0';
++ --last;
++ }
+
+- if (!strcasecmp(name, a) && (value = apr_strtok(NULL, "=", &last2))) {
+- char *last;
+- value += strspn(value, " \t"); /* Move past leading WS */
+- last = value + strlen(value) - 1;
++ if (!strcasecmp(name, a)) {
++ /* last1 points to the next char following the ';' delim,
++ or the trailing NUL char of the string */
++ last = last1 - (*last1 ? 2 : 1);
++ /* Move past leading WS */
++ value += strspn(value, " \t");
+ while (last >= value && apr_isspace(*last)) {
+ *last = '\0';
+ --last;
+@@ -540,6 +550,7 @@
+ return ap_escape_logitem(r->pool, value);
+ }
+ }
++ /* Iterate the remaining tokens using apr_strtok(NULL, ...) */
+ cookies = NULL;
+ }
+ }
diff -Nru apache2-2.2.22/debian/patches/mod_dav-CVE-2013-6438.patch apache2-2.2.22/debian/patches/mod_dav-CVE-2013-6438.patch
--- apache2-2.2.22/debian/patches/mod_dav-CVE-2013-6438.patch 1970-01-01 01:00:00.000000000 +0100
+++ apache2-2.2.22/debian/patches/mod_dav-CVE-2013-6438.patch 2014-05-25 17:34:39.000000000 +0200
@@ -0,0 +1,34 @@
+# commit 9ea49621699c2a5ead8bc9ffb8afa6167d31a826
+# Author: Ruediger Pluem <rpluem@apache.org>
+# Date: Wed Mar 12 11:50:49 2014 +0000
+#
+# Merge r1556428 from trunk:
+#
+# mod_dav: Keep track of length of cdata properly when removing leading spaces.
+#
+# * modules/dav/main/util.c
+# (dav_xml_get_cdata): reduce len variable when increasing cdata pointer.
+#
+# Submitted by: Amin Tora <Amin.Tora neustar.biz>
+#
+# Reviewed by: breser, rpluem, gstein, wrowe
+#
+#
+# git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@1576706 13f79535-47bb-0310-9956-ffa450edef68
+#
+diff --git a/modules/dav/main/util.c b/modules/dav/main/util.c
+index ddbd621..ba856fa 100644
+--- a/modules/dav/main/util.c
++++ b/modules/dav/main/util.c
+@@ -372,8 +372,10 @@ DAV_DECLARE(const char *) dav_xml_get_cdata(const apr_xml_elem *elem, apr_pool_t
+
+ if (strip_white) {
+ /* trim leading whitespace */
+- while (apr_isspace(*cdata)) /* assume: return false for '\0' */
++ while (apr_isspace(*cdata)) { /* assume: return false for '\0' */
+ ++cdata;
++ --len;
++ }
+
+ /* trim trailing whitespace */
+ while (len-- > 0 && apr_isspace(cdata[len]))
diff -Nru apache2-2.2.22/debian/patches/mod_proxy-crash-PR_50335.patch apache2-2.2.22/debian/patches/mod_proxy-crash-PR_50335.patch
--- apache2-2.2.22/debian/patches/mod_proxy-crash-PR_50335.patch 1970-01-01 01:00:00.000000000 +0100
+++ apache2-2.2.22/debian/patches/mod_proxy-crash-PR_50335.patch 2014-05-25 17:34:39.000000000 +0200
@@ -0,0 +1,46 @@
+# https://svn.apache.org/r1576714
+# https://svn.apache.org/r1573067
+# https://issues.apache.org/bugzilla/show_bug.cgi?id=50335
+#
+# Fix crashes in mod_proxy with threaded mpms under high load
+#
+--- apache2.orig/modules/proxy/mod_proxy_http.c
++++ apache2/modules/proxy/mod_proxy_http.c
+@@ -267,6 +267,9 @@
+ if (transferred != -1)
+ conn->worker->s->transferred += transferred;
+ status = ap_pass_brigade(origin->output_filters, bb);
++ /* Cleanup the brigade now to avoid buckets lifetime
++ * issues in case of error returned below. */
++ apr_brigade_cleanup(bb);
+ if (status != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
+ "proxy: pass request body failed to %pI (%s)",
+@@ -286,7 +289,6 @@
+ return HTTP_BAD_REQUEST;
+ }
+ }
+- apr_brigade_cleanup(bb);
+ return OK;
+ }
+
+@@ -709,7 +711,7 @@
+ int force10, rv;
+ apr_table_t *headers_in_copy;
+
+- header_brigade = apr_brigade_create(p, origin->bucket_alloc);
++ header_brigade = apr_brigade_create(p, bucket_alloc);
+
+ /*
+ * Send the HTTP/1.1 request to the remote server
+@@ -1864,6 +1866,10 @@
+ }
+ } while (interim_response && (interim_response < AP_MAX_INTERIM_RESPONSES));
+
++ /* We have to cleanup bb brigade, because buckets inserted to it could be
++ * created from scpool and this pool can be freed before this brigade. */
++ apr_brigade_cleanup(bb);
++
+ /* See define of AP_MAX_INTERIM_RESPONSES for why */
+ if (interim_response >= AP_MAX_INTERIM_RESPONSES) {
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
diff -Nru apache2-2.2.22/debian/patches/series apache2-2.2.22/debian/patches/series
--- apache2-2.2.22/debian/patches/series 2014-01-31 19:41:01.000000000 +0100
+++ apache2-2.2.22/debian/patches/series 2014-05-25 17:34:39.000000000 +0200
@@ -38,3 +38,7 @@
mod_rewrite-CVE-2013-1862.patch
CVE-2013-1896.patch
mod_dav_crash_PR_52559.patch
+mod_dav-CVE-2013-6438.patch
+cookie-logging-CVE-2014-0098.diff
+SSL-ECC.patch
+mod_proxy-crash-PR_50335.patch
diff -Nru apache2-2.2.22/debian/patches/SSL-ECC.patch apache2-2.2.22/debian/patches/SSL-ECC.patch
--- apache2-2.2.22/debian/patches/SSL-ECC.patch 1970-01-01 01:00:00.000000000 +0100
+++ apache2-2.2.22/debian/patches/SSL-ECC.patch 2014-05-25 17:34:39.000000000 +0200
@@ -0,0 +1,332 @@
+# https://svn.apache.org/r1540727
+#
+# Backport from 2.2.26: mod_ssl: enable support for ECC keys and ECDH ciphers.
+#
+diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
+index b9e3f93..19794f0 100644
+--- a/modules/ssl/mod_ssl.c
++++ b/modules/ssl/mod_ssl.c
+@@ -441,6 +441,9 @@ int ssl_init_ssl_connection(conn_rec *c)
+ */
+ SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA);
+ SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH);
++#ifndef OPENSSL_NO_EC
++ SSL_set_tmp_ecdh_callback(ssl, ssl_callback_TmpECDH);
++#endif
+
+ SSL_set_verify_result(ssl, X509_V_OK);
+
+diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
+index dcae945..d8b4802 100644
+--- a/modules/ssl/ssl_engine_init.c
++++ b/modules/ssl/ssl_engine_init.c
+@@ -72,6 +72,9 @@ static void ssl_tmp_keys_free(server_rec *s)
+
+ MODSSL_TMP_KEYS_FREE(mc, RSA);
+ MODSSL_TMP_KEYS_FREE(mc, DH);
++#ifndef OPENSSL_NO_EC
++ MODSSL_TMP_KEY_FREE(mc, EC_KEY, SSL_TMP_KEY_EC_256);
++#endif
+ }
+
+ static int ssl_tmp_key_init_rsa(server_rec *s,
+@@ -133,6 +136,40 @@ static int ssl_tmp_key_init_dh(server_rec *s,
+ return OK;
+ }
+
++#ifndef OPENSSL_NO_EC
++static int ssl_tmp_key_init_ec(server_rec *s,
++ int bits, int idx)
++{
++ SSLModConfigRec *mc = myModConfig(s);
++ EC_KEY *ecdh = NULL;
++
++ /* XXX: Are there any FIPS constraints we should enforce? */
++
++ if (bits != 256) {
++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
++ "Init: Failed to generate temporary "
++ "%d bit EC parameters, only 256 bits supported", bits);
++ return !OK;
++ }
++
++ if ((ecdh = EC_KEY_new()) == NULL ||
++ EC_KEY_set_group(ecdh, EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) != 1)
++ {
++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
++ "Init: Failed to generate temporary "
++ "%d bit EC parameters", bits);
++ return !OK;
++ }
++
++ mc->pTmpKeys[idx] = ecdh;
++ return OK;
++}
++
++#define MODSSL_TMP_KEY_INIT_EC(s, bits) \
++ ssl_tmp_key_init_ec(s, bits, SSL_TMP_KEY_EC_##bits)
++
++#endif
++
+ #define MODSSL_TMP_KEY_INIT_RSA(s, bits) \
+ ssl_tmp_key_init_rsa(s, bits, SSL_TMP_KEY_RSA_##bits)
+
+@@ -157,6 +194,15 @@ static int ssl_tmp_keys_init(server_rec *s)
+ return !OK;
+ }
+
++#ifndef OPENSSL_NO_EC
++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
++ "Init: Generating temporary EC parameters (256 bits)");
++
++ if (MODSSL_TMP_KEY_INIT_EC(s, 256)) {
++ return !OK;
++ }
++#endif
++
+ return OK;
+ }
+
+@@ -399,7 +445,11 @@ static void ssl_init_server_check(server_rec *s,
+ * Check for problematic re-initializations
+ */
+ if (mctx->pks->certs[SSL_AIDX_RSA] ||
+- mctx->pks->certs[SSL_AIDX_DSA])
++ mctx->pks->certs[SSL_AIDX_DSA]
++#ifndef OPENSSL_NO_EC
++ || mctx->pks->certs[SSL_AIDX_ECC]
++#endif
++ )
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+ "Illegal attempt to re-initialise SSL for server "
+@@ -599,6 +649,9 @@ static void ssl_init_ctx_callbacks(server_rec *s,
+
+ SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA);
+ SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
++#ifndef OPENSSL_NO_EC
++ SSL_CTX_set_tmp_ecdh_callback(ctx,ssl_callback_TmpECDH);
++#endif
+
+ SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
+ }
+@@ -866,9 +919,16 @@ static int ssl_server_import_key(server_rec *s,
+ ssl_asn1_t *asn1;
+ MODSSL_D2I_PrivateKey_CONST unsigned char *ptr;
+ const char *type = ssl_asn1_keystr(idx);
+- int pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA;
++ int pkey_type;
+ EVP_PKEY *pkey;
+
++#ifndef OPENSSL_NO_EC
++ if (idx == SSL_AIDX_ECC)
++ pkey_type = EVP_PKEY_EC;
++ else
++#endif
++ pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA;
++
+ if (!(asn1 = ssl_asn1_table_get(mc->tPrivateKey, id))) {
+ return FALSE;
+ }
+@@ -979,19 +1039,39 @@ static void ssl_init_server_certs(server_rec *s,
+ modssl_ctx_t *mctx)
+ {
+ const char *rsa_id, *dsa_id;
++#ifndef OPENSSL_NO_EC
++ const char *ecc_id;
++#endif
+ const char *vhost_id = mctx->sc->vhost_id;
+ int i;
+ int have_rsa, have_dsa;
++#ifndef OPENSSL_NO_EC
++ int have_ecc;
++#endif
+
+ rsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_RSA);
+ dsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_DSA);
++#ifndef OPENSSL_NO_EC
++ ecc_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_ECC);
++#endif
+
+ have_rsa = ssl_server_import_cert(s, mctx, rsa_id, SSL_AIDX_RSA);
+ have_dsa = ssl_server_import_cert(s, mctx, dsa_id, SSL_AIDX_DSA);
++#ifndef OPENSSL_NO_EC
++ have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC);
++#endif
+
+- if (!(have_rsa || have_dsa)) {
++ if (!(have_rsa || have_dsa
++#ifndef OPENSSL_NO_EC
++ || have_ecc
++#endif
++)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
++#ifndef OPENSSL_NO_EC
++ "Oops, no RSA, DSA or ECC server certificate found "
++#else
+ "Oops, no RSA or DSA server certificate found "
++#endif
+ "for '%s:%d'?!", s->server_hostname, s->port);
+ ssl_die();
+ }
+@@ -1002,10 +1082,21 @@ static void ssl_init_server_certs(server_rec *s,
+
+ have_rsa = ssl_server_import_key(s, mctx, rsa_id, SSL_AIDX_RSA);
+ have_dsa = ssl_server_import_key(s, mctx, dsa_id, SSL_AIDX_DSA);
++#ifndef OPENSSL_NO_EC
++ have_ecc = ssl_server_import_key(s, mctx, ecc_id, SSL_AIDX_ECC);
++#endif
+
+- if (!(have_rsa || have_dsa)) {
++ if (!(have_rsa || have_dsa
++#ifndef OPENSSL_NO_EC
++ || have_ecc
++#endif
++ )) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
++#ifndef OPENSSL_NO_EC
++ "Oops, no RSA, DSA or ECC server private key found?!");
++#else
+ "Oops, no RSA or DSA server private key found?!");
++#endif
+ ssl_die();
+ }
+ }
+diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
+index 6cb2087..28bc47a 100644
+--- a/modules/ssl/ssl_engine_kernel.c
++++ b/modules/ssl/ssl_engine_kernel.c
+@@ -1267,6 +1267,27 @@ DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
+ return (DH *)mc->pTmpKeys[idx];
+ }
+
++#ifndef OPENSSL_NO_EC
++EC_KEY *ssl_callback_TmpECDH(SSL *ssl, int export, int keylen)
++{
++ conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
++ SSLModConfigRec *mc = myModConfigFromConn(c);
++ int idx;
++
++ /* XXX Uses 256-bit key for now. TODO: support other sizes. */
++ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
++ "handing out temporary 256 bit ECC key");
++
++ switch (keylen) {
++ case 256:
++ default:
++ idx = SSL_TMP_KEY_EC_256;
++ }
++
++ return (EC_KEY *)mc->pTmpKeys[idx];
++}
++#endif
++
+ /*
+ * This OpenSSL callback function is called when OpenSSL
+ * does client authentication and verifies the certificate chain.
+diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
+index 650043d..79d222e 100644
+--- a/modules/ssl/ssl_private.h
++++ b/modules/ssl/ssl_private.h
+@@ -191,11 +191,21 @@ typedef int ssl_algo_t;
+ #define SSL_ALGO_UNKNOWN (0)
+ #define SSL_ALGO_RSA (1<<0)
+ #define SSL_ALGO_DSA (1<<1)
++#ifndef OPENSSL_NO_EC
++#define SSL_ALGO_ECC (1<<2)
++#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA|SSL_ALGO_ECC)
++#else
+ #define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA)
++#endif
+
+ #define SSL_AIDX_RSA (0)
+ #define SSL_AIDX_DSA (1)
++#ifndef OPENSSL_NO_EC
++#define SSL_AIDX_ECC (2)
++#define SSL_AIDX_MAX (3)
++#else
+ #define SSL_AIDX_MAX (2)
++#endif
+
+
+ /**
+@@ -206,7 +216,12 @@ typedef int ssl_algo_t;
+ #define SSL_TMP_KEY_RSA_1024 (1)
+ #define SSL_TMP_KEY_DH_512 (2)
+ #define SSL_TMP_KEY_DH_1024 (3)
++#ifndef OPENSSL_NO_EC
++#define SSL_TMP_KEY_EC_256 (4)
++#define SSL_TMP_KEY_MAX (5)
++#else
+ #define SSL_TMP_KEY_MAX (4)
++#endif
+
+ /**
+ * Define the SSL options
+@@ -625,6 +640,9 @@ void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s);
+ /** OpenSSL callbacks */
+ RSA *ssl_callback_TmpRSA(SSL *, int, int);
+ DH *ssl_callback_TmpDH(SSL *, int, int);
++#ifndef OPENSSL_NO_EC
++EC_KEY *ssl_callback_TmpECDH(SSL *, int, int);
++#endif
+ int ssl_callback_SSLVerify(int, X509_STORE_CTX *);
+ int ssl_callback_SSLVerify_CRL(int, X509_STORE_CTX *, conn_rec *);
+ int ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **x509, EVP_PKEY **pkey);
+diff --git a/modules/ssl/ssl_toolkit_compat.h b/modules/ssl/ssl_toolkit_compat.h
+index bd57a17..6f49f30 100644
+--- a/modules/ssl/ssl_toolkit_compat.h
++++ b/modules/ssl/ssl_toolkit_compat.h
+@@ -38,6 +38,12 @@
+ #include <openssl/evp.h>
+ #include <openssl/rand.h>
+ #include <openssl/x509v3.h>
++
++/* ECC support came along in OpenSSL 1.0.0 */
++#if (OPENSSL_VERSION_NUMBER < 0x10000000)
++#define OPENSSL_NO_EC
++#endif
++
+ /** Avoid tripping over an engine build installed globally and detected
+ * when the user points at an explicit non-engine flavor of OpenSSL
+ */
+diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c
+index e4387e6..efac310 100644
+--- a/modules/ssl/ssl_util.c
++++ b/modules/ssl/ssl_util.c
+@@ -150,6 +150,11 @@ ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey)
+ case EVP_PKEY_DSA:
+ t = SSL_ALGO_DSA;
+ break;
++#ifndef OPENSSL_NO_EC
++ case EVP_PKEY_EC:
++ t = SSL_ALGO_ECC;
++ break;
++#endif
+ default:
+ break;
+ }
+@@ -174,6 +179,11 @@ char *ssl_util_algotypestr(ssl_algo_t t)
+ case SSL_ALGO_DSA:
+ cp = "DSA";
+ break;
++#ifndef OPENSSL_NO_EC
++ case SSL_ALGO_ECC:
++ cp = "ECC";
++ break;
++#endif
+ default:
+ break;
+ }
+@@ -245,7 +255,11 @@ void ssl_asn1_table_unset(apr_hash_t *table,
+ apr_hash_set(table, key, klen, NULL);
+ }
+
++#ifndef OPENSSL_NO_EC
++static const char *ssl_asn1_key_types[] = {"RSA", "DSA", "ECC"};
++#else
+ static const char *ssl_asn1_key_types[] = {"RSA", "DSA"};
++#endif
+
+ const char *ssl_asn1_keystr(int keytype)
+ {
diff -Nru apache2-2.2.22/debian/README.Debian apache2-2.2.22/debian/README.Debian
--- apache2-2.2.22/debian/README.Debian 2014-01-31 19:35:41.000000000 +0100
+++ apache2-2.2.22/debian/README.Debian 2014-05-25 17:34:39.000000000 +0200
@@ -234,6 +234,18 @@
The default SSL virtual host in /etc/apache2/sites-available/default-ssl
already contains this workaround.
+ECC keys and ECDH ciphers
+-------------------------
+
+The package in Debian has support for ECC keys and ECDH ciphers backported
+from Apache 2.2.26.
+
+If these ciphers causes any problems, they may be disabled by adding ":!ECDH"
+to the SSLCipherSuite directive in /etc/apache2/mods-enabled/ssl.conf .
+
+A special compatibility fix for older Safari browsers is enabled if using an
+up-to-date libssl-1.0.0 (version 1.0.1e-2+deb7u8 or newer).
+
Suexec
======
Reply to: