From bb1b62489e1dacac409010bd63bac7e70e19fedf Mon Sep 17 00:00:00 2001
From: Garrett Holmstrom <gholms@devzero.com>
Date: Mon, 11 Jan 2021 19:42:08 -0800
Subject: [PATCH 4/5] Add compatibility with OpenSSL 1.1

Backports 812cfa7a5c0d323e8f8b4f67a856e10471ec7829
---
 boost/asio/ssl/detail/impl/engine.ipp       |  2 +
 boost/asio/ssl/detail/impl/openssl_init.ipp | 20 +++++--
 boost/asio/ssl/impl/context.ipp             | 63 +++++++++++++++++----
 3 files changed, 68 insertions(+), 17 deletions(-)

diff --git a/boost/asio/ssl/detail/impl/engine.ipp b/boost/asio/ssl/detail/impl/engine.ipp
index 1a3e3336..9fdd3836 100644
--- a/boost/asio/ssl/detail/impl/engine.ipp
+++ b/boost/asio/ssl/detail/impl/engine.ipp
@@ -211,8 +211,10 @@ const boost::system::error_code& engine::map_error_code(
 
   // SSL v2 doesn't provide a protocol-level shutdown, so an eof on the
   // underlying transport is passed through.
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
   if (ssl_ && ssl_->version == SSL2_VERSION)
     return ec;
+#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)
 
   // Otherwise, the peer should have negotiated a proper shutdown.
   if ((::SSL_get_shutdown(ssl_) & SSL_RECEIVED_SHUTDOWN) == 0)
diff --git a/boost/asio/ssl/detail/impl/openssl_init.ipp b/boost/asio/ssl/detail/impl/openssl_init.ipp
index 8a6cb021..a0e68808 100644
--- a/boost/asio/ssl/detail/impl/openssl_init.ipp
+++ b/boost/asio/ssl/detail/impl/openssl_init.ipp
@@ -40,11 +40,13 @@ public:
     ::SSL_load_error_strings();        
     ::OpenSSL_add_all_algorithms();
 
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
     mutexes_.resize(::CRYPTO_num_locks());
     for (size_t i = 0; i < mutexes_.size(); ++i)
       mutexes_[i].reset(new boost::asio::detail::mutex);
     ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func);
     ::CRYPTO_set_id_callback(&do_init::openssl_id_func);
+#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)
 
 #if !defined(SSL_OP_NO_COMPRESSION) \
   && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
@@ -61,20 +63,24 @@ public:
 #endif // !defined(SSL_OP_NO_COMPRESSION)
        // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
 
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
     ::CRYPTO_set_id_callback(0);
     ::CRYPTO_set_locking_callback(0);
     ::ERR_free_strings();
-#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
-    ::ERR_remove_thread_state(NULL);
-#else // (OPENSSL_VERSION_NUMBER >= 0x10000000L)
-    ::ERR_remove_state(0);
-#endif // (OPENSSL_VERSION_NUMBER >= 0x10000000L)
     ::EVP_cleanup();
     ::CRYPTO_cleanup_all_ex_data();
+#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#if (OPENSSL_VERSION_NUMBER < 0x10000000L)
+    ::ERR_remove_state(0);
+#elif (OPENSSL_VERSION_NUMBER < 0x10100000L)
+    ::ERR_remove_thread_state(NULL);
+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
     ::CONF_modules_unload(1);
-#if !defined(OPENSSL_NO_ENGINE)
+#if !defined(OPENSSL_NO_ENGINE) \
+  && (OPENSSL_VERSION_NUMBER < 0x10100000L)
     ::ENGINE_cleanup();
 #endif // !defined(OPENSSL_NO_ENGINE)
+       // && (OPENSSL_VERSION_NUMBER < 0x10100000L)
   }
 
 #if !defined(SSL_OP_NO_COMPRESSION) \
@@ -103,10 +109,12 @@ private:
   static void openssl_locking_func(int mode, int n, 
     const char* /*file*/, int /*line*/)
   {
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
     if (mode & CRYPTO_LOCK)
       instance()->mutexes_[n]->lock();
     else
       instance()->mutexes_[n]->unlock();
+#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)
   }
 
   // Mutexes to be used in locking callbacks.
