openconnect: Fix DTLS with OpenSSL

Backported upstream patches that fix this.

Removed local patch that fixes libp11 with version 0.4.7, which is not
used anymore. Upstream has a different solution.

License fixes and Makefile cleanups.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
This commit is contained in:
Rosen Penev 2019-06-24 10:42:33 -07:00
parent b4015743ce
commit 6dbbc17b1f
5 changed files with 258 additions and 54 deletions

View File

@ -9,18 +9,20 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=openconnect
PKG_VERSION:=8.03
PKG_RELEASE:=1
PKG_USE_MIPS16:=0
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=ftp://ftp.infradead.org/pub/openconnect/
PKG_HASH:=908cff9b1ce266b6bb7f969a7f62723543ab94719ba3c95a150fe3894cbc9ef2
PKG_LICENSE:=LGPLv2.1+
PKG_LICENSE:=LGPL-2.1-or-later
PKG_LICENSE_FILES:=COPYING.LGPL
PKG_CONFIG_DEPENDS:= \
CONFIG_OPENCONNECT_GNUTLS \
CONFIG_OPENCONNECT_OPENSSL \
PKG_USE_MIPS16:=0
include $(INCLUDE_DIR)/package.mk
@ -34,7 +36,7 @@ define Package/openconnect
DEPENDS:=+libxml2 +kmod-tun +resolveip +vpnc-scripts +OPENCONNECT_OPENSSL:libopenssl +OPENCONNECT_OPENSSL:p11-kit +OPENCONNECT_OPENSSL:libp11 +OPENCONNECT_GNUTLS:libgnutls +OPENCONNECT_GNUTLS:libtasn1 +OPENCONNECT_STOKEN:libstoken
TITLE:=OpenConnect VPN client (Cisco AnyConnect and Juniper/Pulse compatible)
MAINTAINER:=Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
URL:=http://www.infradead.org/openconnect/
URL:=https://www.infradead.org/openconnect/
SUBMENU:=VPN
endef

View File

@ -1,50 +0,0 @@
From 03ecd34e0137b3f0bf0d2fc3ab7f7d8b3682785e Mon Sep 17 00:00:00 2001
From: Yousong Zhou <yszhou4tech@gmail.com>
Date: Thu, 14 Dec 2017 18:03:35 +0800
Subject: [PATCH] Fix compilation with libp11 version >= 0.4.7
libp11 0.4.7 renamed then dropped macro definition in commits
4f0fce4: Error reporting fixes
e4c641b: PKCS11 errors separated into P11 and CKR
This change assumes that libp11 will restore compatibility by bringing
back old forms of macro definition
Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
---
openssl-pkcs11.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/openssl-pkcs11.c b/openssl-pkcs11.c
index 61da123..ba7e491 100644
--- a/openssl-pkcs11.c
+++ b/openssl-pkcs11.c
@@ -30,6 +30,24 @@
#include <libp11.h>
#include <p11-kit/pkcs11.h>
+#ifndef ERR_LIB_PKCS11
+# if defined(ERR_LIB_CKR)
+# define ERR_LIB_PKCS11 ERR_LIB_CKR
+# elif defined(ERR_LIB_USER)
+# define ERR_LIB_PKCS11 ERR_LIB_USER
+# else
+# error undefined macro ERR_LIB_PKCS11
+# endif
+#endif
+
+#ifndef PKCS11_F_PKCS11_LOGIN
+# if defined(CKR_F_PKCS11_LOGIN)
+# define PKCS11_F_PKCS11_LOGIN CKR_F_PKCS11_LOGIN
+# else
+# error undefined macro PKCS11_F_PKCS11_LOGIN
+# endif
+#endif
+
static PKCS11_CTX *pkcs11_ctx(struct openconnect_info *vpninfo)
{
PKCS11_CTX *ctx;
--
1.8.3.1

View File

@ -0,0 +1,75 @@
From 460c060dda115bc8066bb4b955453c673459b6cc Mon Sep 17 00:00:00 2001
From: Rosen Penev <rosenp@gmail.com>
Date: Sun, 9 Jun 2019 23:36:53 -0700
Subject: [PATCH] Fix compilation without deprecated OpenSSL 1.1 APIs
Initialization and deinitialization is deprecated.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
library.c | 4 ++++
openssl.c | 2 ++
tests/bad_dtls_test.c | 4 ++++
3 files changed, 10 insertions(+)
diff --git a/library.c b/library.c
index 0e3d05e6..e45e93a2 100644
--- a/library.c
+++ b/library.c
@@ -38,6 +38,10 @@
#include "gnutls.h"
#endif
+#if defined(OPENCONNECT_OPENSSL)
+#include <openssl/bio.h>
+#endif
+
struct openconnect_info *openconnect_vpninfo_new(const char *useragent,
openconnect_validate_peer_cert_vfn validate_peer_cert,
openconnect_write_new_config_vfn write_new_config,
diff --git a/openssl.c b/openssl.c
index 2b1f07bd..e505f49a 100644
--- a/openssl.c
+++ b/openssl.c
@@ -1879,10 +1879,12 @@ int openconnect_init_ssl(void)
if (ret)
return ret;
#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
SSL_library_init();
ERR_clear_error();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
+#endif
return 0;
}
diff --git a/tests/bad_dtls_test.c b/tests/bad_dtls_test.c
index ac8d3f1e..c123c8f8 100644
--- a/tests/bad_dtls_test.c
+++ b/tests/bad_dtls_test.c
@@ -752,8 +752,10 @@ int main(int argc, char *argv[])
int ret;
int i;
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
SSL_library_init();
SSL_load_error_strings();
+#endif
RAND_bytes(session_id, sizeof(session_id));
RAND_bytes(master_secret, sizeof(master_secret));
@@ -910,8 +912,10 @@ int main(int argc, char *argv[])
printf("Cisco BadDTLS test: FAILED\n");
}
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
ERR_free_strings();
EVP_cleanup();
+#endif
return testresult?0:1;
}
--
2.17.1

