|
|
873a72 |
From 42a8bb3bdad73f13425ae18a41addbbc04496101 Mon Sep 17 00:00:00 2001
|
|
|
873a72 |
From: Nikos Mavrogiannopoulos <nmav@gnutls.org>
|
|
|
873a72 |
Date: Thu, 25 Sep 2014 12:00:39 +0200
|
|
|
873a72 |
Subject: [PATCH] protect DTLS clients that don't handle GNUTLS_E_LARGE_PACKET from an infinite loop on handshake
|
|
|
873a72 |
|
|
|
873a72 |
---
|
|
|
873a72 |
lib/gnutls_handshake.c | 6 +++++-
|
|
|
873a72 |
lib/gnutls_int.h | 3 +++
|
|
|
873a72 |
lib/gnutls_state.c | 1 +
|
|
|
873a72 |
3 files changed, 9 insertions(+), 1 deletions(-)
|
|
|
873a72 |
|
|
|
873a72 |
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
|
|
|
873a72 |
index 759c67e..8b73267 100644
|
|
|
873a72 |
--- a/lib/gnutls_handshake.c
|
|
|
873a72 |
+++ b/lib/gnutls_handshake.c
|
|
|
873a72 |
@@ -2601,8 +2601,12 @@ gnutls_handshake_set_timeout(gnutls_session_t session, unsigned int ms)
|
|
|
873a72 |
#define IMED_RET( str, ret, allow_alert) do { \
|
|
|
873a72 |
if (ret < 0) { \
|
|
|
873a72 |
/* EAGAIN and INTERRUPTED are always non-fatal */ \
|
|
|
873a72 |
- if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_LARGE_PACKET) \
|
|
|
873a72 |
+ if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) \
|
|
|
873a72 |
return ret; \
|
|
|
873a72 |
+ if (ret == GNUTLS_E_LARGE_PACKET && session->internals.handshake_large_loops < 16) { \
|
|
|
873a72 |
+ session->internals.handshake_large_loops++; \
|
|
|
873a72 |
+ return ret; \
|
|
|
873a72 |
+ } \
|
|
|
873a72 |
/* a warning alert might interrupt handshake */ \
|
|
|
873a72 |
if (allow_alert != 0 && ret==GNUTLS_E_WARNING_ALERT_RECEIVED) return ret; \
|
|
|
873a72 |
gnutls_assert(); \
|
|
|
873a72 |
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
|
|
|
873a72 |
index 58ffdf1..deca5fe 100644
|
|
|
873a72 |
--- a/lib/gnutls_int.h
|
|
|
873a72 |
+++ b/lib/gnutls_int.h
|
|
|
873a72 |
@@ -961,6 +961,9 @@ typedef struct {
|
|
|
873a72 |
|
|
|
873a72 |
/* DTLS session state */
|
|
|
873a72 |
dtls_st dtls;
|
|
|
873a72 |
+ /* In case of clients that don't handle GNUTLS_E_LARGE_PACKET, don't
|
|
|
873a72 |
+ * force them into an infinite loop */
|
|
|
873a72 |
+ unsigned handshake_large_loops;
|
|
|
873a72 |
|
|
|
873a72 |
/* if set it means that the master key was set using
|
|
|
873a72 |
* gnutls_session_set_master() rather than being negotiated. */
|
|
|
873a72 |
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
|
|
|
873a72 |
index 121ad5c..6165531 100644
|
|
|
873a72 |
--- a/lib/gnutls_state.c
|
|
|
873a72 |
+++ b/lib/gnutls_state.c
|
|
|
873a72 |
@@ -261,6 +261,7 @@ static void _gnutls_handshake_internal_state_init(gnutls_session_t session)
|
|
|
873a72 |
|
|
|
873a72 |
session->internals.resumable = RESUME_TRUE;
|
|
|
873a72 |
|
|
|
873a72 |
+ session->internals.handshake_large_loops = 0;
|
|
|
873a72 |
session->internals.dtls.hsk_read_seq = 0;
|
|
|
873a72 |
session->internals.dtls.hsk_write_seq = 0;
|
|
|
873a72 |
}
|
|
|
873a72 |
--
|
|
|
873a72 |
1.7.1
|
|
|
873a72 |
|