diff --git a/boost/asio/ssl/impl/context.ipp b/boost/asio/ssl/impl/context.ipp
index 9e7cc064..82591a76 100644
--- a/boost/asio/ssl/impl/context.ipp
+++ b/boost/asio/ssl/impl/context.ipp
@@ -69,7 +69,8 @@ context::context(context::method m)
 {
   switch (m)
   {
-#if defined(OPENSSL_NO_SSL2)
+#if defined(OPENSSL_NO_SSL2) \
+  || (OPENSSL_VERSION_NUMBER >= 0x10100000L)
   case context::sslv2:
   case context::sslv2_client:
   case context::sslv2_server:
@@ -77,6 +78,7 @@ context::context(context::method m)
         boost::asio::error::invalid_argument, "context");
     break;
 #else // defined(OPENSSL_NO_SSL2)
+      // || (OPENSSL_VERSION_NUMBER >= 0x10100000L)
   case context::sslv2:
     handle_ = ::SSL_CTX_new(::SSLv2_method());
     break;
@@ -87,6 +89,7 @@ context::context(context::method m)
     handle_ = ::SSL_CTX_new(::SSLv2_server_method());
     break;
 #endif // defined(OPENSSL_NO_SSL2)
+       // || (OPENSSL_VERSION_NUMBER >= 0x10100000L)
 #if defined(OPENSSL_NO_SSL3)
   case context::sslv3:
   case context::sslv3_client:
@@ -203,13 +206,22 @@ context::~context()
 {
   if (handle_)
   {
-    if (handle_->default_passwd_callback_userdata)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    void* cb_userdata = handle_->default_passwd_callback_userdata;
+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    if (cb_userdata)
     {
       detail::password_callback_base* callback =
         static_cast<detail::password_callback_base*>(
-            handle_->default_passwd_callback_userdata);
+            cb_userdata);
       delete callback;
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+      ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0);
+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
       handle_->default_passwd_callback_userdata = 0;
+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
     }
 
     if (SSL_CTX_get_app_data(handle_))
@@ -527,10 +539,17 @@ boost::system::error_code context::use_certificate_chain(
   bio_cleanup bio = { make_buffer_bio(chain) };
   if (bio.p)
   {
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
+    void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    pem_password_cb* callback = handle_->default_passwd_callback;
+    void* cb_userdata = handle_->default_passwd_callback_userdata;
+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
     x509_cleanup cert = {
       ::PEM_read_bio_X509_AUX(bio.p, 0,
-          handle_->default_passwd_callback,
-          handle_->default_passwd_callback_userdata) };
+          callback,
+          cb_userdata) };
     if (!cert.p)
     {
       ec = boost::system::error_code(ERR_R_PEM_LIB,
@@ -558,8 +577,8 @@ boost::system::error_code context::use_certificate_chain(
 #endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)
 
     while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
-          handle_->default_passwd_callback,
-          handle_->default_passwd_callback_userdata))
+          callback,
+          cb_userdata))
     {
       if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
       {
@@ -622,6 +641,14 @@ boost::system::error_code context::use_private_key(
 {
   ::ERR_clear_error();
 
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
+    void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    pem_password_cb* callback = handle_->default_passwd_callback;
+    void* cb_userdata = handle_->default_passwd_callback_userdata;
+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+
   bio_cleanup bio = { make_buffer_bio(private_key) };
   if (bio.p)
   {
@@ -679,6 +706,14 @@ boost::system::error_code context::use_rsa_private_key(
 {
   ::ERR_clear_error();
 
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
+    void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    pem_password_cb* callback = handle_->default_passwd_callback;
+    void* cb_userdata = handle_->default_passwd_callback_userdata;
+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+
   bio_cleanup bio = { make_buffer_bio(private_key) };
   if (bio.p)
   {
@@ -900,11 +935,17 @@ int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
 boost::system::error_code context::do_set_password_callback(
     detail::password_callback_base* callback, boost::system::error_code& ec)
 {
-  if (handle_->default_passwd_callback_userdata)
-    delete static_cast<detail::password_callback_base*>(
-        handle_->default_passwd_callback_userdata);
-
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+  void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
+  ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);
+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+  void* old_callback = handle_->default_passwd_callback_userdata;
   handle_->default_passwd_callback_userdata = callback;
+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+
+  if (old_callback)
+    delete static_cast<detail::password_callback_base*>(
+        old_callback);
 
   SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
 
-- 
2.29.0