View File

@ -0,0 +1,139 @@
From afb6442533dc7475ed61642c3f5b295db1e6f561 Mon Sep 17 00:00:00 2001
From: Rosen Penev <rosenp@gmail.com>
Date: Sun, 9 Jun 2019 23:40:21 -0700
Subject: [PATCH] Fix DTLS bug when lacking deprecated APIs
HAVE_DTLS12 is for DTLSv1_method. This causes dtls_method to be NULL and
crash.
[dwmw2: Rework it quite a bit more]
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
---
configure.ac | 17 ++++++++++++++---
openssl-dtls.c | 49 ++++++++++++++++++++++++++-----------------------
2 files changed, 40 insertions(+), 26 deletions(-)
diff --git a/configure.ac b/configure.ac
index 02096c51..f7557933 100644
--- a/configure.ac
+++ b/configure.ac
@@ -455,11 +455,22 @@ case "$ssl_library" in
AC_DEFINE(HAVE_DTLS1_STOP_TIMER, [1], [OpenSSL has dtls1_stop_timer() function])],
[AC_MSG_RESULT(no)])
- AC_MSG_CHECKING([for DTLSv1_2_client_method() in OpenSSL])
+ # DTLS_client_method() and DTLSv1_2_client_method() were both added between
+ # OpenSSL v1.0.1 and v1.0.2. DTLSV1.2_client_method() was later deprecated
+ # in v1.1.0 so we use DTLS_client_method() as our check for DTLSv1.2 support
+ # and that's what we actually use in openssl-dtls.c too.
+ AC_MSG_CHECKING([for DTLS_client_method() in OpenSSL])
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <openssl/ssl.h>],
- [DTLSv1_2_client_method();])],
+ [DTLS_client_method();])],
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_DTLS12, [1], [OpenSSL has DTLSv1_2_client_method() function])],
+ AC_DEFINE(HAVE_DTLS12, [1], [OpenSSL has DTLS_client_method() function])],
+ [AC_MSG_RESULT(no)])
+
+ AC_MSG_CHECKING([for SSL_CTX_set_min_proto_version() in OpenSSL])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <openssl/ssl.h>],
+ [SSL_CTX_set_min_proto_version((void *)0, 0);])],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SSL_CTX_PROTOVER, [1], [OpenSSL has SSL_CTX_set_min_proto_version() function])],
[AC_MSG_RESULT(no)])
AC_CHECK_FUNC(HMAC_CTX_copy,
diff --git a/openssl-dtls.c b/openssl-dtls.c
index 5086440f..9e3c5d46 100644
--- a/openssl-dtls.c
+++ b/openssl-dtls.c
@@ -332,6 +332,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
const char *cipher = vpninfo->dtls_cipher;
#ifdef HAVE_DTLS12
+ /* These things should never happen unless they're supported */
if (vpninfo->cisco_dtls12) {
dtlsver = DTLS1_2_VERSION;
} else if (!strcmp(cipher, "OC-DTLS1_2-AES128-GCM")) {
@@ -349,16 +350,16 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
if (!vpninfo->dtls_ctx) {
#ifdef HAVE_DTLS12
+ /* If we can use SSL_CTX_set_min_proto_version, do so. */
dtls_method = DTLS_client_method();
#endif
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+#ifndef HAVE_SSL_CTX_PROTOVER
+ /* If !HAVE_DTLS12, dtlsver *MUST* be DTLS1_BAD_VER because it's set
+ * at the top of the function and nothing can change it. */
if (dtlsver == DTLS1_BAD_VER)
dtls_method = DTLSv1_client_method();
-#ifdef HAVE_DTLS12
- else if (dtlsver == DTLS1_2_VERSION)
- dtls_method = DTLSv1_2_client_method();
-#endif
#endif
+
vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
if (!vpninfo->dtls_ctx) {
vpn_progress(vpninfo, PRG_ERR,
@@ -367,24 +368,26 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
vpninfo->dtls_attempt_period = 0;
return -EINVAL;
}
- if (dtlsver) {
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
- if (dtlsver == DTLS1_BAD_VER)
- SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_CISCO_ANYCONNECT);
-#else
- if (!SSL_CTX_set_min_proto_version(vpninfo->dtls_ctx, dtlsver) ||
- !SSL_CTX_set_max_proto_version(vpninfo->dtls_ctx, dtlsver)) {
- vpn_progress(vpninfo, PRG_ERR,
- _("Set DTLS CTX version failed\n"));
- openconnect_report_ssl_errors(vpninfo);
- SSL_CTX_free(vpninfo->dtls_ctx);
- vpninfo->dtls_ctx = NULL;
- vpninfo->dtls_attempt_period = 0;
- return -EINVAL;
- }
+#ifdef HAVE_SSL_CTX_PROTOVER
+ if (dtlsver &&
+ (!SSL_CTX_set_min_proto_version(vpninfo->dtls_ctx, dtlsver) ||
+ !SSL_CTX_set_max_proto_version(vpninfo->dtls_ctx, dtlsver))) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Set DTLS CTX version failed\n"));
+ openconnect_report_ssl_errors(vpninfo);
+ SSL_CTX_free(vpninfo->dtls_ctx);
+ vpninfo->dtls_ctx = NULL;
+ vpninfo->dtls_attempt_period = 0;
+ return -EINVAL;
+ }
+#else /* !HAVE_SSL_CTX_PROTOVER */
+ /* If we used the legacy version-specific methods, we need the special
+ * way to make TLSv1_client_method() do DTLS1_BAD_VER. */
+ if (dtlsver == DTLS1_BAD_VER)
+ SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_CISCO_ANYCONNECT);
#endif
#if defined (HAVE_DTLS12) && !defined(OPENSSL_NO_PSK)
- } else {
+ if (!dtlsver) {
SSL_CTX_set_psk_client_callback(vpninfo->dtls_ctx, psk_callback);
/* For PSK we override the DTLS master secret with one derived
* from the HTTPS session. */
@@ -401,9 +404,9 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
}
/* For SSL_CTX_set_cipher_list() */
cipher = "PSK";
-
-#endif
}
+#endif /* OPENSSL_NO_PSK */
+
/* If we don't readahead, then we do short reads and throw
away the tail of data packets. */
SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
--
2.17.1

View File

@ -0,0 +1,38 @@
From 97cafd182f5a5c2d13f57d7faeac8432aea9bbf8 Mon Sep 17 00:00:00 2001
From: David Woodhouse <dwmw2@infradead.org>
Date: Mon, 10 Jun 2019 12:34:43 +0100
Subject: [PATCH] Disable encrypt-then-mac where possible with DTLS and OpenSSL
There is pain here. Just don't bother.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
---
openssl-dtls.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/openssl-dtls.c b/openssl-dtls.c
index 9e3c5d46..646bf71c 100644
--- a/openssl-dtls.c
+++ b/openssl-dtls.c
@@ -406,7 +406,17 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
cipher = "PSK";
}
#endif /* OPENSSL_NO_PSK */
-
+#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC
+ /* I'm fairly sure I wasn't lying when I said I had tested
+ * https://github.com/openssl/openssl/commit/e23d5071ec4c7aa6bb2b
+ * against GnuTLS both with and without EtM in 2016.
+ * Nevertheless, in 2019 it seems to be failing to negotiate
+ * at least for DTLS1_BAD_VER against ocserv with GnuTLS 3.6.7.
+ * Just turn it off. Real Cisco servers don't do it for
+ * DTLS1_BAD_VER, and we should be using GCM ciphersuites in
+ * newer versions of DTLS anyway so it's irrelevant. */
+ SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_NO_ENCRYPT_THEN_MAC);
+#endif
/* If we don't readahead, then we do short reads and throw
away the tail of data packets. */
SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
--
2.17.1