diff --git a/src/tlslib.c b/src/tlslib.c index 88ff419a..44ba1e3b 100644 --- a/src/tlslib.c +++ b/src/tlslib.c @@ -116,7 +116,7 @@ ssize_t tls_recv(gnutls_session_t session, void *data, size_t data_size) do { ret = gnutls_record_recv(session, data, data_size); - } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); + } while (ret < 0 && (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN)); return ret; } diff --git a/src/worker-vpn.c b/src/worker-vpn.c index 977cae1a..f9f2aff5 100644 --- a/src/worker-vpn.c +++ b/src/worker-vpn.c @@ -1499,7 +1499,7 @@ static int connect_handler(worker_st * ws) if (FD_ISSET(ws->conn_fd, &rfds) || tls_pending != 0) { ret = - gnutls_record_recv(ws->session, ws->buffer, + tls_recv(ws->session, ws->buffer, ws->buffer_size); oclog(ws, LOG_DEBUG, "received %d byte(s) (TLS)", ret); @@ -1534,6 +1534,15 @@ static int connect_handler(worker_st * ws) } } } + + if (ret == GNUTLS_E_REHANDSHAKE) { + /* rekey? */ + oclog(ws, LOG_INFO, "client requested rehandshake on TLS channel"); + do { + ret = gnutls_handshake(ws->session); + } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); + GNUTLS_FATAL_ERR(ret); + } } if (ws->udp_state > UP_WAIT_FD @@ -1543,7 +1552,7 @@ static int connect_handler(worker_st * ws) case UP_ACTIVE: case UP_INACTIVE: ret = - gnutls_record_recv(ws->dtls_session, + tls_recv(ws->dtls_session, ws->buffer, ws->buffer_size); oclog(ws, LOG_DEBUG, @@ -1573,6 +1582,15 @@ static int connect_handler(worker_st * ws) oclog(ws, LOG_DEBUG, "no data received (%d)", ret); + if (ret == GNUTLS_E_REHANDSHAKE) { + /* rekey? */ + oclog(ws, LOG_INFO, "client requested rehandshake on DTLS channel"); + do { + ret = gnutls_handshake(ws->dtls_session); + } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); + GNUTLS_FATAL_ERR(ret); + } + udp_recv_time = now; break; case UP_SETUP: