summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2014-09-25 12:00:39 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2014-09-25 12:32:41 +0200
commit65a3e7842902bc68bfee14f27a16be4152ded602 (patch)
tree2895daaea9783d475524e4d535112d3b6520a6c4
parent19eff0b4c1343e43c2c1f0893043d9a1d43b94af (diff)
downloadgnutls-65a3e7842902bc68bfee14f27a16be4152ded602.tar.gz
protect DTLS clients that don't handle GNUTLS_E_LARGE_PACKET from an infinite loop on handshake
Conflicts: lib/gnutls_int.h lib/gnutls_state.c
-rw-r--r--lib/gnutls_handshake.c6
-rw-r--r--lib/gnutls_int.h6
-rw-r--r--lib/gnutls_state.c1
3 files changed, 11 insertions, 2 deletions
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index bdabb4dad6..d542f21531 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -2544,8 +2544,12 @@ gnutls_handshake_set_timeout (gnutls_session_t session, unsigned int ms)
#define IMED_RET( str, ret, allow_alert) do { \
if (ret < 0) { \
/* EAGAIN and INTERRUPTED are always non-fatal */ \
- if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_LARGE_PACKET) \
+ if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) \
return ret; \
+ if (ret == GNUTLS_E_LARGE_PACKET && session->internals.handshake_large_loops < 16) { \
+ session->internals.handshake_large_loops++; \
+ return ret; \
+ } \
/* a warning alert might interrupt handshake */ \
if (allow_alert != 0 && ret==GNUTLS_E_WARNING_ALERT_RECEIVED) return ret; \
gnutls_assert(); \
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 41efec9030..98e9f4a815 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -955,7 +955,11 @@ typedef struct
recv_state_t recv_state; /* state of the receive function */
unsigned int sc_random_set:1;
-
+
+ /* In case of clients that don't handle GNUTLS_E_LARGE_PACKET, don't
+ * force them into an infinite loop */
+ unsigned handshake_large_loops;
+
/* If you add anything here, check _gnutls_handshake_internal_state_clear().
*/
} internals_st;
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index cfdf2df1f1..4f2bb7b29f 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -269,6 +269,7 @@ _gnutls_handshake_internal_state_init (gnutls_session_t session)
session->internals.dtls.hsk_read_seq = 0;
session->internals.dtls.hsk_write_seq = 0;
+ session->internals.handshake_large_loops = 0;
}
void