diff options
author | Tim Rühsen <tim.ruehsen@gmx.de> | 2018-12-04 17:15:02 +0100 |
---|---|---|
committer | Tim Rühsen <tim.ruehsen@gmx.de> | 2018-12-06 16:13:00 +0100 |
commit | 3507f23cec212506da3c6836dbb159df4b41439f (patch) | |
tree | ff2f02ed31c2473c6fc795864ba98d758cce5c49 | |
parent | 493723ee38cd817a60f25bb0bea505c80b22407c (diff) | |
download | gnutls-3507f23cec212506da3c6836dbb159df4b41439f.tar.gz |
Fix gnutls_handshake_set_timeout() for values < 1000tmp-fix-timeout
handshake-timeout.c now tests for <1000ms timeout and for >=1000ms
timeout. The test duration decreased from 45s to 1.2s.
Signed-off-by: Tim Rühsen <tim.ruehsen@gmx.de>
-rw-r--r-- | lib/gnutls_int.h | 4 | ||||
-rw-r--r-- | lib/handshake.c | 19 | ||||
-rw-r--r-- | lib/handshake.h | 17 | ||||
-rw-r--r-- | lib/state.c | 3 | ||||
-rw-r--r-- | tests/handshake-timeout.c | 38 |
5 files changed, 55 insertions, 26 deletions
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 50a9208346..cccc3d1a97 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1303,7 +1303,9 @@ typedef struct { /* starting time of current handshake */ struct timespec handshake_start_time; - time_t handshake_endtime; /* end time in seconds */ + /* end time of current handshake */ + struct timespec handshake_endtime; + unsigned int handshake_timeout_ms; /* timeout in milliseconds */ unsigned int record_timeout_ms; /* timeout in milliseconds */ diff --git a/lib/handshake.c b/lib/handshake.c index 5080756c28..d83a51c9bb 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -2737,6 +2737,10 @@ int gnutls_handshake(gnutls_session_t session) } if (STATE == STATE0) { + unsigned int tmo_ms; + struct timespec *end; + struct timespec *start; + /* first call */ if (session->internals.priorities == NULL || session->internals.priorities->cs.size == 0) @@ -2752,10 +2756,17 @@ int gnutls_handshake(gnutls_session_t session) session->internals.handshake_in_progress = 1; session->internals.vc_status = -1; gnutls_gettime(&session->internals.handshake_start_time); - if (session->internals.handshake_timeout_ms && - session->internals.handshake_endtime == 0) - session->internals.handshake_endtime = session->internals.handshake_start_time.tv_sec + - session->internals.handshake_timeout_ms / 1000; + + tmo_ms = session->internals.handshake_timeout_ms; + end = &session->internals.handshake_endtime; + start = &session->internals.handshake_start_time; + + if (tmo_ms && end->tv_sec == 0 && end->tv_nsec == 0) { + end->tv_sec = + start->tv_sec + (start->tv_nsec + tmo_ms * 1000000LL) / 1000000000LL; + end->tv_nsec = + (start->tv_nsec + tmo_ms * 1000000LL) % 1000000000LL; + } } if (session->internals.recv_state == RECV_STATE_FALSE_START) { diff --git a/lib/handshake.h b/lib/handshake.h index a82263aad1..11c310f33c 100644 --- a/lib/handshake.h +++ b/lib/handshake.h @@ -112,16 +112,23 @@ int _gnutls13_handshake_hash_buffers_synth(gnutls_session_t session, #define FAGAIN(target) (FINAL_STATE==target?1:0) #define AGAIN2(state, target) (state==target?1:0) +/* return the remaining time in ms */ inline static int handshake_remaining_time(gnutls_session_t session) { - if (session->internals.handshake_endtime) { + struct timespec *end = &session->internals.handshake_endtime; + + if (end->tv_sec || end->tv_nsec) { struct timespec now; gnutls_gettime(&now); - if (now.tv_sec < session->internals.handshake_endtime) - return (session->internals.handshake_endtime - - now.tv_sec) * 1000; - else + if (now.tv_sec < end->tv_sec || + (now.tv_sec == end->tv_sec && now.tv_nsec < end->tv_nsec)) + { + long long now_ms = now.tv_sec * 1000LL + now.tv_nsec / 1000000; + long long end_ms = end->tv_sec * 1000LL + end->tv_nsec / 1000000; + + return end_ms - now_ms; + } else return gnutls_assert_val(GNUTLS_E_TIMEDOUT); } return 0; diff --git a/lib/state.c b/lib/state.c index a60544737a..392183c95f 100644 --- a/lib/state.c +++ b/lib/state.c @@ -430,7 +430,8 @@ void _gnutls_handshake_internal_state_clear(gnutls_session_t session) _gnutls_epoch_gc(session); - session->internals.handshake_endtime = 0; + session->internals.handshake_endtime.tv_sec = 0; + session->internals.handshake_endtime.tv_nsec = 0; session->internals.handshake_in_progress = 0; session->internals.tfo.connect_addrlen = 0; diff --git a/tests/handshake-timeout.c b/tests/handshake-timeout.c index 52c21f69b4..92a398cce0 100644 --- a/tests/handshake-timeout.c +++ b/tests/handshake-timeout.c @@ -26,6 +26,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> #if defined(_WIN32) @@ -61,7 +62,7 @@ static void client_log_func(int level, const char *str) fprintf(stderr, "client|<%d>| %s", level, str); } -static void client(int fd, int wait) +static void client(int fd, int tmo_ms) { int ret; gnutls_anon_client_credentials_t anoncred; @@ -79,7 +80,7 @@ static void client(int fd, int wait) /* Initialize TLS session */ gnutls_init(&session, GNUTLS_CLIENT); - gnutls_handshake_set_timeout(session, 20 * 1000); + gnutls_handshake_set_timeout(session, tmo_ms); /* Use default priorities */ gnutls_priority_set_direct(session, "NORMAL:+ANON-ECDH:-VERS-ALL:+VERS-TLS1.2", NULL); @@ -102,7 +103,7 @@ static void client(int fd, int wait) gnutls_global_deinit(); if (ret < 0) { - if (ret != GNUTLS_E_TIMEDOUT || wait == 0) { + if (ret != GNUTLS_E_TIMEDOUT || tmo_ms == 0) { if (debug) fail("client: unexpected error: %s\n", gnutls_strerror(ret)); @@ -110,19 +111,19 @@ static void client(int fd, int wait) } if (debug) success("client: expected timeout occurred\n"); - return; } else { - if (wait != 0) { + if (tmo_ms != 0) { fail("client: handshake was completed unexpectedly\n"); gnutls_perror(ret); exit(1); } } + shutdown(fd, SHUT_RDWR); return; } -static void server(int fd, int wait) +static void server(int fd, int tmo_ms) { int ret; gnutls_session_t session; @@ -150,8 +151,12 @@ static void server(int fd, int wait) gnutls_transport_set_int(session, fd); - if (wait) { - sec_sleep(25); + if (tmo_ms) { + char buf[32]; + + // read until client closes connection + while (read(fd, buf, sizeof(buf)) > 0) + ; } else { do { ret = gnutls_handshake(session); @@ -167,14 +172,14 @@ static void server(int fd, int wait) gnutls_global_deinit(); } -static void start(int wait_flag) +static void start(int tmo_ms) { int fd[2]; int ret; pid_t child; - if (debug && wait_flag) - fprintf(stderr, "\nWill test timeout\n"); + if (debug && tmo_ms) + fprintf(stderr, "\nWill test timeout %dms\n", tmo_ms); ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); if (ret < 0) { @@ -193,14 +198,14 @@ static void start(int wait_flag) int status = 0; /* parent */ close(fd[1]); - server(fd[0], wait_flag); + server(fd[0], tmo_ms); close(fd[0]); wait(&status); check_wait_status(status); } else { close(fd[0]); - client(fd[1], wait_flag); + client(fd[1], tmo_ms); close(fd[1]); exit(0); } @@ -219,8 +224,11 @@ void doit(void) /* make sure that normal handshake occurs */ start(0); - /* check the handshake with an expected timeout */ - start(1); + /* check the handshake with a 100ms timeout */ + start(100); + + /* check the handshake with a 1000ms timeout */ + start(1000); } #endif /* _WIN32 */ |