From 9f3a6ecb83e80cbfebc038a860d5ce63817e0098 Mon Sep 17 00:00:00 2001
From: Todd Short <tshort@akamai.com>
Date: Mon, 23 Mar 2015 18:00:08 -0400
Subject: [PATCH 10/26] RT3865 Add DISALLOW_RENEGOTIATION option

Add support to disallow renegotiation in openssl
The bit definition may need to change when pulled.

(cherry picked from commit 7bbf1ff458ef7464582257e6bcb4d28138b02255)

Conflicts:
	apps/s_server.c
	ssl/t1_lib.c
---
 apps/s_server.c                 | 8 ++++++++
 doc/ssl/SSL_CTX_set_options.pod | 4 ++++
 include/openssl/ssl.h           | 4 ++++
 ssl/record/rec_layer_s3.c       | 4 +++-
 ssl/t1_lib.c                    | 3 ++-
 5 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/apps/s_server.c b/apps/s_server.c
index 85502cf..c4a0e5d 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -814,6 +814,7 @@ typedef enum OPTION_choice {
     OPT_S_ENUM,
     OPT_V_ENUM,
     OPT_X_ENUM,
+    OPT_DISALLOW_RENEG,
     OPT_IPV4, OPT_IPV6
 } OPTION_CHOICE;
 
@@ -960,6 +961,7 @@ OPTIONS s_server_options[] = {
 #endif
     {"4", OPT_IPV4, '-', "Use IPv4 sockets"},
     {"6", OPT_IPV6, '-', "Use IPv6 sockets"},
+    {"disallow_renegotiation", OPT_DISALLOW_RENEG, '-', "Disallow use of any renegotiation"},
     {NULL}
 };
 
@@ -1015,6 +1017,7 @@ int s_server_main(int argc, char *argv[])
     char *srp_verifier_file = NULL;
 #endif
     int family = AF_UNSPEC;
+    int disallow_reneg = 0;
 
     local_argc = argc;
     local_argv = argv;
@@ -1424,6 +1427,9 @@ int s_server_main(int argc, char *argv[])
         case OPT_IPV6:
             family = AF_INET6;
             break;
+        case OPT_DISALLOW_RENEG:
+            disallow_reneg = 1;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -1622,6 +1628,8 @@ int s_server_main(int argc, char *argv[])
         BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
     }
     SSL_CTX_set_quiet_shutdown(ctx, 1);
+    if (disallow_reneg)
+        SSL_CTX_set_options(ctx, SSL_OP_DISALLOW_RENEGOTIATION);
     if (exc)
         ssl_ctx_set_excert(ctx, exc);
 
diff --git a/doc/ssl/SSL_CTX_set_options.pod b/doc/ssl/SSL_CTX_set_options.pod
index 84dde28..8faf5ab 100644
--- a/doc/ssl/SSL_CTX_set_options.pod
+++ b/doc/ssl/SSL_CTX_set_options.pod
@@ -204,6 +204,10 @@ Allow legacy insecure renegotiation between OpenSSL and unpatched servers
 B<only>: this option is currently set by default. See the
 B<SECURE RENEGOTIATION> section for more details.
 
+=item SSL_OP_DISALLOW_RENEGOTIATION
+
+Disable all renegotiation. Do not accept renegotiation requests.
+
 =back
 
 =head1 SECURE RENEGOTIATION
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index cec70b9..6fa3c4d 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -442,6 +442,10 @@ typedef int (*custom_ext_parse_cb) (SSL *s, unsigned int ext_type,
 
 # define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv3|\
         SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2)
+/*
+ * As server, disallow renegotiation (secure and legacy)
+ */
+# define SSL_OP_DISALLOW_RENEGOTIATION                   0x40000000L
 
 /*
  * These next two were never actually used for anything since SSLeay zap so
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index d308aa3..f14498d 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -1294,6 +1294,7 @@ int ssl3_readv_bytes(SSL *s, int type, const ssl_bucket *buckets,
          */
         goto start;
     }
+
     /*
      * If we are a server and get a client hello when renegotiation isn't
      * allowed send back a no renegotiation alert and carry on. WARNING:
@@ -1306,7 +1307,8 @@ int ssl3_readv_bytes(SSL *s, int type, const ssl_bucket *buckets,
         (s->rlayer.handshake_fragment_len >= 4) &&
         (s->rlayer.handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) &&
         (s->session != NULL) && (s->session->cipher != NULL) &&
-        !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
+        (!(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) ||
+         (s->options & SSL_OP_DISALLOW_RENEGOTIATION))) {
         SSL3_RECORD_set_length(rr, 0);
         ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
         goto start;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 402047a..b059c12 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1541,7 +1541,8 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
     if (ret >= limit)
         return NULL;            /* this really never occurs, but ... */
 
-    if (s->s3->send_connection_binding) {
+    if (!(s->options & SSL_OP_DISALLOW_RENEGOTIATION) &&
+        s->s3->send_connection_binding) {
         int el;
 
         if (!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) {
-- 
2.3.2 (Apple Git-55)

