openconnect: Fix DTLS with OpenSSL
authorRosen Penev <rosenp@gmail.com>
Mon, 24 Jun 2019 17:42:33 +0000 (10:42 -0700)
committerRosen Penev <rosenp@gmail.com>
Mon, 24 Jun 2019 17:58:20 +0000 (10:58 -0700)
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>
net/openconnect/Makefile
net/openconnect/patches/0001-Fix-compilation-with-libp11-version-0.4.7.patch [deleted file]
net/openconnect/patches/010-Fix-compilation-without-deprecated-OpenSSL-1.1-APIs.patch [new file with mode: 0644]
net/openconnect/patches/020-Fix-DTLS-bug-when-lacking-deprecated-APIs.patch [new file with mode: 0644]
net/openconnect/patches/030-Disable-encrypt-then-mac-where-possible-with-DTLS-an.patch [new file with mode: 0644]

index d75d2af019ad861ad974d261e64755d5cdffef5a..4ed174001eb751b0a2052036e4df7c402989e7ee 100644 (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
 
diff --git a/net/openconnect/patches/0001-Fix-compilation-with-libp11-version-0.4.7.patch b/net/openconnect/patches/0001-Fix-compilation-with-libp11-version-0.4.7.patch
deleted file mode 100644 (file)
index c6e139a..0000000
+++ /dev/null
@@ -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
-
diff --git a/net/openconnect/patches/010-Fix-compilation-without-deprecated-OpenSSL-1.1-APIs.patch b/net/openconnect/patches/010-Fix-compilation-without-deprecated-OpenSSL-1.1-APIs.patch
new file mode 100644 (file)
index 0000000..7321bb6
--- /dev/null
@@ -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
+
diff --git a/net/openconnect/patches/020-Fix-DTLS-bug-when-lacking-deprecated-APIs.patch b/net/openconnect/patches/020-Fix-DTLS-bug-when-lacking-deprecated-APIs.patch
new file mode 100644 (file)
index 0000000..e29f801
--- /dev/null
@@ -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
+
diff --git a/net/openconnect/patches/030-Disable-encrypt-then-mac-where-possible-with-DTLS-an.patch b/net/openconnect/patches/030-Disable-encrypt-then-mac-where-possible-with-DTLS-an.patch
new file mode 100644 (file)
index 0000000..bf5d10b
--- /dev/null
@@ -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
+