diff --git a/openconnect-7.05-ensure-dtls-ciphers-match-the-allowed.patch b/openconnect-7.05-ensure-dtls-ciphers-match-the-allowed.patch new file mode 100644 index 0000000..b7d6088 --- /dev/null +++ b/openconnect-7.05-ensure-dtls-ciphers-match-the-allowed.patch @@ -0,0 +1,200 @@ +From 4892c7a53bb0adec98c4540a0b127b209625f82a Mon Sep 17 00:00:00 2001 +From: Nikos Mavrogiannopoulos +Date: Wed, 4 Mar 2015 10:29:06 +0100 +Subject: [PATCH 2/2] when using gnutls enable only the DTLS ciphersuites that + were available during TLS + +Signed-off-by: Nikos Mavrogiannopoulos +--- + cstp.c | 3 ++ + dtls.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++---- + gnutls.c | 7 ++--- + openconnect-internal.h | 2 ++ + 4 files changed, 81 insertions(+), 10 deletions(-) + +diff --git a/cstp.c b/cstp.c +index d0d7eff..a06ca34 100644 +--- a/cstp.c ++++ b/cstp.c +@@ -202,6 +202,9 @@ static int start_cstp_connection(struct openconnect_info *vpninfo) + vpninfo->ip_info.domain = vpninfo->ip_info.proxy_pac = NULL; + vpninfo->banner = NULL; + ++ if (!vpninfo->dtls_ciphers) ++ vpninfo->dtls_ciphers = dtls_ciphers_from_conn(vpninfo); ++ + for (i = 0; i < 3; i++) + vpninfo->ip_info.dns[i] = vpninfo->ip_info.nbns[i] = NULL; + free_split_routes(vpninfo); +diff --git a/dtls.c b/dtls.c +index abffbf1..6ac537d 100644 +--- a/dtls.c ++++ b/dtls.c +@@ -222,6 +222,11 @@ static SSL_SESSION *generate_dtls_session(struct openconnect_info *vpninfo, + } + #endif + ++char *dtls_ciphers_from_conn(struct openconnect_info *vpninfo) ++{ ++ return NULL; ++} ++ + static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) + { + STACK_OF(SSL_CIPHER) *ciphers; +@@ -438,27 +443,89 @@ void dtls_shutdown(struct openconnect_info *vpninfo) + #include + #include "gnutls.h" + ++#define SSTR(x) x,sizeof(x) + struct { + const char *name; ++ unsigned name_len; + gnutls_protocol_t version; + gnutls_cipher_algorithm_t cipher; + gnutls_mac_algorithm_t mac; + const char *prio; ++ unsigned disabled; + } gnutls_dtls_ciphers[] = { +- { "AES128-SHA", GNUTLS_DTLS0_9, GNUTLS_CIPHER_AES_128_CBC, GNUTLS_MAC_SHA1, ++ { SSTR("AES128-SHA"), GNUTLS_DTLS0_9, GNUTLS_CIPHER_AES_128_CBC, GNUTLS_MAC_SHA1, + "NONE:+VERS-DTLS0.9:+COMP-NULL:+AES-128-CBC:+SHA1:+RSA:%COMPAT" }, +- { "AES256-SHA", GNUTLS_DTLS0_9, GNUTLS_CIPHER_AES_256_CBC, GNUTLS_MAC_SHA1, ++ { SSTR("AES256-SHA"), GNUTLS_DTLS0_9, GNUTLS_CIPHER_AES_256_CBC, GNUTLS_MAC_SHA1, + "NONE:+VERS-DTLS0.9:+COMP-NULL:+AES-256-CBC:+SHA1:+RSA:%COMPAT" }, +- { "DES-CBC3-SHA", GNUTLS_DTLS0_9, GNUTLS_CIPHER_3DES_CBC, GNUTLS_MAC_SHA1, ++ { SSTR("DES-CBC3-SHA"), GNUTLS_DTLS0_9, GNUTLS_CIPHER_3DES_CBC, GNUTLS_MAC_SHA1, + "NONE:+VERS-DTLS0.9:+COMP-NULL:+3DES-CBC:+SHA1:+RSA:%COMPAT" }, + #if GNUTLS_VERSION_NUMBER >= 0x030207 /* if DTLS 1.2 is supported (and a bug in gnutls is solved) */ +- { "OC-DTLS1_2-AES128-GCM", GNUTLS_DTLS1_2, GNUTLS_CIPHER_AES_128_GCM, GNUTLS_MAC_AEAD, ++ { SSTR("OC-DTLS1_2-AES128-GCM"), GNUTLS_DTLS1_2, GNUTLS_CIPHER_AES_128_GCM, GNUTLS_MAC_AEAD, + "NONE:+VERS-DTLS1.2:+COMP-NULL:+AES-128-GCM:+AEAD:+RSA:%COMPAT:+SIGN-ALL" }, +- { "OC-DTLS1_2-AES256-GCM", GNUTLS_DTLS1_2, GNUTLS_CIPHER_AES_256_GCM, GNUTLS_MAC_AEAD, ++ { SSTR("OC-DTLS1_2-AES256-GCM"), GNUTLS_DTLS1_2, GNUTLS_CIPHER_AES_256_GCM, GNUTLS_MAC_AEAD, + "NONE:+VERS-DTLS1.2:+COMP-NULL:+AES-256-GCM:+AEAD:+RSA:%COMPAT:+SIGN-ALL" }, + #endif + }; + ++char *dtls_ciphers_from_conn(struct openconnect_info *vpninfo) ++{ ++ /* only enable the ciphers that would have been negotiated in the TLS channel */ ++ unsigned i, j; ++ int ret; ++ unsigned idx; ++ gnutls_cipher_algorithm_t cipher; ++ gnutls_mac_algorithm_t mac; ++ struct oc_text_buf *buf; ++ gnutls_priority_t cache; ++ char *p; ++ ++ /* everything is disabled by default */ ++ for (i = 0; i < sizeof(gnutls_dtls_ciphers)/sizeof(gnutls_dtls_ciphers[0]); i++) { ++ gnutls_dtls_ciphers[i].disabled = 1; ++ } ++ ++ ret = gnutls_priority_init(&cache, vpninfo->gnutls_default_prio, NULL); ++ if (ret < 0) ++ return NULL; ++ ++ for (j=0;;j++) { ++ ret = gnutls_priority_get_cipher_suite_index(cache, j, &idx); ++ if (ret == GNUTLS_E_UNKNOWN_CIPHER_SUITE) ++ continue; ++ else if (ret < 0) ++ break; ++ ++ if (gnutls_cipher_suite_info(idx, NULL, NULL, &cipher, &mac, NULL) != NULL) { ++ for (i = 0; i < sizeof(gnutls_dtls_ciphers)/sizeof(gnutls_dtls_ciphers[0]); i++) { ++ if (gnutls_dtls_ciphers[i].mac == mac && gnutls_dtls_ciphers[i].cipher == cipher) { ++ gnutls_dtls_ciphers[i].disabled = 0; ++ break; ++ } ++ } ++ } ++ } ++ ++ buf = buf_alloc(); ++ ++ for (i = 0; i < sizeof(gnutls_dtls_ciphers)/sizeof(gnutls_dtls_ciphers[0]); i++) { ++ if (!gnutls_dtls_ciphers[i].disabled) { ++ if (buf->buf_len == 0) { ++ buf_append(buf, "%s", gnutls_dtls_ciphers[i].name); ++ } else { ++ buf_append(buf, ":%s", gnutls_dtls_ciphers[i].name); ++ } ++ } ++ } ++ ++ /* steal buffer */ ++ p = buf->data; ++ buf->data = NULL; ++ ++ buf_free(buf); ++ gnutls_priority_deinit(cache); ++ return p; ++} ++ + #define DTLS_SEND gnutls_record_send + #define DTLS_RECV gnutls_record_recv + #define DTLS_FREE gnutls_deinit +@@ -470,7 +537,7 @@ static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) + int cipher; + + for (cipher = 0; cipher < sizeof(gnutls_dtls_ciphers)/sizeof(gnutls_dtls_ciphers[0]); cipher++) { +- if (!strcmp(vpninfo->dtls_cipher, gnutls_dtls_ciphers[cipher].name)) ++ if (!strcmp(vpninfo->dtls_cipher, gnutls_dtls_ciphers[cipher].name) && !gnutls_dtls_ciphers[cipher].disabled) + goto found_cipher; + } + vpn_progress(vpninfo, PRG_ERR, _("Unknown DTLS parameters for requested CipherSuite '%s'\n"), +diff --git a/gnutls.c b/gnutls.c +index 34119da..e121842 100644 +--- a/gnutls.c ++++ b/gnutls.c +@@ -2070,7 +2070,6 @@ int openconnect_open_https(struct openconnect_info *vpninfo) + { + int ssl_sock = -1; + int err; +- const char * prio; + + if (vpninfo->https_sess) + return 0; +@@ -2196,13 +2195,13 @@ int openconnect_open_https(struct openconnect_info *vpninfo) + strlen(vpninfo->hostname)); + + if (vpninfo->pfs) { +- prio = DEFAULT_PRIO":-RSA"; ++ vpninfo->gnutls_default_prio = DEFAULT_PRIO":-RSA"; + } else { +- prio = DEFAULT_PRIO; ++ vpninfo->gnutls_default_prio = DEFAULT_PRIO; + } + + err = gnutls_priority_set_direct(vpninfo->https_sess, +- prio, NULL); ++ vpninfo->gnutls_default_prio, NULL); + if (err) { + vpn_progress(vpninfo, PRG_ERR, + _("Failed to set TLS priority string: %s\n"), +diff --git a/openconnect-internal.h b/openconnect-internal.h +index 04cb226..7b7161c 100644 +--- a/openconnect-internal.h ++++ b/openconnect-internal.h +@@ -469,6 +469,7 @@ struct openconnect_info { + gnutls_session_t https_sess; + gnutls_certificate_credentials_t https_cred; + char local_cert_md5[MD5_SIZE * 2 + 1]; /* For CSD */ ++ const char *gnutls_default_prio; + #ifdef HAVE_TROUSERS + TSS_HCONTEXT tpm_context; + TSS_HKEY srk; +@@ -765,6 +766,7 @@ int dtls_setup(struct openconnect_info *vpninfo, int dtls_attempt_period); + int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout); + void dtls_close(struct openconnect_info *vpninfo); + void dtls_shutdown(struct openconnect_info *vpninfo); ++char *dtls_ciphers_from_conn(struct openconnect_info *vpninfo); + + /* cstp.c */ + void cstp_common_headers(struct openconnect_info *vpninfo, struct oc_text_buf *buf); +-- +2.1.0 + diff --git a/openconnect-7.05-override-default-prio-string.patch b/openconnect-7.05-override-default-prio-string.patch new file mode 100644 index 0000000..2e5c906 --- /dev/null +++ b/openconnect-7.05-override-default-prio-string.patch @@ -0,0 +1,64 @@ +From db955eceff87ecc7994348c952029ae012fc5b6a Mon Sep 17 00:00:00 2001 +From: Nikos Mavrogiannopoulos +Date: Tue, 3 Mar 2015 16:57:51 +0100 +Subject: [PATCH 1/2] Allow overriding the default GnuTLS priority string + +Signed-off-by: Nikos Mavrogiannopoulos +--- + configure.ac | 9 +++++++++ + gnutls.c | 18 ++++++++++-------- + 2 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/configure.ac b/configure.ac +index e5b5e80..ddb5c48 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -417,6 +417,15 @@ if test "$with_gnutls" = "yes"; then + LIBS="$oldlibs" + CFLAGS="$oldcflags" + fi ++ ++AC_ARG_WITH([default-gnutls-priority], ++ AS_HELP_STRING([--with-default-gnutls-priority=STRING], ++ [Provide a default string as GnuTLS priority string]), ++ default_gnutls_priority=$withval) ++if test -n "$default_gnutls_priority"; then ++ AC_DEFINE_UNQUOTED([DEFAULT_PRIO], ["$default_gnutls_priority"], [The GnuTLS priority string]) ++fi ++ + if test "$with_openssl" = "yes" || test "$with_openssl" = "" || test "$ssl_library" = "both"; then + PKG_CHECK_MODULES(OPENSSL, openssl, [], + [oldLIBS="$LIBS" +diff --git a/gnutls.c b/gnutls.c +index 3f79a22..34119da 100644 +--- a/gnutls.c ++++ b/gnutls.c +@@ -2052,15 +2052,17 @@ static int verify_peer(gnutls_session_t session) + * >= 3.2.9 as there the %COMPAT keyword ensures that the client hello + * will be outside that range. + */ +-#if GNUTLS_VERSION_NUMBER >= 0x030209 +-# define DEFAULT_PRIO "NORMAL:-VERS-SSL3.0:%COMPAT" +-#else +-# define _DEFAULT_PRIO "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:" \ ++#ifndef DEFAULT_PRIO ++# if GNUTLS_VERSION_NUMBER >= 0x030209 ++# define DEFAULT_PRIO "NORMAL:-VERS-SSL3.0:%COMPAT" ++# else ++# define _DEFAULT_PRIO "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:" \ + "%COMPAT:%DISABLE_SAFE_RENEGOTIATION:%LATEST_RECORD_VERSION" +-# if GNUTLS_VERSION_MAJOR >= 3 +-# define DEFAULT_PRIO _DEFAULT_PRIO":-CURVE-ALL:-ECDHE-RSA:-ECDHE-ECDSA" +-#else +-# define DEFAULT_PRIO _DEFAULT_PRIO ++# if GNUTLS_VERSION_MAJOR >= 3 ++# define DEFAULT_PRIO _DEFAULT_PRIO":-CURVE-ALL:-ECDHE-RSA:-ECDHE-ECDSA" ++# else ++# define DEFAULT_PRIO _DEFAULT_PRIO ++# endif + # endif + #endif + +-- +2.1.0 + diff --git a/openconnect.spec b/openconnect.spec index 4ad901a..d422caf 100644 --- a/openconnect.spec +++ b/openconnect.spec @@ -21,13 +21,16 @@ Name: openconnect Version: 7.05 -Release: 1%{?relsuffix}%{?dist} +Release: 2%{?relsuffix}%{?dist} Summary: Open client for Cisco AnyConnect VPN Group: Applications/Internet License: LGPLv2+ URL: http://www.infradead.org/openconnect.html Source0: ftp://ftp.infradead.org/pub/openconnect/openconnect-%{version}%{?gitsuffix}.tar.gz +Patch1: openconnect-7.05-override-default-prio-string.patch +Patch2: openconnect-7.05-ensure-dtls-ciphers-match-the-allowed.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: pkgconfig(openssl) pkgconfig(libxml-2.0) @@ -70,8 +73,13 @@ for NetworkManager etc. %prep %setup -q -n openconnect-%{version}%{?gitsuffix} +%patch1 -p1 -b .prio +%patch2 -p1 -b .ciphers + %build +autoreconf -fvi %configure --with-vpnc-script=/etc/vpnc/vpnc-script \ + --with-default-gnutls-priority="@SYSTEM" \ %if !%{use_gnutls} --with-openssl --without-openssl-version-check \ %endif @@ -106,6 +114,9 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/pkgconfig/openconnect.pc %changelog +* Wed Mar 11 2015 Nikos Mavrogiannopoulos - 7.05-2 +- Utilize and enforce system-wide policies (#1179331) + * Sun Jan 25 2015 David Woodhouse - 7.05-1 - Update to 7.05 release