You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
6.9 KiB
201 lines
6.9 KiB
From 4892c7a53bb0adec98c4540a0b127b209625f82a Mon Sep 17 00:00:00 2001
|
|
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
|
|
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 <nmav@redhat.com>
|
|
---
|
|
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 <gnutls/dtls.h>
|
|
#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
|
|
|