summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2012-12-27 14:39:25 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2012-12-28 12:54:22 +0200
commitac856dc00b9a4344c444d036ab3595c017f78d7d (patch)
tree7371f7002b00524ea16fc3dd3f5a424d2528ad87
parentbec3b3932c30a5bd220af737b889e7844ae9f4bd (diff)
downloadgnutls-ac856dc00b9a4344c444d036ab3595c017f78d7d.tar.gz
Improvements in heartbeat handling.
-rw-r--r--NEWS3
-rw-r--r--lib/ext/heartbeat.c20
2 files changed, 20 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index 0fe0e9e7dc..d5ee736138 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,9 @@ Patterson and Nadhem Alfardan.
** libgnutls: gnutls_x509_crt_get_policy() allows for a list of zero
policy qualifiers.
+** libgnutls: Ignore heartbeat messages when received out-of-order,
+instead of issuing an error.
+
** libgnutls-guile: Fixed parallel compilation issue.
** gnutls-cli: It will try to connect to all possible returned addresses
diff --git a/lib/ext/heartbeat.c b/lib/ext/heartbeat.c
index 89d01202b7..9659c383d2 100644
--- a/lib/ext/heartbeat.c
+++ b/lib/ext/heartbeat.c
@@ -188,6 +188,12 @@ gnutls_heartbeat_ping (gnutls_session_t session, size_t data_size,
if (!heartbeat_allow_send (session))
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ /* resume previous call if interrupted */
+ if (session->internals.record_send_buffer.byte_length > 0 &&
+ session->internals.record_send_buffer.head != NULL &&
+ session->internals.record_send_buffer.head->type == GNUTLS_HEARTBEAT)
+ return _gnutls_io_write_flush (session);
+
switch(session->internals.hb_state)
{
case SHB_SEND1:
@@ -287,6 +293,11 @@ gnutls_heartbeat_pong (gnutls_session_t session, unsigned int flags)
{
int ret;
+ if (session->internals.record_send_buffer.byte_length > 0 &&
+ session->internals.record_send_buffer.head != NULL &&
+ session->internals.record_send_buffer.head->type == GNUTLS_HEARTBEAT)
+ return _gnutls_io_write_flush (session);
+
if (session->internals.hb_remote_data.length == 0)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
@@ -324,7 +335,7 @@ _gnutls_heartbeat_handle (gnutls_session_t session, mbuffer_st * bufel)
hb_len = _gnutls_read_uint16 (msg + 1);
if (hb_len > len - 3)
- return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET);
+ return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
switch (msg[0])
{
@@ -352,10 +363,13 @@ _gnutls_heartbeat_handle (gnutls_session_t session, mbuffer_st * bufel)
if (hb_len > 0 && memcmp (msg + 3, session->internals.hb_local_data.data,
hb_len) != 0)
{
- _gnutls_record_log ("REC[%p]: HB: %s - received\n", session,
+ _gnutls_record_log ("REC[%p]: unexpected HB: %s - received\n", session,
_gnutls_bin2hex (msg + 3, hb_len, pr,
sizeof (pr), NULL));
- return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET);
+ if (IS_DTLS(session))
+ return gnutls_assert_val( GNUTLS_E_AGAIN); /* ignore it */
+ else
+ return gnutls_assert_val( GNUTLS_E_UNEXPECTED_PACKET);
}
_gnutls_buffer_reset (&session->internals.hb_local_data);