[patch] www/apache22 and www/apache20: fix CVE-2009-3555

Eygene Ryabinkin rea-fbsd at codelabs.ru
Sat Nov 7 14:02:32 UTC 2009


>Submitter-Id:	current-users
>Originator:	Eygene Ryabinkin
>Organization:	Code Labs
>Confidential:	no 
>Synopsis:	[patch] www/apache22 and www/apache20: fix CVE-2009-3555
>Severity:	critical
>Priority:	high
>Category:	ports
>Class:		sw-bug
>Release:	FreeBSD 8.0-BETA2 amd64
>Environment:

System: FreeBSD 8.0-BETA2 amd64

>Description:

See [1].

>How-To-Repeat:

[1] http://marc.info/?l=apache-httpd-announce&m=125755783724966&w=2

>Fix:

I had applied the upstream fix for the Apache 2.2 and backported it
to Apache 2.0.  Since OpenSSL port was already upgraded to 0.9.8k
that disables renegotiation, the only missing piece is the system
OpenSSL, so the patch is applied only when system OpenSSL is used.

I had verified this with www/apache22 -- renegotiation turns the
connection down and error is logged to the Apache error log.

Hadn't yet tested www/apache20 in the real world -- only compilability.

--- apache-fix.diff begins here ---
>From 7ab29b62ed92d86bc7c593a762f888a0482a0bcc Mon Sep 17 00:00:00 2001
From: Eygene Ryabinkin <rea-fbsd at codelabs.ru>
Date: Sat, 7 Nov 2009 15:29:59 +0300

Signed-off-by: Eygene Ryabinkin <rea-fbsd at codelabs.ru>
---
 www/apache20/Makefile                |    3 +-
 www/apache20/files/fix-cve-2009-3555 |  279 +++++++++++++++++++++++++++++++
 www/apache22/Makefile                |    5 +
 www/apache22/files/fix-cve-2009-3555 |  303 ++++++++++++++++++++++++++++++++++
 4 files changed, 589 insertions(+), 1 deletions(-)
 create mode 100644 www/apache20/files/fix-cve-2009-3555
 create mode 100644 www/apache22/files/fix-cve-2009-3555

diff --git a/www/apache20/Makefile b/www/apache20/Makefile
index 14a06c5..23011bd 100644
--- a/www/apache20/Makefile
+++ b/www/apache20/Makefile
@@ -9,7 +9,7 @@
 
 PORTNAME=	apache
 PORTVERSION=	2.0.63
-PORTREVISION=	3
+PORTREVISION=	4
 CATEGORIES=	www
 MASTER_SITES=	${MASTER_SITE_APACHE_HTTPD} \
 		${MASTER_SITE_LOCAL:S/$/:powerlogo/}
@@ -37,6 +37,7 @@ CONFLICTS=	apache+mod_ssl-1.* apache+mod_ssl+ipv6-1.* apache+mod_ssl+modsnmp-1.*
 
 # patch files
 EXTRA_PATCHES+=		${FILESDIR}/build-fix-openssl_beta
+EXTRA_PATCHES+=		${FILESDIR}/fix-cve-2009-3555
 
 .if defined(WITH_EXPERIMENTAL_PATCHES)
 IGNORE=		: Please define WITH_KQUEUE_SUPPORT instead
diff --git a/www/apache20/files/fix-cve-2009-3555 b/www/apache20/files/fix-cve-2009-3555
new file mode 100644
index 0000000..c6a7265
--- /dev/null
+++ b/www/apache20/files/fix-cve-2009-3555
@@ -0,0 +1,279 @@
+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);
+     }
+-
+-    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));
+-            }
+-        }
+     }
+ 
+     /*
+@@ -1789,3 +1775,48 @@
+     }
+ }
+ 
++/*
++ * 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);
++    }
++}
diff --git a/www/apache22/Makefile b/www/apache22/Makefile
index 4eb1f0c..cb9bcd4 100644
--- a/www/apache22/Makefile
+++ b/www/apache22/Makefile
@@ -9,6 +9,7 @@
 
 PORTNAME=	apache
 PORTVERSION=	2.2.13
+PORTREVISION=	1
 CATEGORIES=	www
 MASTER_SITES=	${MASTER_SITE_APACHE_HTTPD}
 DISTNAME=	httpd-${PORTVERSION}
@@ -121,6 +122,10 @@ WITH_LDAP=	yes
 CFLAGS+=	-I${OPENSSLINC}
 LDFLAGS+=	-L${OPENSSLLIB}
 
+.if defined(WITH_OPENSSL_BASE)
+EXTRA_PATCHES+=		${FILESDIR}/fix-cve-2009-3555
+.endif
+
 .endif
 
 .if defined(WITH_APR_FROM_PORTS)
diff --git a/www/apache22/files/fix-cve-2009-3555 b/www/apache22/files/fix-cve-2009-3555
new file mode 100644
index 0000000..f2253e6
--- /dev/null
+++ b/www/apache22/files/fix-cve-2009-3555
@@ -0,0 +1,303 @@
+ 
+ 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]
+
+Obtained-From: http://www.apache.org/dist/httpd/patches/apply_to_2.2.14/CVE-2009-3555-2.2.patch
+Notes: should be discarded when OpenSSL will be upgraded to 0.9.8l.
+
+Index: modules/ssl/ssl_private.h
+===================================================================
+--- modules/ssl/ssl_private.h	(revision 833621)
++++ modules/ssl/ssl_private.h	(revision 833622)
+@@ -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
+Index: modules/ssl/ssl_engine_init.c
+===================================================================
+--- modules/ssl/ssl_engine_init.c	(revision 833621)
++++ modules/ssl/ssl_engine_init.c	(revision 833622)
+@@ -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,
+Index: modules/ssl/ssl_engine_io.c
+===================================================================
+--- modules/ssl/ssl_engine_io.c	(revision 833621)
++++ modules/ssl/ssl_engine_io.c	(revision 833622)
+@@ -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);
+Index: modules/ssl/ssl_engine_kernel.c
+===================================================================
+--- modules/ssl/ssl_engine_kernel.c	(revision 833621)
++++ modules/ssl/ssl_engine_kernel.c	(revision 833622)
+@@ -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
++     * 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);
+     }
+-
+-    s = mySrvFromConn(c);
+-    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) {
++    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: 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",
++                         "%s: Exit: failed in %s",
+                          SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
+         }
+-        else if (where & SSL_CB_READ) {
++        else if (rc < 0) {
+             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+-                         "%s: Read: %s",
++                         "%s: Exit: error in %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: 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
-- 
1.6.3.1
--- apache-fix.diff ends here ---

VuXML entry will follow, probably today.


More information about the freebsd-apache mailing list