diff --git a/cstp.c b/cstp.c index fde14e63..6234a49f 100644 --- a/cstp.c +++ b/cstp.c @@ -889,7 +889,16 @@ int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout) /* Not that this will ever happen; we don't even process the setting when we're asked for it. */ vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n")); - goto do_reconnect; + if (vpninfo->ssl_times.rekey_method == REKEY_TUNNEL) + goto do_reconnect; + else if (vpninfo->ssl_times.rekey_method == REKEY_SSL) { + ret = cstp_handshake(vpninfo, 0); + if (ret) { + /* if we failed rehandshake try establishing a new-tunnel instead of failing */ + vpn_progress(vpninfo, PRG_ERR, _("Rehandshake failed; attempting new-tunnel\n")); + goto do_reconnect; + } + } break; case KA_DPD_DEAD: diff --git a/gnutls.c b/gnutls.c index de473b0d..3abe7b55 100644 --- a/gnutls.c +++ b/gnutls.c @@ -1949,6 +1949,24 @@ int openconnect_open_https(struct openconnect_info *vpninfo) vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"), vpninfo->hostname); + + err = cstp_handshake(vpninfo, 1); + if (err) + return err; + + vpninfo->ssl_fd = ssl_sock; + + + return 0; +} + +int cstp_handshake(struct openconnect_info *vpninfo, unsigned init) +{ + int err; + int ssl_sock = -1; + + ssl_sock = (long)gnutls_transport_get_ptr(vpninfo->https_sess); + while ((err = gnutls_handshake(vpninfo->https_sess))) { if (err == GNUTLS_E_AGAIN) { fd_set rd_set, wr_set; @@ -1986,10 +2004,13 @@ int openconnect_open_https(struct openconnect_info *vpninfo) } } - vpninfo->ssl_fd = ssl_sock; - - vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"), - vpninfo->hostname); + if (init) { + vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"), + vpninfo->hostname); + } else { + vpn_progress(vpninfo, PRG_INFO, _("Renegotiated SSL on %s\n"), + vpninfo->hostname); + } return 0; } diff --git a/mainloop.c b/mainloop.c index eca89190..9fc5ab8e 100644 --- a/mainloop.c +++ b/mainloop.c @@ -263,8 +263,10 @@ int keepalive_action(struct keepalive_info *ka, int *timeout) if (ka->rekey) { time_t due = ka->last_rekey + ka->rekey; - if (now >= due) + if (now >= due) { + ka->last_rekey = now; return KA_REKEY; + } if (*timeout > (due - now) * 1000) *timeout = (due - now) * 1000; diff --git a/openconnect-internal.h b/openconnect-internal.h index 004cb38b..d28a8ca4 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -496,6 +496,7 @@ int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t le int openconnect_SSL_read(struct openconnect_info *vpninfo, char *buf, size_t len); int openconnect_open_https(struct openconnect_info *vpninfo); void openconnect_close_https(struct openconnect_info *vpninfo, int final); +int cstp_handshake(struct openconnect_info *vpninfo, unsigned init); int get_cert_md5_fingerprint(struct openconnect_info *vpninfo, OPENCONNECT_X509 *cert, char *buf); int openconnect_sha1(unsigned char *result, void *data, int len); diff --git a/openssl.c b/openssl.c index d6e83cf1..13b8c0d9 100644 --- a/openssl.c +++ b/openssl.c @@ -1413,6 +1413,11 @@ int openconnect_open_https(struct openconnect_info *vpninfo) return 0; } +int cstp_handshake(struct openconnect_info *vpninfo, unsigned init) +{ + return -EOPNOTSUPP; +} + void openconnect_close_https(struct openconnect_info *vpninfo, int final) { if (vpninfo->peer_cert) {