Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Apache: CVS

svn commit: r833622 - in /httpd/httpd/branches/2.2.x: CHANGES modules/ssl/ssl_engine_init.c modules/ssl/ssl_engine_io.c modules/ssl/ssl_engine_kernel.c modules/ssl/ssl_private.h

 

 

Apache cvs RSS feed   Index | Next | Previous | View Threaded


jorton at apache

Nov 6, 2009, 4:56 PM

Post #1 of 1 (62 views)
Permalink
svn commit: r833622 - in /httpd/httpd/branches/2.2.x: CHANGES modules/ssl/ssl_engine_init.c modules/ssl/ssl_engine_io.c modules/ssl/ssl_engine_kernel.c modules/ssl/ssl_private.h

Author: jorton
Date: Sat Nov 7 00:56:23 2009
New Revision: 833622

URL: http://svn.apache.org/viewvc?rev=833622&view=rev
Log:
Merge r833582, r833593 from trunk:

SECURITY: Partial fix for CVE-2009-3555:

Reject client-initiated renegotiations; this is sufficient to prevent
the attack for any configuration which does not require renegotiation
due to per-directory/per-location access control configuration.

Configuration with per-directory/per-location access control
requirements (such as "SSLVerifyClient require") are still vulnerable
to CVE-2009-3555 with this patch applied (if using OpenSSL <= 0.9.8k).

* modules/ssl/ssl_private.h (SSLConnRec): Add reneg_state field.
(ssl_callback_Info): Renamed from ssl_callback_LogTracingState.

* modules/ssl/ssl_engine_init.c (ssl_init_ctx_callbacks): Install
the (renamed) info callback unconditionally.

* modules/ssl/ssl_engine_io.c (ssl_filter_ctx_t): Add config pointer
to SSLConnRec.
(bio_filter_out_write, bio_filter_in_read): Fail with
APR_ECONNABORTED if the reneg state is set to RENEG_ABORT.

* modules/ssl/ssl_engine_kernel.c (log_tracing_state): Factored out
of ssl_callback_LogTracingState.
(ssl_callback_Info): New function.

Submitted by: jorton, rpluem
Reviewed by: jorton, rpluem, dirkx

Modified:
httpd/httpd/branches/2.2.x/CHANGES
httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_init.c
httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c
httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_kernel.c
httpd/httpd/branches/2.2.x/modules/ssl/ssl_private.h

Modified: httpd/httpd/branches/2.2.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/CHANGES?rev=833622&r1=833621&r2=833622&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.2.x/CHANGES [utf-8] Sat Nov 7 00:56:23 2009
@@ -1,6 +1,13 @@
-*- coding: utf-8 -*-
Changes with Apache 2.2.15

+ *) SECURITY: CVE-2009-3555 (cve.mitre.org)
+ A partial fix for the TLS renegotiation prefix injection attack by
+ rejecting any client-initiated renegotiations. Any configuration
+ which requires renegotiation for per-directory/location access
+ control is still vulnerable, unless using OpenSSL >= 0.9.8l.
+ [Joe Orton, Ruediger Pluem]
+
*) mod_rewrite: Make sure that a hostname:port isn't fully qualified if
the request is a CONNECT request. PR 47928
[Bill Zajac <billz consultla.com>]

Modified: httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_init.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_init.c?rev=833622&r1=833621&r2=833622&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_init.c (original)
+++ httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_init.c Sat Nov 7 00:56:23 2009
@@ -501,10 +501,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,

Modified: httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c?rev=833622&r1=833621&r2=833622&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c (original)
+++ httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c Sat Nov 7 00:56:23 2009
@@ -103,6 +103,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,7 +194,13 @@
static int bio_filter_out_write(BIO *bio, const char *in, int inl)
{
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)
@@ -466,6 +473,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.
@@ -1724,6 +1737,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);

Modified: httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_kernel.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_kernel.c?rev=833622&r1=833621&r2=833622&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_kernel.c (original)
+++ httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_kernel.c Sat Nov 7 00:56:23 2009
@@ -729,6 +729,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);

@@ -750,6 +754,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_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Re-negotiation handshake failed: "
@@ -1844,76 +1850,55 @@
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)
+/* 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)
{
- conn_rec *c;
- server_rec *s;
- SSLSrvConfigRec *sc;
-
- /*
- * find corresponding server
- */
- if (!(c = (conn_rec *)SSL_get_app_data((SSL *)ssl))) {
- return;
- }
-
- s = mySrvFromConn(c);
- if (!(sc = mySrvConfig(s))) {
- return;
- }
-
/*
* 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) {
+ 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) {
+ 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));
- }
- }
}

/*
@@ -1933,6 +1918,52 @@
}
}

+/*
+ * 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)
+{
+ conn_rec *c;
+ server_rec *s;
+ SSLConnRec *scr;
+
+ /* Retrieve the conn_rec and the associated SSLConnRec. */
+ if ((c = (conn_rec *)SSL_get_app_data((SSL *)ssl)) == NULL) {
+ return;
+ }
+
+ if ((scr = myConnConfig(c)) == NULL) {
+ return;
+ }
+
+ /* 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);
+
+ 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);
+ }
+}
+
#ifndef OPENSSL_NO_TLSEXT
/*
* This callback function is executed when OpenSSL encounters an extended

Modified: httpd/httpd/branches/2.2.x/modules/ssl/ssl_private.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/ssl/ssl_private.h?rev=833622&r1=833621&r2=833622&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/ssl/ssl_private.h (original)
+++ httpd/httpd/branches/2.2.x/modules/ssl/ssl_private.h Sat Nov 7 00:56:23 2009
@@ -356,6 +356,20 @@
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;
+
server_rec *server;
} SSLConnRec;

@@ -574,7 +588,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);
#ifndef OPENSSL_NO_TLSEXT
int ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
#endif

Apache cvs RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact lists@gossamer-threads.com
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.