diff options
Diffstat (limited to 'ace/SSL/SSL_Context.cpp')
-rw-r--r-- | ace/SSL/SSL_Context.cpp | 567 |
1 files changed, 0 insertions, 567 deletions
diff --git a/ace/SSL/SSL_Context.cpp b/ace/SSL/SSL_Context.cpp deleted file mode 100644 index 76ad6aafc29..00000000000 --- a/ace/SSL/SSL_Context.cpp +++ /dev/null @@ -1,567 +0,0 @@ -#include "SSL_Context.h" - -#include "sslconf.h" - -#if !defined(__ACE_INLINE__) -#include "SSL_Context.inl" -#endif /* __ACE_INLINE__ */ - -#include "ace/Guard_T.h" -#include "ace/Object_Manager.h" -#include "ace/Log_Msg.h" -#include "ace/Singleton.h" -#include "ace/Synch_Traits.h" -#include "ace/ACE.h" -#include "ace/OS_NS_errno.h" -#include "ace/OS_NS_string.h" - -#ifdef ACE_HAS_THREADS -# include "ace/Thread_Mutex.h" -# include "ace/Synch_Traits.h" -# include "ace/Auto_Ptr.h" -# include "ace/OS_NS_Thread.h" -#endif /* ACE_HAS_THREADS */ - -#include <openssl/x509.h> -#include <openssl/err.h> -#include <openssl/rand.h> - -ACE_RCSID (ACE_SSL, - SSL_Context, - "$Id$") - - -namespace -{ - /// Reference count of the number of times the ACE_SSL_Context was - /// initialized. - int ssl_library_init_count = 0; - - // @@ This should also be done with a singleton, otherwise it is not - // thread safe and/or portable to some weird platforms... - -#ifdef ACE_HAS_THREADS - /// Array of mutexes used internally by OpenSSL when the SSL - /// application is multithreaded. - ACE_Auto_Basic_Array_Ptr<ACE_SYNCH_MUTEX> ssl_locks; - - // @@ This should also be managed by a singleton. -#endif -} - -#ifdef ACE_HAS_THREADS - -# if (defined (ACE_HAS_VERSIONED_NAMESPACE) \ - && ACE_HAS_VERSIONED_NAMESPACE == 1) \ - && !(defined (_MSC_VER) && _MSC_VER <= 1200) -// MSVC++ 6's preprocessor can't handle macro expansions required by -// the versioned namespace support. *sigh* - -# define ACE_SSL_LOCKING_CALLBACK_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_locking_callback) -# define ACE_SSL_THREAD_ID_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_thread_id) - -# else - -# define ACE_SSL_LOCKING_CALLBACK_NAME ACE_SSL_locking_callback -# define ACE_SSL_THREAD_ID_NAME ACE_SSL_thread_id - -# endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */ - - - -extern "C" -{ - void - ACE_SSL_LOCKING_CALLBACK_NAME (int mode, - int type, - const char * /* file */, - int /* line */) - { - // #ifdef undef - // fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n", - // CRYPTO_thread_id(), - // (mode&CRYPTO_LOCK)?"l":"u", - // (type&CRYPTO_READ)?"r":"w",file,line); - // #endif - // /* - // if (CRYPTO_LOCK_SSL_CERT == type) - // fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n", - // CRYPTO_thread_id(), - // mode,file,line); - // */ - if (mode & CRYPTO_LOCK) - (void) ssl_locks[type].acquire (); - else - (void) ssl_locks[type].release (); - } - - // ------------------------------- - - // Return the current thread ID. OpenSSL uses this on platforms - // that need it. - unsigned long - ACE_SSL_THREAD_ID_NAME (void) - { - return (unsigned long) ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::thr_self (); - } -} -#endif /* ACE_HAS_THREADS */ - - -// **************************************************************** - -ACE_BEGIN_VERSIONED_NAMESPACE_DECL - -ACE_SSL_Context::ACE_SSL_Context (void) - : context_ (0), - mode_ (-1), - default_verify_mode_ (SSL_VERIFY_NONE), - have_ca_ (0) -{ - ACE_SSL_Context::ssl_library_init (); -} - -ACE_SSL_Context::~ACE_SSL_Context (void) -{ - if (this->context_) - { - ::SSL_CTX_free (this->context_); - this->context_ = 0; - } - - ACE_SSL_Context::ssl_library_fini (); -} - -ACE_SSL_Context * -ACE_SSL_Context::instance (void) -{ - return ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::instance (); -} - -void -ACE_SSL_Context::ssl_library_init (void) -{ - ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, - ace_ssl_mon, - *ACE_Static_Object_Lock::instance ())); - - if (ssl_library_init_count == 0) - { - // Initialize the locking callbacks before initializing anything - // else. -#ifdef ACE_HAS_THREADS - int const num_locks = ::CRYPTO_num_locks (); - - ssl_locks.reset (new ACE_SYNCH_MUTEX[num_locks]); - -# if !defined (WIN32) - // This call isn't necessary on some platforms. See the CRYPTO - // library's threads(3) man page for details. - ::CRYPTO_set_id_callback (ACE_SSL_THREAD_ID_NAME); -# endif /* !WIN32 */ - ::CRYPTO_set_locking_callback (ACE_SSL_LOCKING_CALLBACK_NAME); -#endif /* ACE_HAS_THREADS */ - - ::SSLeay_add_ssl_algorithms (); - ::SSL_load_error_strings (); - - // Seed the random number generator. Note that the random - // number generator can be seeded more than once to "stir" its - // state. - -#ifdef WIN32 - // Seed the random number generator by sampling the screen. - ::RAND_screen (); -#endif /* WIN32 */ - -#if OPENSSL_VERSION_NUMBER >= 0x00905100L - // OpenSSL < 0.9.5 doesn't have EGD support. - - const char *egd_socket_file = - ACE_OS::getenv (ACE_SSL_EGD_FILE_ENV); - - if (egd_socket_file != 0) - (void) this->egd_file (egd_socket_file); -#endif /* OPENSSL_VERSION_NUMBER */ - - const char *rand_file = - ACE_OS::getenv (ACE_SSL_RAND_FILE_ENV); - - if (rand_file != 0) - (void) this->seed_file (rand_file); - - // Initialize the mutexes that will be used by the SSL and - // crypto library. - - } - - ++ssl_library_init_count; -} - -void -ACE_SSL_Context::ssl_library_fini (void) -{ - ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, - ace_ssl_mon, - *ACE_Static_Object_Lock::instance ())); - - --ssl_library_init_count; - if (ssl_library_init_count == 0) - { - ::ERR_free_strings (); - ::EVP_cleanup (); - - // Clean up the locking callbacks after everything else has been - // cleaned up. -#ifdef ACE_HAS_THREADS - ::CRYPTO_set_locking_callback (0); -#endif /* ACE_HAS_THREADS */ - } -} - -int -ACE_SSL_Context::set_mode (int mode) -{ - ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, - ace_ssl_mon, - *ACE_Static_Object_Lock::instance (), - -1)); - - if (this->context_ != 0) - return -1; - - SSL_METHOD *method = 0; - - switch (mode) - { - case ACE_SSL_Context::SSLv2_client: - method = ::SSLv2_client_method (); - break; - case ACE_SSL_Context::SSLv2_server: - method = ::SSLv2_server_method (); - break; - case ACE_SSL_Context::SSLv2: - method = ::SSLv2_method (); - break; - case ACE_SSL_Context::SSLv3_client: - method = ::SSLv3_client_method (); - break; - case ACE_SSL_Context::SSLv3_server: - method = ::SSLv3_server_method (); - break; - case ACE_SSL_Context::SSLv3: - method = ::SSLv3_method (); - break; - case ACE_SSL_Context::SSLv23_client: - method = ::SSLv23_client_method (); - break; - case ACE_SSL_Context::SSLv23_server: - method = ::SSLv23_server_method (); - break; - case ACE_SSL_Context::SSLv23: - method = ::SSLv23_method (); - break; - case ACE_SSL_Context::TLSv1_client: - method = ::TLSv1_client_method (); - break; - case ACE_SSL_Context::TLSv1_server: - method = ::TLSv1_server_method (); - break; - case ACE_SSL_Context::TLSv1: - method = ::TLSv1_method (); - break; - default: - method = ::SSLv3_method (); - break; - } - - this->context_ = ::SSL_CTX_new (method); - if (this->context_ == 0) - return -1; - - this->mode_ = mode; - - // Load the trusted certificate authority (default) certificate - // locations. But do not return -1 on error, doing so confuses CTX - // allocation (severe error) with the less important loading of CA - // certificate location error. If it is important for your - // application then call ACE_SSL_Context::have_trusted_ca(), - // immediately following this call to set_mode(). - (void) this->load_trusted_ca (); - - return 0; -} - -int -ACE_SSL_Context::load_trusted_ca (const char* ca_file, const char* ca_dir) -{ - this->check_context (); - - if (ca_file == 0) - { - // Use the default environment settings. - ca_file = ACE_OS::getenv (ACE_SSL_CERT_FILE_ENV); - if (ca_file == 0) - ca_file = ACE_DEFAULT_SSL_CERT_FILE; - } - - if (ca_dir == 0) - { - // Use the default environment settings. - ca_dir = ACE_OS::getenv (ACE_SSL_CERT_DIR_ENV); - if (ca_dir == 0) - ca_dir = ACE_DEFAULT_SSL_CERT_DIR; - } - - // NOTE: SSL_CTX_load_verify_locations() returns 0 on error. - if (::SSL_CTX_load_verify_locations (this->context_, - ca_file, - ca_dir) <= 0) - { - if (ACE::debug ()) - ACE_SSL_Context::report_error (); - return -1; - } - else - { - ++this->have_ca_; - - // for TLS/SSL servers scan all certificates in ca_file and list - // then as acceptable CAs when requesting a client certificate. - if (mode_ == SSLv23 - || mode_ == SSLv23_server - || mode_ == TLSv1 - || mode_ == TLSv1_server - || mode_ == SSLv3 - || mode_ == SSLv3_server - || mode_ == SSLv2 - || mode_ == SSLv2_server) - { - STACK_OF (X509_NAME) * cert_names; - cert_names = ::SSL_CTX_get_client_CA_list (this->context_); - - if (cert_names == 0) - { - // Set the first certificate authorith list. - cert_names = ::SSL_load_client_CA_file (ca_file); - if (cert_names != 0 ) - ::SSL_CTX_set_client_CA_list (this->context_, - cert_names); - } - else - { - // Add new certificate names to the list. - if (!::SSL_add_file_cert_subjects_to_stack (cert_names, - ca_file)) - cert_names = 0; - } - - if (cert_names == 0) - { - if (ACE::debug ()) - ACE_SSL_Context::report_error (); - return -1; - } - - // @todo - // If warranted do the same for ca_dir when the function - // SSL_add_dir_cert_subjects_to_stack() is portable to - // WIN32, VMS, MAC_OS_pre_X (nb. it is not defined for those - // platforms by OpenSSL). - } - } - - return 0; -} - - -int -ACE_SSL_Context::private_key (const char *file_name, - int type) -{ - if (this->private_key_.type () != -1) - return 0; - - this->check_context (); - - this->private_key_ = ACE_SSL_Data_File (file_name, type); - - if (::SSL_CTX_use_PrivateKey_file (this->context_, - this->private_key_.file_name (), - this->private_key_.type ()) <= 0) - return -1; - else - return this->verify_private_key (); -} - -int -ACE_SSL_Context::verify_private_key (void) -{ - this->check_context (); - - return (::SSL_CTX_check_private_key (this->context_) <= 0 ? -1 : 0); -} - -int -ACE_SSL_Context::certificate (const char *file_name, - int type) -{ - if (this->certificate_.type () != -1) - return 0; - - this->certificate_ = ACE_SSL_Data_File (file_name, type); - - this->check_context (); - - if (::SSL_CTX_use_certificate_file (this->context_, - this->certificate_.file_name (), - this->certificate_.type ()) <= 0) - return -1; - else - return 0; -} - -void -ACE_SSL_Context::set_verify_peer (int strict, int once, int depth) -{ - this->check_context (); - - // Setup the peer verififcation mode. - - int verify_mode = SSL_VERIFY_PEER; - if (once) - verify_mode |= SSL_VERIFY_CLIENT_ONCE; - if (strict) - verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - - // set the default verify mode - this->default_verify_mode (verify_mode); - - // Set the max certificate depth but later let the verify_callback - // catch the depth error by adding one to the required depth. - if (depth > 0) - ::SSL_CTX_set_verify_depth (this->context_, depth + 1); -} - - -int -ACE_SSL_Context::random_seed (const char * seed) -{ - ::RAND_seed (seed, ACE_OS::strlen (seed)); - -#if OPENSSL_VERSION_NUMBER >= 0x00905100L - // RAND_status() returns 1 if the PRNG has enough entropy. - return (::RAND_status () == 1 ? 0 : -1); -#else - return 0; // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status(). -#endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */ -} - -int -ACE_SSL_Context::egd_file (const char * socket_file) -{ -#if OPENSSL_VERSION_NUMBER < 0x00905100L - // OpenSSL < 0.9.5 doesn't have EGD support. - ACE_UNUSED_ARG (socket_file); - ACE_NOTSUP_RETURN (-1); -#else - // RAND_egd() returns the amount of entropy used to seed the random - // number generator. The actually value should be greater than 16, - // i.e. 128 bits. - if (::RAND_egd (socket_file) > 0) - return 0; - else - return -1; -#endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */ -} - -int -ACE_SSL_Context::seed_file (const char * seed_file, long bytes) -{ - // RAND_load_file() returns the number of bytes used to seed the - // random number generator. - if (::RAND_load_file (seed_file, bytes) > 0) - return 0; - else - return -1; -} - -void -ACE_SSL_Context::report_error (unsigned long error_code) -{ - if (error_code == 0) - return; - - char error_string[256]; - - (void) ::ERR_error_string (error_code, error_string); - - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("ACE_SSL (%P|%t) error code: %u - %C\n"), - error_code, - error_string)); -} - -void -ACE_SSL_Context::report_error (void) -{ - unsigned long error = ::ERR_get_error (); - ACE_SSL_Context::report_error (error); - ACE_OS::last_error (error); -} - -int -ACE_SSL_Context::dh_params (const char *file_name, - int type) -{ - if (this->dh_params_.type () != -1) - return 0; - - this->dh_params_ = ACE_SSL_Data_File (file_name, type); - - this->check_context (); - - { - // For now we only support PEM encodings - if (this->dh_params_.type () != SSL_FILETYPE_PEM) - return -1; - - // Swiped from Rescorla's examples and the OpenSSL s_server.c app - DH * ret=0; - BIO * bio = 0; - - if ((bio = ::BIO_new_file (this->dh_params_.file_name (), "r")) == NULL) - return -1; - - ret = PEM_read_bio_DHparams (bio, NULL, NULL, NULL); - BIO_free (bio); - - if (ret == 0) - return -1; - - if(::SSL_CTX_set_tmp_dh (this->context_, ret) < 0) - return -1; - DH_free (ret); - } - - return 0; -} - -// **************************************************************** - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) - -template class ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>; - -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) - -#pragma instantiate ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX> - -#elif defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION) - -template ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX> * - ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::singleton_; - -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ - -ACE_END_VERSIONED_NAMESPACE_DECL |