|
|
- 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
-
|