commit 22646a075e75991b4e8f5d67171e45a6aead5b48
Author: Matt Caswell <matt@openssl.org>
Date:   Wed Sep 21 14:48:16 2016 +0100

    Don't allow too many consecutive warning alerts
    
    Certain warning alerts are ignored if they are received. This can mean that
    no progress will be made if one peer continually sends those warning alerts.
    Implement a count so that we abort the connection if we receive too many.
    
    Issue reported by Shi Lei.
    
    Reviewed-by: Rich Salz <rsalz@openssl.org>

Index: openssl-1.0.1i/ssl/d1_pkt.c
===================================================================
--- openssl-1.0.1i.orig/ssl/d1_pkt.c	2017-01-31 17:50:11.741143919 +0100
+++ openssl-1.0.1i/ssl/d1_pkt.c	2017-01-31 17:51:50.250698452 +0100
@@ -911,6 +911,13 @@ start:
 		goto start;
 		}
 
+    /*
+     * Reset the count of consecutive warning alerts if we've got a non-empty
+     * record that isn't an alert.
+     */
+    if (rr->type != SSL3_RT_ALERT && rr->length != 0)
+        s->cert->alert_count = 0;
+
 	/* we now have a packet which can be read and processed */
 
 	if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
@@ -1180,6 +1187,14 @@ start:
 		if (alert_level == 1) /* warning */
 			{
 			s->s3->warn_alert = alert_descr;
+
+	            	s->cert->alert_count++;
+       		     if (s->cert->alert_count == MAX_WARN_ALERT_COUNT) {
+	                al = SSL_AD_UNEXPECTED_MESSAGE;
+	                SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS);
+	                goto f_err;
+	            }
+
 			if (alert_descr == SSL_AD_CLOSE_NOTIFY)
 				{
 #ifndef OPENSSL_NO_SCTP
Index: openssl-1.0.1i/ssl/s3_pkt.c
===================================================================
--- openssl-1.0.1i.orig/ssl/s3_pkt.c	2017-01-31 17:50:11.349137734 +0100
+++ openssl-1.0.1i/ssl/s3_pkt.c	2017-01-31 17:50:11.781144551 +0100
@@ -1027,6 +1027,13 @@ start:
 		if (ret <= 0) return(ret);
 		}
 
+    	/*
+     	* Reset the count of consecutive warning alerts if we've got a non-empty
+     	* record that isn't an alert.
+     	*/
+    	if (rr->type != SSL3_RT_ALERT && rr->length != 0)
+        	s->cert->alert_count = 0;
+
 	/* we now have a packet which can be read and processed */
 
 	if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
@@ -1243,6 +1250,14 @@ start:
 		if (alert_level == 1) /* warning */
 			{
 			s->s3->warn_alert = alert_descr;
+
+            		s->cert->alert_count++;
+            		if (s->cert->alert_count == MAX_WARN_ALERT_COUNT) {
+                		al = SSL_AD_UNEXPECTED_MESSAGE;
+                		SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS);
+                		goto f_err;
+            		}
+
 			if (alert_descr == SSL_AD_CLOSE_NOTIFY)
 				{
 				s->shutdown |= SSL_RECEIVED_SHUTDOWN;
Index: openssl-1.0.1i/ssl/ssl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl.h	2017-01-31 17:50:11.737143856 +0100
+++ openssl-1.0.1i/ssl/ssl.h	2017-01-31 17:50:11.781144551 +0100
@@ -2559,6 +2559,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_WARN_ALERTS                       409
 #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
Index: openssl-1.0.1i/ssl/ssl_locl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_locl.h	2017-01-31 17:50:11.741143919 +0100
+++ openssl-1.0.1i/ssl/ssl_locl.h	2017-01-31 17:50:11.781144551 +0100
@@ -446,6 +446,7 @@
 #define SSL_C_EXPORT_PKEYLENGTH(c)	SSL_EXPORT_PKEYLENGTH((c)->algo_strength)
 
 
+#define MAX_WARN_ALERT_COUNT    5
 
 
 /* Mostly for SSLv3 */
@@ -521,6 +522,8 @@ typedef struct cert_st
 	CERT_PKEY pkeys[SSL_PKEY_NUM];
 
 	int references; /* >1 only if SSL_copy_session_id is used */
+	/* Count of the number of consecutive warning alerts received */
+	unsigned int alert_count;
 	} CERT;
 
 
