[PATCH 4/6] Added --pfs option to force perfect forward secrecy

Nikos Mavrogiannopoulos nmav at gnutls.org
Sat Nov 23 12:58:28 EST 2013


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)) {





More information about the openconnect-devel mailing list