From 42a8bb3bdad73f13425ae18a41addbbc04496101 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 25 Sep 2014 12:00:39 +0200 Subject: [PATCH] protect DTLS clients that don't handle GNUTLS_E_LARGE_PACKET from an infinite loop on handshake --- lib/gnutls_handshake.c | 6 +++++- lib/gnutls_int.h | 3 +++ lib/gnutls_state.c | 1 + 3 files changed, 9 insertions(+), 1 deletions(-) diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 759c67e..8b73267 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -2601,8 +2601,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 58ffdf1..deca5fe 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -961,6 +961,9 @@ typedef struct { /* DTLS session state */ dtls_st dtls; + /* 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 set it means that the master key was set using * gnutls_session_set_master() rather than being negotiated. */ diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 121ad5c..6165531 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -261,6 +261,7 @@ static void _gnutls_handshake_internal_state_init(gnutls_session_t session) session->internals.resumable = RESUME_TRUE; + session->internals.handshake_large_loops = 0; session->internals.dtls.hsk_read_seq = 0; session->internals.dtls.hsk_write_seq = 0; } -- 1.7.1