summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip M. Gollucci <pgollucci@FreeBSD.org>2010-05-13 00:30:19 +0000
committerPhilip M. Gollucci <pgollucci@FreeBSD.org>2010-05-13 00:30:19 +0000
commita0a564f0bc7174559ba406cb1db81be96aa29f9b (patch)
treee58ee24728b2a4ec71ce4bd2facae784ee26ef4d
parentBackport of the Apache 2.3 module that replaces the apparent client (diff)
- Fix openssl rengotiation patch [1]
- Fix the openssl from ports flag - Bump PORTREVISION - Also patch 2 more CVEs *) SECURITY: CVE-2010-0434 (cve.mitre.org) Ensure each subrequest has a shallow copy of headers_in so that the parent request headers are not corrupted. Elimiates a problematic optimization in the case of no request body. PR 48359 [Jake Scott, William Rowe, Ruediger Pluem] *) SECURITY: CVE-2008-2364 (cve.mitre.org) mod_proxy_http: Better handling of excessive interim responses from origin server to prevent potential denial of service and high memory usage. Reported by Ryujiro Shibuya. [Ruediger Pluem, Joe Orton, Jim Jagielski] PR: ports/146389 [1] Submitted by: several [1] With Hat: apache@
Notes
Notes: svn path=/head/; revision=254235
-rw-r--r--www/apache20/Makefile4
-rw-r--r--www/apache20/files/patch-CVE-2008-236462
-rw-r--r--www/apache20/files/patch-CVE-2009-3555340
-rw-r--r--www/apache20/files/patch-CVE-2010-043411
4 files changed, 146 insertions, 271 deletions
diff --git a/www/apache20/Makefile b/www/apache20/Makefile
index 0fc06a812d6c..5eb9d5285746 100644
--- a/www/apache20/Makefile
+++ b/www/apache20/Makefile
@@ -9,7 +9,7 @@
PORTNAME= apache
PORTVERSION= 2.0.63
-PORTREVISION= 8
+PORTREVISION= 9
CATEGORIES= www
MASTER_SITES= ${MASTER_SITE_APACHE_HTTPD} \
${MASTER_SITE_LOCAL:S/$/:powerlogo/}
@@ -147,7 +147,7 @@ CONFIGURE_ARGS+= --enable-ldap=shared --enable-auth-ldap --with-ldap \
.include "${APACHEDIR}/Makefile.modules"
.include <bsd.port.pre.mk>
-.if defined(OPENSSL_INSTALLED)
+.if defined(WITH_OPENSSL_PORT)
EXTRA_PATCHES+= ${FILESDIR}/extra-openssl-9.8up.patch
.endif
diff --git a/www/apache20/files/patch-CVE-2008-2364 b/www/apache20/files/patch-CVE-2008-2364
new file mode 100644
index 000000000000..4848ad92acb1
--- /dev/null
+++ b/www/apache20/files/patch-CVE-2008-2364
@@ -0,0 +1,62 @@
+--- modules/proxy/proxy_http.c 2010/03/11 15:52:45 921907
++++ modules/proxy/proxy_http.c 2010/03/11 15:54:18 921908
+@@ -1290,6 +1290,16 @@
+ return 1;
+ }
+
++/*
++ * Limit the number of interim respones we sent back to the client. Otherwise
++ * we suffer from a memory build up. Besides there is NO sense in sending back
++ * an unlimited number of interim responses to the client. Thus if we cross
++ * this limit send back a 502 (Bad Gateway).
++ */
++#ifndef AP_MAX_INTERIM_RESPONSES
++#define AP_MAX_INTERIM_RESPONSES 10
++#endif
++
+ static
+ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
+ proxy_http_conn_t *p_conn,
+@@ -1322,7 +1332,7 @@
+ */
+ rp->proxyreq = PROXYREQ_RESPONSE;
+
+- while (received_continue) {
++ while (received_continue && (received_continue <= AP_MAX_INTERIM_RESPONSES)) {
+ apr_brigade_cleanup(bb);
+
+ len = ap_getline(buffer, sizeof(buffer), rp, 0);
+@@ -1440,7 +1450,9 @@
+ if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
+ ap_set_content_type(r, apr_pstrdup(p, buf));
+ }
+- ap_proxy_pre_http_request(origin,rp);
++ if (!ap_is_HTTP_INFO(r->status)) {
++ ap_proxy_pre_http_request(origin, rp);
++ }
+
+ /* handle Via header in response */
+ if (conf->viaopt != via_off && conf->viaopt != via_block) {
+@@ -1486,6 +1498,7 @@
+ if ( r->status != HTTP_CONTINUE ) {
+ received_continue = 0;
+ } else {
++ received_continue++;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
+ "proxy: HTTP: received 100 CONTINUE");
+ }
+@@ -1622,6 +1635,14 @@
+ }
+ }
+
++ /* See define of AP_MAX_INTERIM_RESPONSES for why */
++ if (received_continue > AP_MAX_INTERIM_RESPONSES) {
++ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
++ apr_psprintf(p,
++ "Too many (%d) interim responses from origin server",
++ received_continue));
++ }
++
+ if ( conf->error_override ) {
+ /* the code above this checks for 'OK' which is what the hook expects */
+ if ( r->status == HTTP_OK )
diff --git a/www/apache20/files/patch-CVE-2009-3555 b/www/apache20/files/patch-CVE-2009-3555
index c6a7265b34f4..fd997ab960fc 100644
--- a/www/apache20/files/patch-CVE-2009-3555
+++ b/www/apache20/files/patch-CVE-2009-3555
@@ -1,279 +1,81 @@
-Modified patch from http://www.apache.org/dist/httpd/patches/apply_to_2.2.14/CVE-2009-3555-2.2.patch
-
---- modules/ssl/mod_ssl.h.orig 2009-11-07 14:55:25.000000000 +0300
-+++ modules/ssl/mod_ssl.h 2009-11-07 14:56:40.000000000 +0300
-@@ -389,6 +389,19 @@
- int is_proxy;
- int disabled;
- int non_ssl_request;
-+
-+ /* Track the handshake/renegotiation state for the connection so
-+ * that all client-initiated renegotiations can be rejected, as a
-+ * partial fix for CVE-2009-3555. */
-+ enum {
-+ RENEG_INIT = 0, /* Before initial handshake */
-+ RENEG_REJECT, /* After initial handshake; any client-initiated
-+ * renegotiation should be rejected */
-+ RENEG_ALLOW, /* A server-initated renegotiation is taking
-+ * place (as dictated by configuration) */
-+ RENEG_ABORT /* Renegotiation initiated by client, abort the
-+ * connection */
-+ } reneg_state;
- } SSLConnRec;
-
- typedef struct {
-@@ -585,7 +598,7 @@
- int ssl_callback_NewSessionCacheEntry(SSL *, SSL_SESSION *);
- SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *);
- void ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
--void ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE, int, int);
-+void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE, int, int);
-
- /* Session Cache Support */
- void ssl_scache_init(server_rec *, apr_pool_t *);
---- modules/ssl/ssl_engine_init.c.orig 2009-11-07 14:57:31.000000000 +0300
-+++ modules/ssl/ssl_engine_init.c 2009-11-07 14:58:00.000000000 +0300
-@@ -464,10 +464,7 @@
- SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA);
- SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
-
-- if (s->loglevel >= APLOG_DEBUG) {
-- /* this callback only logs if LogLevel >= info */
-- SSL_CTX_set_info_callback(ctx, ssl_callback_LogTracingState);
-- }
-+ SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
- }
-
- static void ssl_init_ctx_verify(server_rec *s,
---- modules/ssl/ssl_engine_io.c.orig 2009-11-07 14:58:35.000000000 +0300
-+++ modules/ssl/ssl_engine_io.c 2009-11-07 15:01:05.000000000 +0300
-@@ -102,6 +102,7 @@
- ap_filter_t *pInputFilter;
- ap_filter_t *pOutputFilter;
- int nobuffer; /* non-zero to prevent buffering */
-+ SSLConnRec *config;
- } ssl_filter_ctx_t;
-
- typedef struct {
-@@ -193,6 +194,12 @@
- {
- bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr);
-
-+ /* Abort early if the client has initiated a renegotiation. */
-+ if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
-+ outctx->rc = APR_ECONNABORTED;
-+ return -1;
-+ }
-+
- /* when handshaking we'll have a small number of bytes.
- * max size SSL will pass us here is about 16k.
- * (16413 bytes to be exact)
-@@ -465,6 +472,12 @@
- if (!in)
- return 0;
-
-+ /* Abort early if the client has initiated a renegotiation. */
-+ if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
-+ inctx->rc = APR_ECONNABORTED;
-+ return -1;
-+ }
-+
- /* XXX: flush here only required for SSLv2;
- * OpenSSL calls BIO_flush() at the appropriate times for
- * the other protocols.
-@@ -1585,6 +1598,8 @@
-
- filter_ctx = apr_palloc(c->pool, sizeof(ssl_filter_ctx_t));
-
-+ filter_ctx->config = myConnConfig(c);
-+
- filter_ctx->nobuffer = 0;
- filter_ctx->pOutputFilter = ap_add_output_filter(ssl_io_filter,
- filter_ctx, NULL, c);
---- modules/ssl/ssl_engine_kernel.c.orig 2009-11-07 15:01:41.000000000 +0300
-+++ modules/ssl/ssl_engine_kernel.c 2009-11-07 15:09:49.000000000 +0300
-@@ -611,6 +611,10 @@
- (unsigned char *)&id,
- sizeof(id));
-
-+ /* Toggle the renegotiation state to allow the new
-+ * handshake to proceed. */
-+ sslconn->reneg_state = RENEG_ALLOW;
-+
- SSL_renegotiate(ssl);
- SSL_do_handshake(ssl);
-
-@@ -628,6 +632,8 @@
- SSL_set_state(ssl, SSL_ST_ACCEPT);
- SSL_do_handshake(ssl);
-
-+ sslconn->reneg_state = RENEG_REJECT;
-+
- if (SSL_get_state(ssl) != SSL_ST_OK) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
- "Re-negotiation handshake failed: "
-@@ -1700,76 +1706,56 @@
- return;
- }
-
--/*
-- * This callback function is executed while OpenSSL processes the
-- * SSL handshake and does SSL record layer stuff. We use it to
-- * trace OpenSSL's processing in out SSL logfile.
-- */
--void ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc)
--{
-- conn_rec *c;
-- server_rec *s;
-- SSLSrvConfigRec *sc;
-+/* Dump debugginfo trace to the log file. */
-+static void log_tracing_state(MODSSL_INFO_CB_ARG_TYPE ssl, conn_rec *c,
-+ server_rec *s, int where, int rc)
-
-+{
- /*
-- * find corresponding server
-+ * create the various trace messages
- */
-- if (!(c = (conn_rec *)SSL_get_app_data((SSL *)ssl))) {
-- return;
-+ if (where & SSL_CB_HANDSHAKE_START) {
-+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-+ "%s: Handshake: start", SSL_LIBRARY_NAME);
+Index: modules/ssl/ssl_engine_io.c
+===================================================================
+--- modules/ssl/ssl_engine_io.c 2010-01-08 16:06:21.000000000 +0100
++++ modules/ssl/ssl_engine_io.c 2010-01-08 15:31:05.000000000 +0100
+@@ -1241,9 +1241,17 @@
}
--
-- s = c->base_server;
-- if (!(sc = mySrvConfig(s))) {
-- return;
-+ else if (where & SSL_CB_HANDSHAKE_DONE) {
-+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-+ "%s: Handshake: done", SSL_LIBRARY_NAME);
- }
--
-- /*
-- * create the various trace messages
-- */
-- if (s->loglevel >= APLOG_DEBUG) {
-- if (where & SSL_CB_HANDSHAKE_START) {
-- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-- "%s: Handshake: start", SSL_LIBRARY_NAME);
-- }
-- else if (where & SSL_CB_HANDSHAKE_DONE) {
-- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-- "%s: Handshake: done", SSL_LIBRARY_NAME);
-- }
-- else if (where & SSL_CB_LOOP) {
-- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-- "%s: Loop: %s",
-- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
-- }
-- else if (where & SSL_CB_READ) {
-+ else if (where & SSL_CB_LOOP) {
-+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-+ "%s: Loop: %s",
-+ SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
-+ }
-+ else if (where & SSL_CB_READ) {
-+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-+ "%s: Read: %s",
-+ SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
-+ }
-+ else if (where & SSL_CB_WRITE) {
-+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-+ "%s: Write: %s",
-+ SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
-+ }
-+ else if (where & SSL_CB_ALERT) {
-+ char *str = (where & SSL_CB_READ) ? "read" : "write";
-+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-+ "%s: Alert: %s:%s:%s",
-+ SSL_LIBRARY_NAME, str,
-+ SSL_alert_type_string_long(rc),
-+ SSL_alert_desc_string_long(rc));
-+ }
-+ else if (where & SSL_CB_EXIT) {
-+ if (rc == 0) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-- "%s: Read: %s",
-+ "%s: Exit: failed in %s",
- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
- }
-- else if (where & SSL_CB_WRITE) {
-+ else if (rc < 0) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-- "%s: Write: %s",
-+ "%s: Exit: error in %s",
- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
- }
-- else if (where & SSL_CB_ALERT) {
-- char *str = (where & SSL_CB_READ) ? "read" : "write";
-- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-- "%s: Alert: %s:%s:%s",
-- SSL_LIBRARY_NAME, str,
-- SSL_alert_type_string_long(rc),
-- SSL_alert_desc_string_long(rc));
-- }
-- else if (where & SSL_CB_EXIT) {
-- if (rc == 0) {
-- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-- "%s: Exit: failed in %s",
-- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
-- }
-- else if (rc < 0) {
-- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-- "%s: Exit: error in %s",
-- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
-- }
-- }
+ else {
+ /* We have no idea what you are talking about, so return an error. */
+- return APR_ENOTIMPL;
++ status = APR_ENOTIMPL;
}
- /*
-@@ -1789,3 +1775,48 @@
++ /* It is possible for mod_ssl's BIO to be used outside of the
++ * direct control of mod_ssl's input or output filter -- notably,
++ * when mod_ssl initiates a renegotiation. Switching the BIO mode
++ * back to "blocking" here ensures such operations don't fail with
++ * SSL_ERROR_WANT_READ. */
++ inctx->block = APR_BLOCK_READ;
++
++ /* Handle custom errors. */
+ if (status != APR_SUCCESS) {
+ return ssl_io_filter_error(f, bb, status);
}
- }
-
-+/*
-+ * This callback function is executed while OpenSSL processes the SSL
-+ * handshake and does SSL record layer stuff. It's used to trap
-+ * client-initiated renegotiations, and for dumping everything to the
-+ * log.
-+ */
-+void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc)
+Index: modules/ssl/ssl_engine_kernel.c
+===================================================================
+--- modules/ssl/ssl_engine_kernel.c 2010-01-08 16:06:21.000000000 +0100
++++ modules/ssl/ssl_engine_kernel.c 2010-01-08 15:24:48.000000000 +0100
+@@ -31,6 +31,29 @@
+ #include "mod_ssl.h"
+
+ static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
++
++/* Perform a speculative (and non-blocking) read from the connection
++ * filters for the given request, to determine whether there is any
++ * pending data to read. Return non-zero if there is, else zero. */
++static int has_buffered_data(request_rec *r)
+{
-+ conn_rec *c;
-+ server_rec *s;
-+ SSLConnRec *scr;
++ apr_bucket_brigade *bb;
++ apr_off_t len;
++ apr_status_t rv;
++ int result;
+
-+ /* Retrieve the conn_rec and the associated SSLConnRec. */
-+ if ((c = (conn_rec *)SSL_get_app_data((SSL *)ssl)) == NULL) {
-+ return;
-+ }
++ bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+
-+ if ((scr = myConnConfig(c)) == NULL) {
-+ return;
-+ }
++ rv = ap_get_brigade(r->connection->input_filters, bb, AP_MODE_SPECULATIVE,
++ APR_NONBLOCK_READ, 1);
++ result = rv == APR_SUCCESS
++ && apr_brigade_length(bb, 1, &len) == APR_SUCCESS
++ && len > 0;
+
-+ /* If the reneg state is to reject renegotiations, check the SSL
-+ * state machine and move to ABORT if a Client Hello is being
-+ * read. */
-+ if ((where & SSL_CB_ACCEPT_LOOP) && scr->reneg_state == RENEG_REJECT) {
-+ int state = SSL_get_state(ssl);
++ apr_brigade_destroy(bb);
+
-+ if (state == SSL3_ST_SR_CLNT_HELLO_A
-+ || state == SSL23_ST_SR_CLNT_HELLO_A) {
-+ scr->reneg_state = RENEG_ABORT;
-+ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
-+ "rejecting client initiated renegotiation");
-+ }
-+ }
-+ /* If the first handshake is complete, change state to reject any
-+ * subsequent client-initated renegotiation. */
-+ else if ((where & SSL_CB_HANDSHAKE_DONE) && scr->reneg_state == RENEG_INIT) {
-+ scr->reneg_state = RENEG_REJECT;
-+ }
-+
-+ s = mySrvFromConn(c);
-+ if (s && s->loglevel >= APLOG_DEBUG) {
-+ log_tracing_state(ssl, c, s, where, rc);
-+ }
++ return result;
+}
+
+ /*
+ * Post Read Request Handler
+@@ -602,6 +625,23 @@
+ else {
+ request_rec *id = r->main ? r->main : r;
+
++ /* Additional mitigation for CVE-2009-3555: At this point,
++ * before renegotiating, an (entire) request has been read
++ * from the connection. An attacker may have sent further
++ * data to "prefix" any subsequent request by the victim's
++ * client after the renegotiation; this data may already
++ * have been read and buffered. Forcing a connection
++ * closure after the response ensures such data will be
++ * discarded. Legimately pipelined HTTP requests will be
++ * retried anyway with this approach. */
++ if (has_buffered_data(r)) {
++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
++ "insecure SSL re-negotiation required, but "
++ "a pipelined request is present; keepalive "
++ "disabled");
++ r->connection->keepalive = AP_CONN_CLOSE;
++ }
++
+ /* do a full renegotiation */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "Performing full renegotiation: "
diff --git a/www/apache20/files/patch-CVE-2010-0434 b/www/apache20/files/patch-CVE-2010-0434
new file mode 100644
index 000000000000..0f6407d0e469
--- /dev/null
+++ b/www/apache20/files/patch-CVE-2010-0434
@@ -0,0 +1,11 @@
+--- server/protocol.c 2010/03/11 15:55:59 921909
++++ server/protocol.c 2010/03/11 15:57:26 921910
+@@ -1022,7 +1022,7 @@
+
+ rnew->status = HTTP_OK;
+
+- rnew->headers_in = r->headers_in;
++ rnew->headers_in = apr_table_copy(rnew->pool, r->headers_in);
+ rnew->subprocess_env = apr_table_copy(rnew->pool, r->subprocess_env);
+ rnew->headers_out = apr_table_make(rnew->pool, 5);
+ rnew->err_headers_out = apr_table_make(rnew->pool, 5);