diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2014-09-25 12:00:39 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2014-09-25 12:32:41 +0200 |
commit | 65a3e7842902bc68bfee14f27a16be4152ded602 (patch) | |
tree | 2895daaea9783d475524e4d535112d3b6520a6c4 | |
parent | 19eff0b4c1343e43c2c1f0893043d9a1d43b94af (diff) | |
download | gnutls-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.c | 6 | ||||
-rw-r--r-- | lib/gnutls_int.h | 6 | ||||
-rw-r--r-- | lib/gnutls_state.c | 1 |
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 |