only send heartbeat extension from server if client sent one
authorDr. Stephen Henson <steve@openssl.org>
Tue, 3 Jan 2012 22:03:20 +0000 (22:03 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 3 Jan 2012 22:03:20 +0000 (22:03 +0000)
ssl/s3_srvr.c
ssl/ssl.h
ssl/ssl3.h
ssl/ssl_err.c
ssl/t1_lib.c

index 9e73d62..587dc86 100644 (file)
@@ -297,6 +297,7 @@ int ssl3_accept(SSL *s)
                                }
 
                        s->init_num=0;
+                       s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE;
 
                        if (s->state != SSL_ST_RENEGOTIATE)
                                {
@@ -871,6 +872,14 @@ int ssl3_check_client_hello(SSL *s)
        int ok;
        long n;
 
+       /* We only allow the client to restart the handshake once per
+        * negotiation. */
+       if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE)
+               {
+               SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, SSL_R_MULTIPLE_SGC_RESTARTS);
+               return -1;
+               }
+
        /* this function is called when we really expect a Certificate message,
         * so permit appropriate message length */
        n=s->method->ssl_get_message(s,
@@ -899,6 +908,7 @@ int ssl3_check_client_hello(SSL *s)
                        s->s3->tmp.ecdh = NULL;
                        }
 #endif
+               s->s3->flags |= SSL3_FLAGS_SGC_RESTART_DONE;
                return 2;
                }
        return 1;
index 4bf477a..9ce2684 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2133,6 +2133,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL3_CALLBACK_CTRL                        233
 #define SSL_F_SSL3_CHANGE_CIPHER_STATE                  129
 #define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM             130
+#define SSL_F_SSL3_CHECK_CLIENT_HELLO                   315
 #define SSL_F_SSL3_CLIENT_HELLO                                 131
 #define SSL_F_SSL3_CONNECT                              132
 #define SSL_F_SSL3_CTRL                                         213
@@ -2412,6 +2413,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_MISSING_TMP_RSA_KEY                       172
 #define SSL_R_MISSING_TMP_RSA_PKEY                      173
 #define SSL_R_MISSING_VERIFY_MESSAGE                    174
+#define SSL_R_MULTIPLE_SGC_RESTARTS                     370
 #define SSL_R_NON_SSLV2_INITIAL_PACKET                  175
 #define SSL_R_NO_CERTIFICATES_RETURNED                  176
 #define SSL_R_NO_CERTIFICATE_ASSIGNED                   177
index 93f9ead..68a66e2 100644 (file)
@@ -389,6 +389,17 @@ typedef struct ssl3_buffer_st
 #define TLS1_FLAGS_SKIP_CERT_VERIFY            0x0010
 #define TLS1_FLAGS_KEEP_HANDSHAKE              0x0020
 
+/* SSL3_FLAGS_SGC_RESTART_DONE is set when we
+ * restart a handshake because of MS SGC and so prevents us
+ * from restarting the handshake in a loop. It's reset on a
+ * renegotiation, so effectively limits the client to one restart
+ * per negotiation. This limits the possibility of a DDoS
+ * attack where the client handshakes in a loop using SGC to
+ * restart. Servers which permit renegotiation can still be
+ * effected, but we can't prevent that.
+ */
+#define SSL3_FLAGS_SGC_RESTART_DONE            0x0040
+
 #ifndef OPENSSL_NO_SSL_INTERN
 
 typedef struct ssl3_state_st
index 0c3838a..4eb2e44 100644 (file)
@@ -138,6 +138,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL),   "SSL3_CALLBACK_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE),     "SSL3_CHANGE_CIPHER_STATE"},
 {ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM),        "SSL3_CHECK_CERT_AND_ALGORITHM"},
+{ERR_FUNC(SSL_F_SSL3_CHECK_CLIENT_HELLO),      "SSL3_CHECK_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO),    "SSL3_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_CONNECT), "SSL3_CONNECT"},
 {ERR_FUNC(SSL_F_SSL3_CTRL),    "SSL3_CTRL"},
@@ -420,6 +421,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_MISSING_TMP_RSA_KEY)   ,"missing tmp rsa key"},
 {ERR_REASON(SSL_R_MISSING_TMP_RSA_PKEY)  ,"missing tmp rsa pkey"},
 {ERR_REASON(SSL_R_MISSING_VERIFY_MESSAGE),"missing verify message"},
+{ERR_REASON(SSL_R_MULTIPLE_SGC_RESTARTS) ,"multiple sgc restarts"},
 {ERR_REASON(SSL_R_NON_SSLV2_INITIAL_PACKET),"non sslv2 initial packet"},
 {ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED),"no certificates returned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED),"no certificate assigned"},
index c5c805c..e38bd9f 100644 (file)
@@ -812,17 +812,20 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                }
 
 #ifndef OPENSSL_NO_HEARTBEATS
-       /* Add Heartbeat extension */
-       s2n(TLSEXT_TYPE_heartbeat,ret);
-       s2n(1,ret);
-       /* Set mode:
-        * 1: peer may send requests
-        * 2: peer not allowed to send requests
-        */
-       if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
-               *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
-       else
-               *(ret++) = SSL_TLSEXT_HB_ENABLED;
+       /* Add Heartbeat extension if we've received one */
+       if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED)
+               {
+               s2n(TLSEXT_TYPE_heartbeat,ret);
+               s2n(1,ret);
+               /* Set mode:
+                * 1: peer may send requests
+                * 2: peer not allowed to send requests
+                */
+               if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
+                       *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
+               else
+                       *(ret++) = SSL_TLSEXT_HB_ENABLED;
+               }
 #endif
 
 #ifndef OPENSSL_NO_NEXTPROTONEG