openssl_init.ipp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //
  2. // ssl/detail/impl/openssl_init.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
  6. // Copyright (c) 2005-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. #ifndef ASIO_SSL_DETAIL_IMPL_OPENSSL_INIT_IPP
  12. #define ASIO_SSL_DETAIL_IMPL_OPENSSL_INIT_IPP
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  14. # pragma once
  15. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #include "asio/detail/config.hpp"
  17. #include <vector>
  18. #include "asio/detail/assert.hpp"
  19. #include "asio/detail/mutex.hpp"
  20. #include "asio/detail/tss_ptr.hpp"
  21. #include "asio/ssl/detail/openssl_init.hpp"
  22. #include "asio/ssl/detail/openssl_types.hpp"
  23. #include "asio/detail/push_options.hpp"
  24. namespace asio {
  25. namespace ssl {
  26. namespace detail {
  27. class openssl_init_base::do_init
  28. {
  29. public:
  30. do_init()
  31. {
  32. ::SSL_library_init();
  33. ::SSL_load_error_strings();
  34. ::OpenSSL_add_all_algorithms();
  35. mutexes_.resize(::CRYPTO_num_locks());
  36. for (size_t i = 0; i < mutexes_.size(); ++i)
  37. mutexes_[i].reset(new asio::detail::mutex);
  38. ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func);
  39. ::CRYPTO_set_id_callback(&do_init::openssl_id_func);
  40. #if !defined(SSL_OP_NO_COMPRESSION) \
  41. && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  42. null_compression_methods_ = sk_SSL_COMP_new_null();
  43. #endif // !defined(SSL_OP_NO_COMPRESSION)
  44. // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  45. }
  46. ~do_init()
  47. {
  48. #if !defined(SSL_OP_NO_COMPRESSION) \
  49. && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  50. sk_SSL_COMP_free(null_compression_methods_);
  51. #endif // !defined(SSL_OP_NO_COMPRESSION)
  52. // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  53. ::CRYPTO_set_id_callback(0);
  54. ::CRYPTO_set_locking_callback(0);
  55. ::ERR_free_strings();
  56. #if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
  57. ::ERR_remove_thread_state(NULL);
  58. #else // (OPENSSL_VERSION_NUMBER >= 0x10000000L)
  59. ::ERR_remove_state(0);
  60. #endif // (OPENSSL_VERSION_NUMBER >= 0x10000000L)
  61. ::EVP_cleanup();
  62. ::CRYPTO_cleanup_all_ex_data();
  63. ::CONF_modules_unload(1);
  64. #if !defined(OPENSSL_NO_ENGINE)
  65. ::ENGINE_cleanup();
  66. #endif // !defined(OPENSSL_NO_ENGINE)
  67. }
  68. #if !defined(SSL_OP_NO_COMPRESSION) \
  69. && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  70. STACK_OF(SSL_COMP)* get_null_compression_methods() const
  71. {
  72. return null_compression_methods_;
  73. }
  74. #endif // !defined(SSL_OP_NO_COMPRESSION)
  75. // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  76. private:
  77. static unsigned long openssl_id_func()
  78. {
  79. #if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
  80. return ::GetCurrentThreadId();
  81. #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
  82. void* id = instance()->thread_id_;
  83. if (id == 0)
  84. instance()->thread_id_ = id = &id; // Ugh.
  85. ASIO_ASSERT(sizeof(unsigned long) >= sizeof(void*));
  86. return reinterpret_cast<unsigned long>(id);
  87. #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
  88. }
  89. static void openssl_locking_func(int mode, int n,
  90. const char* /*file*/, int /*line*/)
  91. {
  92. if (mode & CRYPTO_LOCK)
  93. instance()->mutexes_[n]->lock();
  94. else
  95. instance()->mutexes_[n]->unlock();
  96. }
  97. // Mutexes to be used in locking callbacks.
  98. std::vector<asio::detail::shared_ptr<
  99. asio::detail::mutex> > mutexes_;
  100. #if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)
  101. // The thread identifiers to be used by openssl.
  102. asio::detail::tss_ptr<void> thread_id_;
  103. #endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)
  104. #if !defined(SSL_OP_NO_COMPRESSION) \
  105. && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  106. STACK_OF(SSL_COMP)* null_compression_methods_;
  107. #endif // !defined(SSL_OP_NO_COMPRESSION)
  108. // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  109. };
  110. asio::detail::shared_ptr<openssl_init_base::do_init>
  111. openssl_init_base::instance()
  112. {
  113. static asio::detail::shared_ptr<do_init> init(new do_init);
  114. return init;
  115. }
  116. #if !defined(SSL_OP_NO_COMPRESSION) \
  117. && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  118. STACK_OF(SSL_COMP)* openssl_init_base::get_null_compression_methods()
  119. {
  120. return instance()->get_null_compression_methods();
  121. }
  122. #endif // !defined(SSL_OP_NO_COMPRESSION)
  123. // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  124. } // namespace detail
  125. } // namespace ssl
  126. } // namespace asio
  127. #include "asio/detail/pop_options.hpp"
  128. #endif // ASIO_SSL_DETAIL_IMPL_OPENSSL_INIT_IPP