diff -ruN -x '*~' stunnel-4.54b4.orig/doc/stunnel.8 stunnel-4.54b4/doc/stunnel.8
--- stunnel-4.54b4.orig/doc/stunnel.8	2012-06-27 22:58:47.702927772 +0200
+++ stunnel-4.54b4/doc/stunnel.8	2012-06-27 23:24:18.597867466 +0200
@@ -582,6 +582,18 @@
 .IP "\fBpty\fR = yes | no (Unix only)" 4
 .IX Item "pty = yes | no (Unix only)"
 allocate pseudo terminal for 'exec' option
+.IP "\fBrenegotiation\fR = yes | no" 4
+.IX Item "renegotiation = yes | no"
+support SSL renegotiation
+.Sp
+Renegotiation can be a security risk (see CVE-2009-3555, although it
+is patched in any recent OpenSSL version) and also can make certain
+DoS attacks easier (see http://www.thc.org/thc-ssl-dos/). In most
+cases it can be disabled, but be advised that it is needed sometimes
+(for example in some cases of certificate based client
+authentication).
+.Sp
+default: yes (if OpenSSL supports it)
 .IP "\fBreset\fR = yes | no" 4
 .IX Item "reset = yes | no"
 attempt to use \s-1TCP\s0 \s-1RST\s0 flag to indicate an error
diff -ruN -x '*~' stunnel-4.54b4.orig/src/client.c stunnel-4.54b4/src/client.c
--- stunnel-4.54b4.orig/src/client.c	2012-06-27 22:58:47.704927772 +0200
+++ stunnel-4.54b4/src/client.c	2012-06-27 23:15:41.747887826 +0200
@@ -605,6 +605,11 @@
             longjmp(c->err, 1);
         }
 
+        if(c->reneg_state == RENEG_DETECTED && !c->opt->option.renegotiation) {
+            s_log(LOG_NOTICE, "Aborting due to renegotiation request");
+            longjmp(c->err, 1);
+        }
+
         /****************************** send SSL close_notify alert */
         if(shutdown_wants_read || shutdown_wants_write) {
             num=SSL_shutdown(c->ssl); /* send close_notify alert */
diff -ruN -x '*~' stunnel-4.54b4.orig/src/ctx.c stunnel-4.54b4/src/ctx.c
--- stunnel-4.54b4.orig/src/ctx.c	2012-06-27 22:58:47.705927772 +0200
+++ stunnel-4.54b4/src/ctx.c	2012-06-27 23:17:51.684882707 +0200
@@ -614,6 +614,28 @@
         const
 #endif
         SSL *ssl, int where, int ret) {
+    CLI *c;
+
+    c = SSL_get_ex_data(ssl, cli_index);
+    if(c) {
+        if((where & SSL_CB_HANDSHAKE_DONE) &&
+           c->reneg_state == RENEG_INIT) {
+            /* first (initial) handshake was completed, remember this,
+             * so that further renegotiation attempts can be detected */
+            c->reneg_state = RENEG_ESTABLISHED;
+        } else if((where & SSL_CB_ACCEPT_LOOP) &&
+                  c->reneg_state == RENEG_ESTABLISHED) {
+            int state = SSL_get_state(ssl);
+
+            if (state == SSL3_ST_SR_CLNT_HELLO_A ||
+                state == SSL23_ST_SR_CLNT_HELLO_A) {
+                /* client hello received after initial handshake, this
+                 * means renegotiation, mark it */
+                c->reneg_state = RENEG_DETECTED;
+            }
+        }
+    }
+
     if(global_options.debug_level<LOG_DEBUG)
         return; /* performance optimization */
     if(where & SSL_CB_LOOP) {
diff -ruN -x '*~' stunnel-4.54b4.orig/src/options.c stunnel-4.54b4/src/options.c
--- stunnel-4.54b4.orig/src/options.c	2012-06-27 22:58:47.705927772 +0200
+++ stunnel-4.54b4/src/options.c	2012-06-27 23:06:29.667909573 +0200
@@ -1189,6 +1189,29 @@
     }
 #endif
 
+    /* renegotiation */
+    switch(cmd) {
+    case CMD_INIT:
+        section->option.renegotiation=1;
+        break;
+    case CMD_EXEC:
+        if(strcasecmp(opt, "renegotiation"))
+            break;
+        if(!strcasecmp(arg, "yes"))
+            section->option.renegotiation=1;
+        else if(!strcasecmp(arg, "no"))
+            section->option.renegotiation=0;
+        else
+            return "argument should be either 'yes' or 'no'";
+        return NULL; /* OK */
+    case CMD_DEFAULT:
+        break;
+    case CMD_HELP:
+        s_log(LOG_NOTICE, "%-15s = yes|no support renegotiation",
+              "renegotiation");
+        break;
+    }
+
     /* reset */
     switch(cmd) {
     case CMD_INIT:
diff -ruN -x '*~' stunnel-4.54b4.orig/src/prototypes.h stunnel-4.54b4/src/prototypes.h
--- stunnel-4.54b4.orig/src/prototypes.h	2012-06-27 22:58:47.705927772 +0200
+++ stunnel-4.54b4/src/prototypes.h	2012-06-27 23:14:44.883890065 +0200
@@ -219,6 +219,7 @@
         unsigned int ocsp:1;
 #endif
         unsigned int reset:1;           /* reset sockets on error */
+        unsigned int renegotiation:1;
     } option;
 } SERVICE_OPTIONS;
 
@@ -397,6 +398,12 @@
 
 /**************************************** prototypes for client.c */
 
+typedef enum {
+    RENEG_INIT, /* initial state */
+    RENEG_ESTABLISHED, /* initial handshake completed */
+    RENEG_DETECTED /* renegotiation detected */
+} RENEG_STATE;
+
 typedef struct {
     jmp_buf err; /* exception handler needs to be 16-byte aligned on Itanium */
     SSL *ssl; /* SSL connnection */
@@ -420,6 +427,8 @@
     FD *ssl_rfd, *ssl_wfd; /* read and write SSL descriptors */
     int sock_bytes, ssl_bytes; /* bytes written to socket and SSL */
     s_poll_set *fds; /* file descriptors */
+
+    RENEG_STATE reneg_state; /* used to track renegotiation attempts */
 } CLI;
 
 CLI *alloc_client_session(SERVICE_OPTIONS *, int, int);
