File gnutls-CVE-2016-8610.patch of Package gnutls.5070

From 1ffb827e45721ef56982d0ffd5c5de52376c428e Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Fri, 14 Oct 2016 10:22:07 +0200
Subject: [PATCH] handshake: set a maximum number of warning messages that can be received per handshake

That is to avoid DoS due to the assymetry of cost of sending an alert vs the cost
of processing.
---
 lib/gnutls_int.h |  6 +++---
 lib/handshake.c  | 15 ++++++++++-----
 lib/state.c      |  2 +-
 3 files changed, 14 insertions(+), 9 deletions(-)

Index: gnutls-3.2.15/lib/gnutls_int.h
===================================================================
--- gnutls-3.2.15.orig/lib/gnutls_int.h	2014-05-22 22:33:39.000000000 +0200
+++ gnutls-3.2.15/lib/gnutls_int.h	2017-01-12 17:28:50.564202623 +0100
@@ -945,6 +945,10 @@ typedef struct {
 	/* DTLS session state */
 	dtls_st dtls;
 
+	/* Protect from infinite loops due to GNUTLS_E_LARGE_PACKET non-handling
+	 * or due to multiple alerts being received. */
+	unsigned handshake_suspicious_loops;
+
 	/* if set it means that the master key was set using
 	 * gnutls_session_set_master() rather than being negotiated. */
 	unsigned int premaster_set:1;
Index: gnutls-3.2.15/lib/gnutls_handshake.c
===================================================================
--- gnutls-3.2.15.orig/lib/gnutls_handshake.c	2014-05-29 19:00:09.000000000 +0200
+++ gnutls-3.2.15/lib/gnutls_handshake.c	2017-01-12 17:28:50.564202623 +0100
@@ -2591,8 +2591,17 @@ gnutls_handshake_set_timeout(gnutls_sess
 		/* EAGAIN and INTERRUPTED are always non-fatal */ \
 		if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) \
 			return ret; \
-                /* a warning alert might interrupt handshake */ \
-		if (allow_alert != 0 && ret==GNUTLS_E_WARNING_ALERT_RECEIVED) return ret; \
+		if (session->internals.handshake_suspicious_loops < 16) { \
+			if (ret == GNUTLS_E_LARGE_PACKET) { \
+				session->internals.handshake_suspicious_loops++; \
+				return ret; \
+			} \
+			/* a warning alert might interrupt handshake */ \
+			if (allow_alert != 0 && ret==GNUTLS_E_WARNING_ALERT_RECEIVED) { \
+				session->internals.handshake_suspicious_loops++; \
+				return ret; \
+			} \
+		} \
 		gnutls_assert(); \
 		ERR( str, ret); \
 		_gnutls_handshake_hash_buffers_clear(session); \
Index: gnutls-3.2.15/lib/gnutls_state.c
===================================================================
--- gnutls-3.2.15.orig/lib/gnutls_state.c	2014-02-18 09:36:44.000000000 +0100
+++ gnutls-3.2.15/lib/gnutls_state.c	2017-01-12 17:28:50.568202688 +0100
@@ -261,6 +261,7 @@ static void _gnutls_handshake_internal_s
 
 	session->internals.resumable = RESUME_TRUE;
 
+	session->internals.handshake_suspicious_loops = 0;
 	session->internals.dtls.hsk_read_seq = 0;
 	session->internals.dtls.hsk_write_seq = 0;
 }
openSUSE Build Service is sponsored by