The PFS option will prevent a leakage of the server long-term key from causing decryption of all previously exchanged data. Signed-off-by: Nikos Mavrogiannopoulos <nmav at gnutls.org> --- gnutls.c | 18 +++++++++++++----- main.c | 6 ++++++ openconnect-internal.h | 1 + openssl.c | 3 +++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/gnutls.c b/gnutls.c index 52e632b..d25ec23 100644 --- a/gnutls.c +++ b/gnutls.c @@ -1801,11 +1801,14 @@ static int verify_peer(gnutls_session_t session) return err; } +#define DEFAULT_PRIO "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:" \ + "%COMPAT:%DISABLE_SAFE_RENEGOTIATION:%LATEST_RECORD_VERSION" int openconnect_open_https(struct openconnect_info *vpninfo) { int ssl_sock = -1; int err; + const char * prio; if (vpninfo->https_sess) return 0; @@ -1912,13 +1915,18 @@ int openconnect_open_https(struct openconnect_info *vpninfo) gnutls_sign_callback_set(vpninfo->https_sess, gtls2_tpm_sign_cb, vpninfo); #endif - err = gnutls_priority_set_direct(vpninfo->https_sess, - "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:" + if (vpninfo->pfs) { + prio = DEFAULT_PRIO":-RSA"; + } else { + prio = DEFAULT_PRIO #if GNUTLS_VERSION_MAJOR >= 3 - "-CURVE-ALL:" + ":-CURVE-ALL" #endif - "%COMPAT:%DISABLE_SAFE_RENEGOTIATION:%LATEST_RECORD_VERSION", - NULL); + ; + } + + err = gnutls_priority_set_direct(vpninfo->https_sess, + prio, NULL); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to set TLS priority string: %s\n"), diff --git a/main.c b/main.c index 5ddd9b8..afaedf2 100644 --- a/main.c +++ b/main.c @@ -116,6 +116,7 @@ enum { OPT_TOKEN_MODE, OPT_TOKEN_SECRET, OPT_OS, + OPT_PFS, }; #ifdef __sun__ @@ -130,6 +131,7 @@ enum { static struct option long_options[] = { OPTION("background", 0, 'b'), + OPTION("pfs", 0, OPT_PFS), OPTION("pid-file", 1, OPT_PIDFILE), OPTION("certificate", 1, 'c'), OPTION("sslkey", 1, 'k'), @@ -270,6 +272,7 @@ static void usage(void) #ifndef LIBPROXY_HDR printf(" %s\n", _("(NOTE: libproxy disabled in this build)")); #endif + printf(" --pfs %s\n", _("Require perfect forward secrecy")); printf(" -q, --quiet %s\n", _("Less output")); printf(" -Q, --queue-len=LEN %s\n", _("Set packet queue limit to LEN pkts")); printf(" -s, --script=SCRIPT %s\n", _("Shell command line for using a vpnc-compatible config script")); @@ -541,6 +544,9 @@ int main(int argc, char **argv) case OPT_PIDFILE: pidfile = keep_config_arg(); break; + case OPT_PFS: + vpninfo->pfs = 1; + break; case OPT_SERVERCERT: vpninfo->servercert = keep_config_arg(); break; diff --git a/openconnect-internal.h b/openconnect-internal.h index 4dc9ed4..b480847 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -203,6 +203,7 @@ struct openconnect_info { struct vpn_option *cstp_options; struct vpn_option *dtls_options; + unsigned pfs; #if defined(OPENCONNECT_OPENSSL) X509 *cert_x509; SSL_CTX *https_ctx; diff --git a/openssl.c b/openssl.c index a395bc5..43a2093 100644 --- a/openssl.c +++ b/openssl.c @@ -1319,6 +1319,9 @@ int openconnect_open_https(struct openconnect_info *vpninfo) ssl_app_verify_callback, NULL); #endif SSL_CTX_set_default_verify_paths(vpninfo->https_ctx); + + if (vpninfo->pfs) + SSL_CTX_set_cipher_list(vpninfo->https_ctx, "HIGH:!aNULL:!eNULL:-RSA"); #ifdef ANDROID_KEYSTORE if (vpninfo->cafile && !strncmp(vpninfo->cafile, "keystore:", 9)) {