From: Nikos Mavrogiannopoulos Date: Thu, 20 Sep 2012 21:36:00 +0000 (+0200) Subject: updates in heartbeat support X-Git-Tag: gnutls_3_1_2~36 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2b997db624a800b6d74bdd9ccbf46cc362495d84;p=thirdparty%2Fgnutls.git updates in heartbeat support --- diff --git a/lib/ext/heartbeat.c b/lib/ext/heartbeat.c index d27b94f1bd..88dd989687 100644 --- a/lib/ext/heartbeat.c +++ b/lib/ext/heartbeat.c @@ -96,13 +96,13 @@ gnutls_heartbeat_allowed (gnutls_session_t session, unsigned int type) static int heartbeat_allow_recv (gnutls_session_t session) { - return gnutls_heartbeat_allowed(session, 0); + return gnutls_heartbeat_allowed(session, GNUTLS_HB_PEER_ALLOWED_TO_SEND); } static int heartbeat_allow_send (gnutls_session_t session) { - return gnutls_heartbeat_allowed(session, 1); + return gnutls_heartbeat_allowed(session, GNUTLS_HB_LOCAL_ALLOWED_TO_SEND); } /*- @@ -148,7 +148,7 @@ heartbeat_send_data (gnutls_session_t session, const void *data, _gnutls_record_log ("REC[%p]: HB sent: %d\n", session, ret); _gnutls_buffer_clear (&response); - return gnutls_assert_val (ret); + return ret; } /** @@ -172,13 +172,13 @@ gnutls_heartbeat_ping (gnutls_session_t session, size_t data_size, unsigned int max_tries, unsigned int flags) { int ret; - unsigned int retries = 0; + unsigned int retries = 1; if (data_size > MAX_HEARTBEAT_LENGTH) return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET_LENGTH); if (!heartbeat_allow_send (session)) - return GNUTLS_E_INVALID_REQUEST; + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); switch(session->internals.hb_state) { @@ -195,8 +195,8 @@ gnutls_heartbeat_ping (gnutls_session_t session, size_t data_size, ret = _gnutls_rnd (GNUTLS_RND_NONCE, session->internals.hb_local_data.data, data_size); if (ret < 0) return gnutls_assert_val(ret); - session->internals.hb_local_data.length = data_size; + session->internals.hb_local_data.length = data_size; session->internals.hb_state = SHB_SEND2; case SHB_SEND2: session->internals.hb_timeout = HEARTBEAT_TIMEOUT; @@ -317,7 +317,7 @@ _gnutls_heartbeat_handle (gnutls_session_t session, mbuffer_st * bufel) memcpy(session->internals.hb_remote_data.data, msg+3, hb_len); session->internals.hb_remote_data.length = hb_len; - return GNUTLS_E_HEARTBEAT_PING_RECEIVED; + return gnutls_assert_val(GNUTLS_E_HEARTBEAT_PING_RECEIVED); case HEARTBEAT_RESPONSE: @@ -335,7 +335,7 @@ _gnutls_heartbeat_handle (gnutls_session_t session, mbuffer_st * bufel) _gnutls_buffer_reset (&session->internals.hb_local_data); - return GNUTLS_E_HEARTBEAT_PONG_RECEIVED; + return gnutls_assert_val(GNUTLS_E_HEARTBEAT_PONG_RECEIVED); default: _gnutls_record_log ("REC[%p]: HB: received unknown type %u\n", diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index 9f91f3d15c..79b4904030 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -508,7 +508,6 @@ check_buffers (gnutls_session_t session, content_type_t type, { if ((type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE || - type == GNUTLS_HEARTBEAT || type == GNUTLS_CHANGE_CIPHER_SPEC) && _gnutls_record_buffer_get_size (session) > 0) { @@ -591,7 +590,6 @@ record_add_to_buffers (gnutls_session_t session, if ((recv->type == type) && (type == GNUTLS_APPLICATION_DATA || type == GNUTLS_CHANGE_CIPHER_SPEC || - type == GNUTLS_HEARTBEAT || type == GNUTLS_HANDSHAKE)) { _gnutls_record_buffer_put (session, type, seq, bufel); @@ -1161,7 +1159,7 @@ cleanup: return ret; recv_error: - if (ret < 0 && gnutls_error_is_fatal (ret) == 0) + if (ret < 0 && (gnutls_error_is_fatal (ret) == 0 || ret == GNUTLS_E_TIMEDOUT)) return ret; if (IS_DTLS(session)) @@ -1198,10 +1196,8 @@ _gnutls_recv_int (gnutls_session_t session, content_type_t type, { int ret; - if (type != GNUTLS_ALERT && (data_size == 0 || data == NULL)) - { - return GNUTLS_E_INVALID_REQUEST; - } + if ((type != GNUTLS_ALERT && type != GNUTLS_HEARTBEAT) && (data_size == 0 || data == NULL)) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); if (session->internals.read_eof != 0) { diff --git a/src/common.c b/src/common.c index 4b21e22c7a..2bccedc8c6 100644 --- a/src/common.c +++ b/src/common.c @@ -1042,6 +1042,8 @@ print_list (const char *priorities, int verbose) int check_command(gnutls_session_t session, const char* str) { size_t len = strnlen(str, 128); + int ret; + fprintf (stderr, "*** Processing %zu bytes command: %s\n", len, str); if (len > 2 && str[0] == str[1] && str[0] == '*') { @@ -1051,7 +1053,19 @@ int check_command(gnutls_session_t session, const char* str) gnutls_rehandshake (session); return 1; } else if (strncmp(str, "**HEARTBEAT**", sizeof ("**HEARTBEAT**") - 1) == 0) { - gnutls_heartbeat_ping_rnd (session); + ret = gnutls_heartbeat_ping (session, 300, 5, GNUTLS_HEARTBEAT_WAIT); + if (ret < 0) + { + if (ret == GNUTLS_E_INVALID_REQUEST) + { + fprintf(stderr, "No heartbeat in this session\n"); + } + else + { + fprintf(stderr, "ping: %s\n", gnutls_strerror(ret)); + exit(1); + } + } return 2; } } diff --git a/src/serv.c b/src/serv.c index b1e5a4992a..d3dc35043e 100644 --- a/src/serv.c +++ b/src/serv.c @@ -1342,6 +1342,10 @@ tcp_server (const char *name, int port) { r = gnutls_record_recv (j->tls_session, buf, MIN (1024, SMALL_READ_TEST)); + if (r == GNUTLS_E_HEARTBEAT_PING_RECEIVED) + { + gnutls_heartbeat_pong(j->tls_session, 0); + } if (r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) { /* do nothing */ @@ -1376,10 +1380,7 @@ tcp_server (const char *name, int port) { if (r < 0) { - if (GNUTLS_E_HEARTBEAT_PONG_FAILED == r) - fprintf (stderr, - "HeartBeat pong failed, ping dropped\n"); - else if (r != GNUTLS_E_UNEXPECTED_PACKET_LENGTH) + if (r != GNUTLS_E_UNEXPECTED_PACKET_LENGTH) { j->http_state = HTTP_STATE_CLOSING; check_alert (j->tls_session, r); diff --git a/src/socket.c b/src/socket.c index b33f6bc58b..c50488528d 100644 --- a/src/socket.c +++ b/src/socket.c @@ -50,15 +50,16 @@ socket_recv (const socket_st * socket, void *buffer, int buffer_size) int ret; if (socket->secure) - do - { - ret = gnutls_record_recv (socket->session, buffer, buffer_size); - if (GNUTLS_E_HEARTBEAT_PONG_FAILED == ret) { - fprintf (stderr, "HeartBeat pong failed, ping dropped\n"); - ret = GNUTLS_E_AGAIN; - } - } - while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); + { + do + { + ret = gnutls_record_recv (socket->session, buffer, buffer_size); + if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED) + gnutls_heartbeat_pong(socket->session, 0); + } + while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED); + + } else do { diff --git a/src/udp-serv.c b/src/udp-serv.c index 478435fa4b..08d2677a88 100644 --- a/src/udp-serv.c +++ b/src/udp-serv.c @@ -144,9 +144,13 @@ void udp_server(const char* name, int port, int mtu) for(;;) { - do { - ret = gnutls_record_recv_seq(session, buffer, MAX_BUFFER, sequence); - } while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); + do + { + ret = gnutls_record_recv_seq(session, buffer, MAX_BUFFER, sequence); + if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED) + gnutls_heartbeat_pong(session, 0); + } + while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED); if (ret == GNUTLS_E_REHANDSHAKE) {