From 20c2a03480d24a0dc3dfd1adfdda951896fc7518 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 29 Apr 2015 14:27:57 +0200 Subject: [PATCH] Only enable the DTLS ciphersuites that match the ones enabled in TLS That currently is restricted to gnutls code. Signed-off-by: Nikos Mavrogiannopoulos Signed-off-by: David Woodhouse --- dtls.c | 43 ++++++++++++++++++++++++++++++++++++++++++ gnutls.c | 9 ++++----- openconnect-internal.h | 1 + 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/dtls.c b/dtls.c index 746858b7..ec089ded 100644 --- a/dtls.c +++ b/dtls.c @@ -471,6 +471,7 @@ struct { "NONE:+VERS-DTLS1.2:+COMP-NULL:+AES-256-GCM:+AEAD:+RSA:%COMPAT:+SIGN-ALL", "3.2.7" }, }; +#if GNUTLS_VERSION_NUMBER < 0x030009 void append_dtls_ciphers(struct openconnect_info *vpninfo, struct oc_text_buf *buf) { int i, first = 1; @@ -482,7 +483,49 @@ void append_dtls_ciphers(struct openconnect_info *vpninfo, struct oc_text_buf *b first = 0; } } +#else +void append_dtls_ciphers(struct openconnect_info *vpninfo, struct oc_text_buf *buf) +{ + /* only enable the ciphers that would have been negotiated in the TLS channel */ + unsigned i, j, first = 1; + int ret; + unsigned idx; + gnutls_cipher_algorithm_t cipher; + gnutls_mac_algorithm_t mac; + gnutls_priority_t cache; + uint32_t used = 0; + + ret = gnutls_priority_init(&cache, vpninfo->gnutls_prio, NULL); + if (ret < 0) { + buf->error = -EIO; + return; + } + + 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 (used & (1 << i)) + continue; + if (gnutls_dtls_ciphers[i].mac == mac && gnutls_dtls_ciphers[i].cipher == cipher) { + buf_append(buf, "%s%s", first ? "" : ":", + gnutls_dtls_ciphers[i].name); + first = 0; + used |= (1 << i); + break; + } + } + } + } + + gnutls_priority_deinit(cache); } +#endif #define DTLS_SEND gnutls_record_send #define DTLS_RECV gnutls_record_recv diff --git a/gnutls.c b/gnutls.c index 9658f9f2..223e53a9 100644 --- a/gnutls.c +++ b/gnutls.c @@ -2069,7 +2069,6 @@ int openconnect_open_https(struct openconnect_info *vpninfo) { int ssl_sock = -1; int err; - char prio[256]; if (vpninfo->https_sess) return 0; @@ -2222,19 +2221,19 @@ int openconnect_open_https(struct openconnect_info *vpninfo) * 28065ce3896b1b0f87972d0bce9b17641ebb69b9 */ if (gnutls_check_version("3.2.9")) { - snprintf(prio, sizeof(prio), DEFAULT_PRIO_3_2_9"%s", vpninfo->pfs?":-RSA":""); + snprintf(vpninfo->gnutls_prio, sizeof(vpninfo->gnutls_prio), DEFAULT_PRIO_3_2_9"%s", vpninfo->pfs?":-RSA":""); } else { if (gnutls_check_version("3.0.0")) { - snprintf(prio, sizeof(prio), DEFAULT_PRIO_3_0_0"%s", vpninfo->pfs?":-RSA":""); + snprintf(vpninfo->gnutls_prio, sizeof(vpninfo->gnutls_prio), DEFAULT_PRIO_3_0_0"%s", vpninfo->pfs?":-RSA":""); } else { - snprintf(prio, sizeof(prio), DEFAULT_PRIO_2_12_0"%s", + snprintf(vpninfo->gnutls_prio, sizeof(vpninfo->gnutls_prio), DEFAULT_PRIO_2_12_0"%s", vpninfo->pfs?":-RSA":""); } } err = gnutls_priority_set_direct(vpninfo->https_sess, - prio, NULL); + vpninfo->gnutls_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 a771c796..a891e24b 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -470,6 +470,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 */ + char gnutls_prio[256]; #ifdef HAVE_TROUSERS TSS_HCONTEXT tpm_context; TSS_HKEY srk;