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.

139 lines
5.3 KiB

  1. From afb6442533dc7475ed61642c3f5b295db1e6f561 Mon Sep 17 00:00:00 2001
  2. From: Rosen Penev <rosenp@gmail.com>
  3. Date: Sun, 9 Jun 2019 23:40:21 -0700
  4. Subject: [PATCH] Fix DTLS bug when lacking deprecated APIs
  5. HAVE_DTLS12 is for DTLSv1_method. This causes dtls_method to be NULL and
  6. crash.
  7. [dwmw2: Rework it quite a bit more]
  8. Signed-off-by: Rosen Penev <rosenp@gmail.com>
  9. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
  10. ---
  11. configure.ac | 17 ++++++++++++++---
  12. openssl-dtls.c | 49 ++++++++++++++++++++++++++-----------------------
  13. 2 files changed, 40 insertions(+), 26 deletions(-)
  14. diff --git a/configure.ac b/configure.ac
  15. index 02096c51..f7557933 100644
  16. --- a/configure.ac
  17. +++ b/configure.ac
  18. @@ -455,11 +455,22 @@ case "$ssl_library" in
  19. AC_DEFINE(HAVE_DTLS1_STOP_TIMER, [1], [OpenSSL has dtls1_stop_timer() function])],
  20. [AC_MSG_RESULT(no)])
  21. - AC_MSG_CHECKING([for DTLSv1_2_client_method() in OpenSSL])
  22. + # DTLS_client_method() and DTLSv1_2_client_method() were both added between
  23. + # OpenSSL v1.0.1 and v1.0.2. DTLSV1.2_client_method() was later deprecated
  24. + # in v1.1.0 so we use DTLS_client_method() as our check for DTLSv1.2 support
  25. + # and that's what we actually use in openssl-dtls.c too.
  26. + AC_MSG_CHECKING([for DTLS_client_method() in OpenSSL])
  27. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <openssl/ssl.h>],
  28. - [DTLSv1_2_client_method();])],
  29. + [DTLS_client_method();])],
  30. [AC_MSG_RESULT(yes)
  31. - AC_DEFINE(HAVE_DTLS12, [1], [OpenSSL has DTLSv1_2_client_method() function])],
  32. + AC_DEFINE(HAVE_DTLS12, [1], [OpenSSL has DTLS_client_method() function])],
  33. + [AC_MSG_RESULT(no)])
  34. +
  35. + AC_MSG_CHECKING([for SSL_CTX_set_min_proto_version() in OpenSSL])
  36. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <openssl/ssl.h>],
  37. + [SSL_CTX_set_min_proto_version((void *)0, 0);])],
  38. + [AC_MSG_RESULT(yes)
  39. + AC_DEFINE(HAVE_SSL_CTX_PROTOVER, [1], [OpenSSL has SSL_CTX_set_min_proto_version() function])],
  40. [AC_MSG_RESULT(no)])
  41. AC_CHECK_FUNC(HMAC_CTX_copy,
  42. diff --git a/openssl-dtls.c b/openssl-dtls.c
  43. index 5086440f..9e3c5d46 100644
  44. --- a/openssl-dtls.c
  45. +++ b/openssl-dtls.c
  46. @@ -332,6 +332,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
  47. const char *cipher = vpninfo->dtls_cipher;
  48. #ifdef HAVE_DTLS12
  49. + /* These things should never happen unless they're supported */
  50. if (vpninfo->cisco_dtls12) {
  51. dtlsver = DTLS1_2_VERSION;
  52. } else if (!strcmp(cipher, "OC-DTLS1_2-AES128-GCM")) {
  53. @@ -349,16 +350,16 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
  54. if (!vpninfo->dtls_ctx) {
  55. #ifdef HAVE_DTLS12
  56. + /* If we can use SSL_CTX_set_min_proto_version, do so. */
  57. dtls_method = DTLS_client_method();
  58. #endif
  59. -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  60. +#ifndef HAVE_SSL_CTX_PROTOVER
  61. + /* If !HAVE_DTLS12, dtlsver *MUST* be DTLS1_BAD_VER because it's set
  62. + * at the top of the function and nothing can change it. */
  63. if (dtlsver == DTLS1_BAD_VER)
  64. dtls_method = DTLSv1_client_method();
  65. -#ifdef HAVE_DTLS12
  66. - else if (dtlsver == DTLS1_2_VERSION)
  67. - dtls_method = DTLSv1_2_client_method();
  68. -#endif
  69. #endif
  70. +
  71. vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
  72. if (!vpninfo->dtls_ctx) {
  73. vpn_progress(vpninfo, PRG_ERR,
  74. @@ -367,24 +368,26 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
  75. vpninfo->dtls_attempt_period = 0;
  76. return -EINVAL;
  77. }
  78. - if (dtlsver) {
  79. -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  80. - if (dtlsver == DTLS1_BAD_VER)
  81. - SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_CISCO_ANYCONNECT);
  82. -#else
  83. - if (!SSL_CTX_set_min_proto_version(vpninfo->dtls_ctx, dtlsver) ||
  84. - !SSL_CTX_set_max_proto_version(vpninfo->dtls_ctx, dtlsver)) {
  85. - vpn_progress(vpninfo, PRG_ERR,
  86. - _("Set DTLS CTX version failed\n"));
  87. - openconnect_report_ssl_errors(vpninfo);
  88. - SSL_CTX_free(vpninfo->dtls_ctx);
  89. - vpninfo->dtls_ctx = NULL;
  90. - vpninfo->dtls_attempt_period = 0;
  91. - return -EINVAL;
  92. - }
  93. +#ifdef HAVE_SSL_CTX_PROTOVER
  94. + if (dtlsver &&
  95. + (!SSL_CTX_set_min_proto_version(vpninfo->dtls_ctx, dtlsver) ||
  96. + !SSL_CTX_set_max_proto_version(vpninfo->dtls_ctx, dtlsver))) {
  97. + vpn_progress(vpninfo, PRG_ERR,
  98. + _("Set DTLS CTX version failed\n"));
  99. + openconnect_report_ssl_errors(vpninfo);
  100. + SSL_CTX_free(vpninfo->dtls_ctx);
  101. + vpninfo->dtls_ctx = NULL;
  102. + vpninfo->dtls_attempt_period = 0;
  103. + return -EINVAL;
  104. + }
  105. +#else /* !HAVE_SSL_CTX_PROTOVER */
  106. + /* If we used the legacy version-specific methods, we need the special
  107. + * way to make TLSv1_client_method() do DTLS1_BAD_VER. */
  108. + if (dtlsver == DTLS1_BAD_VER)
  109. + SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_CISCO_ANYCONNECT);
  110. #endif
  111. #if defined (HAVE_DTLS12) && !defined(OPENSSL_NO_PSK)
  112. - } else {
  113. + if (!dtlsver) {
  114. SSL_CTX_set_psk_client_callback(vpninfo->dtls_ctx, psk_callback);
  115. /* For PSK we override the DTLS master secret with one derived
  116. * from the HTTPS session. */
  117. @@ -401,9 +404,9 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
  118. }
  119. /* For SSL_CTX_set_cipher_list() */
  120. cipher = "PSK";
  121. -
  122. -#endif
  123. }
  124. +#endif /* OPENSSL_NO_PSK */
  125. +
  126. /* If we don't readahead, then we do short reads and throw
  127. away the tail of data packets. */
  128. SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
  129. --
  130. 2.17.1