Index: src/base.h
===================================================================
--- src/base.h.orig	2013-03-26 16:37:12.813039493 +0100
+++ src/base.h	2013-03-26 16:41:12.886017236 +0100
@@ -270,6 +270,7 @@ typedef struct {
 	buffer *ssl_ca_file;
 	buffer *ssl_cipher_list;
 	unsigned short ssl_use_sslv2;
+	unsigned short ssl_disable_client_renegotiation;
 
 	unsigned short use_ipv6;
 	unsigned short is_ssl;
@@ -421,6 +422,7 @@ typedef struct {
 # ifndef OPENSSL_NO_TLSEXT
 	buffer *tlsext_server_name;
 # endif
+	unsigned int renegotiations; /* count of SSL_CB_HANDSHAKE_START */
 #endif
 	/* etag handling */
 	etag_flags_t etag_flags;
Index: src/configfile.c
===================================================================
--- src/configfile.c.orig	2013-03-26 16:37:12.813039493 +0100
+++ src/configfile.c	2013-03-26 16:41:12.888017236 +0100
@@ -94,6 +94,7 @@ static int config_insert(server *srv) {
 		{ "etag.use-inode",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 49 */
 		{ "etag.use-mtime",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 50 */
 		{ "etag.use-size",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 51 */
+		{ "ssl.disable-client-renegotiation", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },/* 52 */
 		{ "server.host",                 "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
 		{ "server.docroot",              "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
 		{ "server.virtual-root",         "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
@@ -174,6 +175,7 @@ static int config_insert(server *srv) {
 		s->global_kbytes_per_second = 0;
 		s->global_bytes_per_second_cnt = 0;
 		s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
+		s->ssl_disable_client_renegotiation = 1;
 
 		cv[2].destination = s->errorfile_prefix;
 
@@ -217,6 +219,7 @@ static int config_insert(server *srv) {
 		cv[49].destination = &(s->etag_use_inode);
 		cv[50].destination = &(s->etag_use_mtime);
 		cv[51].destination = &(s->etag_use_size);
+		cv[52].destination = &(s->ssl_disable_client_renegotiation);
 
 		srv->config_storage[i] = s;
 
@@ -296,6 +299,7 @@ int config_setup_connection(server *srv,
 	PATCH(etag_use_inode);
 	PATCH(etag_use_mtime);
 	PATCH(etag_use_size);
+	PATCH(ssl_disable_client_renegotiation);
  
 	return 0;
 }
@@ -384,6 +388,8 @@ int config_patch_connection(server *srv,
 				PATCH(global_kbytes_per_second);
 				PATCH(global_bytes_per_second_cnt);
 				con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.disable-client-renegotiation"))) {
+				PATCH(ssl_disable_client_renegotiation);
 			}
 		}
 	}
Index: src/connections.c
===================================================================
--- src/connections.c.orig	2013-03-26 16:37:12.813039493 +0100
+++ src/connections.c	2013-03-26 16:41:12.889017236 +0100
@@ -217,6 +217,12 @@ static int connection_handle_read_ssl(se
 
 		len = SSL_read(con->ssl, b->ptr + read_offset, toread);
 
+		if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
+			connection_set_state(srv, con, CON_STATE_ERROR);
+			log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
+			return -1;
+		}
+
 
 		if (len > 0) {
 			if (b->used > 0) b->used--;
@@ -1355,9 +1361,8 @@ connection *connection_accept(server *sr
 				return NULL;
 			}
 
-#ifndef OPENSSL_NO_TLSEXT
+			con->renegotiations = 0;
 			SSL_set_app_data(con->ssl, con);
-#endif
 			SSL_set_accept_state(con->ssl);
 			con->conf.is_ssl=1;
 
Index: src/network.c
===================================================================
--- src/network.c.orig	2013-03-26 16:38:04.711034681 +0100
+++ src/network.c	2013-03-26 16:41:12.890017235 +0100
@@ -27,6 +27,17 @@
 # include <openssl/rand.h>
 #endif
 
+static void ssl_info_callback(const SSL *ssl, int where, int ret) {
+	UNUSED(ret);
+
+	if (0 != (where & SSL_CB_HANDSHAKE_START)) {
+		connection *con = SSL_get_app_data(ssl);
+		++con->renegotiations;
+	} else if (0 != (where & SSL_CB_HANDSHAKE_DONE)) {
+		ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
+	}
+}
+
 handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
 	server     *srv = (server *)s;
 	server_socket *srv_socket = (server_socket *)context;
@@ -468,6 +479,12 @@ int network_init(server *srv) {
 	for (i = 0; i < srv->config_context->used; i++) {
 		data_config *dc = (data_config *)srv->config_context->data[i];
 		specific_config *s = srv->config_storage[i];
+#ifndef SSL_OP_NO_COMPRESSION
+# define SSL_OP_NO_COMPRESSION 0
+#endif
+		long ssloptions =
+			SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;
+
 
 		if (buffer_is_empty(s->ssl_pemfile)) continue;
 
@@ -497,9 +514,12 @@ int network_init(server *srv) {
 			return -1;
 		}
 
+		SSL_CTX_set_options(s->ssl_ctx, ssloptions);
+		SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);
+
 		if (!s->ssl_use_sslv2) {
 			/* disable SSLv2 */
-			if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) {	
+			if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) {
 				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
 						ERR_error_string(ERR_get_error(), NULL));
 				return -1;
Index: src/network_openssl.c
===================================================================
--- src/network_openssl.c.orig	2013-03-26 16:37:12.813039493 +0100
+++ src/network_openssl.c	2013-03-26 16:41:12.891017235 +0100
@@ -86,7 +86,14 @@ int network_write_chunkqueue_openssl(ser
 			 */
 
 			ERR_clear_error();
-			if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
+			r = SSL_write(ssl, offset, toSend);
+
+			if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
+				log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
+				return -1;
+			}
+
+			if (r <= 0) {
 				unsigned long err;
 
 				switch ((ssl_r = SSL_get_error(ssl, r))) {
@@ -189,7 +196,14 @@ int network_write_chunkqueue_openssl(ser
 				close(ifd);
 
 				ERR_clear_error();
-				if ((r = SSL_write(ssl, s, toSend)) <= 0) {
+				r = SSL_write(ssl, s, toSend);
+
+				if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
+					log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
+					return -1;
+				}
+
+				if (r <= 0) {
 					unsigned long err;
 
 					switch ((ssl_r = SSL_get_error(ssl, r))) {
