From 42d7e1ff372f9e7e0fed9fe413e34de4b202987a Mon Sep 17 00:00:00 2001
From: Adam Langley <agl@chromium.org>
Date: Wed, 20 Feb 2013 12:42:09 -0500
Subject: [PATCH 04/11] empty_record_limit

Limit the number of empty records that will be processed consecutively
in order to prevent ssl3_get_record from never returning.

Reported by "oftc_must_be_destroyed" and George Kadianakis.
---
 ssl/s3_pkt.c  | 19 ++++++++++++++++++-
 ssl/ssl.h     |  1 +
 ssl/ssl_err.c |  1 +
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 8056291..e589409 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -272,6 +272,12 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
 	return(n);
 	}
 
+/* MAX_EMPTY_RECORDS defines the number of consecutive, empty records that will
+ * be processed per call to ssl3_get_record. Without this limit an attacker
+ * could send empty records at a faster rate than we can process and cause
+ * ssl3_get_record to loop forever. */
+#define MAX_EMPTY_RECORDS 32
+
 /* Call this to get a new input record.
  * It will return <= 0 if more data is needed, normally due to an error
  * or non-blocking IO.
@@ -292,6 +298,7 @@ static int ssl3_get_record(SSL *s)
 	short version;
 	unsigned mac_size;
 	size_t extra;
+	unsigned empty_record_count = 0;
 
 	rr= &(s->s3->rrec);
 	sess=s->session;
@@ -522,7 +529,17 @@ printf("\n");
 	s->packet_length=0;
 
 	/* just read a 0 length packet */
-	if (rr->length == 0) goto again;
+	if (rr->length == 0)
+		{
+		empty_record_count++;
+		if (empty_record_count > MAX_EMPTY_RECORDS)
+			{
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_TOO_MANY_EMPTY_FRAGMENTS);
+			goto f_err;
+			}
+		goto again;
+		}
 
 #if 0
 fprintf(stderr, "Ultimate Record type=%d, Length=%d\n", rr->type, rr->length);
diff --git a/ssl/ssl.h b/ssl/ssl.h
index e14a8d4..938f65a 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2820,6 +2820,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST		 157
 #define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
 #define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 234
+#define SSL_R_TOO_MANY_EMPTY_FRAGMENTS			 388
 #define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 235
 #define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 236
 #define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS		 313
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index d8b4d70..fd571a3 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -575,6 +575,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"},
 {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"},
 {ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),"tls rsa encrypted value length is wrong"},
+{ERR_REASON(SSL_R_TOO_MANY_EMPTY_FRAGMENTS),"too many empty fragments"},
 {ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER),"tried to use unsupported cipher"},
 {ERR_REASON(SSL_R_UNABLE_TO_DECODE_DH_CERTS),"unable to decode dh certs"},
 {ERR_REASON(SSL_R_UNABLE_TO_DECODE_ECDH_CERTS),"unable to decode ecdh certs"},
-- 
1.8.2.1

