mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-22 21:26:23 +00:00
Directory Structure [step 1]: moving files
working on #672 NOTE: This commit can't be compiled!!
This commit is contained in:
795
deps/acelite/ace/SSL/SSL_Context.cpp
vendored
Normal file
795
deps/acelite/ace/SSL/SSL_Context.cpp
vendored
Normal file
@@ -0,0 +1,795 @@
|
||||
#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_Category.h"
|
||||
#include "ace/Singleton.h"
|
||||
#include "ace/Synch_Traits.h"
|
||||
#include "ace/Truncate.h"
|
||||
#include "ace/ACE.h"
|
||||
#include "ace/INET_Addr.h"
|
||||
#include "ace/OS_NS_errno.h"
|
||||
#include "ace/OS_NS_string.h"
|
||||
#include "ace/OS_NS_ctype.h"
|
||||
|
||||
#ifdef ACE_HAS_THREADS
|
||||
# include "ace/Thread_Mutex.h"
|
||||
# include "ace/OS_NS_Thread.h"
|
||||
#endif /* ACE_HAS_THREADS */
|
||||
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/safestack.h>
|
||||
|
||||
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_SSL_Context::lock_type * ssl_locks = 0;
|
||||
|
||||
// @@ This should also be managed by a singleton.
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ACE_HAS_THREADS
|
||||
|
||||
# if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
|
||||
# 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
|
||||
|
||||
#ifdef ACE_HAS_THREADS
|
||||
ACE_SSL_Context::lock_type * ACE_SSL_Context::locks_ = 0;
|
||||
#endif /* ACE_HAS_THREADS */
|
||||
|
||||
ACE_SSL_Context::ACE_SSL_Context (void)
|
||||
: context_ (0),
|
||||
mode_ (-1),
|
||||
default_verify_mode_ (SSL_VERIFY_NONE),
|
||||
default_verify_callback_ (0),
|
||||
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_Unmanaged_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 ();
|
||||
|
||||
this->locks_ = new lock_type[num_locks];
|
||||
ssl_locks = this->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);
|
||||
ssl_locks = 0;
|
||||
|
||||
delete [] this->locks_;
|
||||
this->locks_ = 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;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000002
|
||||
const SSL_METHOD *method = 0;
|
||||
#else
|
||||
SSL_METHOD *method = 0;
|
||||
#endif
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
#if !defined (OPENSSL_NO_SSL2)
|
||||
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;
|
||||
#endif /* OPENSSL_NO_SSL2 */
|
||||
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;
|
||||
#if defined(TLS1_1_VERSION) && (TLS_MAX_VERSION >= TLS1_1_VERSION)
|
||||
case ACE_SSL_Context::TLSv1_1_client:
|
||||
method = ::TLSv1_1_client_method ();
|
||||
break;
|
||||
case ACE_SSL_Context::TLSv1_1_server:
|
||||
method = ::TLSv1_1_server_method ();
|
||||
break;
|
||||
case ACE_SSL_Context::TLSv1_1:
|
||||
method = ::TLSv1_1_method ();
|
||||
break;
|
||||
#endif
|
||||
#if defined(TLS1_2_VERSION) && (TLS_MAX_VERSION >= TLS1_2_VERSION)
|
||||
case ACE_SSL_Context::TLSv1_2_client:
|
||||
method = ::TLSv1_2_client_method ();
|
||||
break;
|
||||
case ACE_SSL_Context::TLSv1_2_server:
|
||||
method = ::TLSv1_2_server_method ();
|
||||
break;
|
||||
case ACE_SSL_Context::TLSv1_2:
|
||||
method = ::TLSv1_2_method ();
|
||||
break;
|
||||
#endif
|
||||
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::filter_versions (const char* versionlist)
|
||||
{
|
||||
this->check_context ();
|
||||
|
||||
ACE_CString vlist = versionlist;
|
||||
ACE_CString seplist = " ,;";
|
||||
ACE_CString::size_type pos = 0;
|
||||
bool match = false;
|
||||
|
||||
for (; pos < vlist.length (); pos++)
|
||||
{
|
||||
vlist[pos] = ACE_OS::ace_tolower (vlist[pos]);
|
||||
}
|
||||
|
||||
#if defined (SSL_OP_NO_SSLv2)
|
||||
pos = vlist.find("sslv2");
|
||||
match = pos != ACE_CString::npos &&
|
||||
(pos == vlist.length () - 5 ||
|
||||
seplist.find (vlist[pos + 5]) != ACE_CString::npos);
|
||||
if (!match)
|
||||
{
|
||||
::SSL_CTX_set_options (this->context_, SSL_OP_NO_SSLv2);
|
||||
}
|
||||
#endif /* SSL_OP_NO_SSLv2 */
|
||||
|
||||
#if defined (SSL_OP_NO_SSLv3)
|
||||
pos = vlist.find("sslv3");
|
||||
match = pos != ACE_CString::npos &&
|
||||
(pos == vlist.length () - 5 ||
|
||||
seplist.find (vlist[pos + 5]) != ACE_CString::npos);
|
||||
if (!match)
|
||||
{
|
||||
::SSL_CTX_set_options (this->context_, SSL_OP_NO_SSLv3);
|
||||
}
|
||||
#endif /* SSL_OP_NO_SSLv3 */
|
||||
|
||||
#if defined (SSL_OP_NO_TLSv1)
|
||||
pos = vlist.find("tlsv1");
|
||||
match = pos != ACE_CString::npos &&
|
||||
(pos == vlist.length () - 5 ||
|
||||
seplist.find (vlist[pos + 5]) != ACE_CString::npos);
|
||||
if (!match)
|
||||
{
|
||||
::SSL_CTX_set_options (this->context_, SSL_OP_NO_TLSv1);
|
||||
}
|
||||
#endif /* SSL_OP_NO_TLSv1 */
|
||||
|
||||
#if defined (SSL_OP_NO_TLSv1_1)
|
||||
pos = vlist.find("tlsv1.1");
|
||||
match = pos != ACE_CString::npos &&
|
||||
(pos == vlist.length () - 7 ||
|
||||
seplist.find (vlist[pos + 7]) != ACE_CString::npos);
|
||||
if (!match)
|
||||
{
|
||||
::SSL_CTX_set_options (this->context_, SSL_OP_NO_TLSv1_1);
|
||||
}
|
||||
#endif /* SSL_OP_NO_TLSv1_1 */
|
||||
|
||||
#if defined (SSL_OP_NO_TLSv1_2)
|
||||
pos = vlist.find("tlsv1.2");
|
||||
match = pos != ACE_CString::npos &&
|
||||
(pos == vlist.length () - 7 ||
|
||||
seplist.find (vlist[pos + 7]) != ACE_CString::npos);
|
||||
if (!match)
|
||||
{
|
||||
::SSL_CTX_set_options (this->context_, SSL_OP_NO_TLSv1_2);
|
||||
}
|
||||
#endif /* SSL_OP_NO_TLSv1_2 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ACE_SSL_Context::check_host (const ACE_INET_Addr &host, SSL *peerssl)
|
||||
{
|
||||
#if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10002001L)
|
||||
|
||||
this->check_context ();
|
||||
|
||||
int result = 0;
|
||||
char name[MAXHOSTNAMELEN+1];
|
||||
|
||||
if (peerssl == 0 || host.get_host_name (name, MAXHOSTNAMELEN) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
X509* cert = ::SSL_get_peer_certificate (peerssl);
|
||||
if (cert == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char *peer = 0;
|
||||
char **peerarg = ACE::debug () ? &peer : 0;
|
||||
int flags = X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT;
|
||||
size_t len = ACE_OS::strlen (name);
|
||||
|
||||
result = ::X509_check_host (cert, name, len, flags, peerarg);
|
||||
|
||||
if (ACE::debug ())
|
||||
{
|
||||
ACELIB_DEBUG ((LM_DEBUG,
|
||||
ACE_TEXT ("ACE (%P|%t) SSL_Context::check_host ")
|
||||
ACE_TEXT ("name <%s> returns %d, peer <%s>\n"),
|
||||
name, result, peer));
|
||||
}
|
||||
if (peer != 0)
|
||||
{
|
||||
::OPENSSL_free (peer);
|
||||
}
|
||||
|
||||
::X509_free (cert);
|
||||
|
||||
return result == 1;
|
||||
#else
|
||||
ACE_UNUSED_ARG (host);
|
||||
ACE_UNUSED_ARG (peerssl);
|
||||
|
||||
return false;
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
}
|
||||
|
||||
int
|
||||
ACE_SSL_Context::load_trusted_ca (const char* ca_file,
|
||||
const char* ca_dir,
|
||||
bool use_env_defaults)
|
||||
{
|
||||
this->check_context ();
|
||||
|
||||
if (ca_file == 0 && use_env_defaults)
|
||||
{
|
||||
// Use the default environment settings.
|
||||
ca_file = ACE_OS::getenv (ACE_SSL_CERT_FILE_ENV);
|
||||
#ifdef ACE_DEFAULT_SSL_CERT_FILE
|
||||
if (ca_file == 0)
|
||||
ca_file = ACE_DEFAULT_SSL_CERT_FILE;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ca_dir == 0 && use_env_defaults)
|
||||
{
|
||||
// Use the default environment settings.
|
||||
ca_dir = ACE_OS::getenv (ACE_SSL_CERT_DIR_ENV);
|
||||
#ifdef ACE_DEFAULT_SSL_CERT_DIR
|
||||
if (ca_dir == 0)
|
||||
ca_dir = ACE_DEFAULT_SSL_CERT_DIR;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
++this->have_ca_;
|
||||
|
||||
// For TLS/SSL servers scan all certificates in ca_file and ca_dir and
|
||||
// list them as acceptable CAs when requesting a client certificate.
|
||||
if (mode_ == SSLv23
|
||||
|| mode_ == SSLv23_server
|
||||
|| mode_ == TLSv1
|
||||
|| mode_ == TLSv1_server
|
||||
#if !defined (OPENSSL_NO_SSL2)
|
||||
|| mode_ == SSLv2
|
||||
|| mode_ == SSLv2_server
|
||||
#endif /* !OPENSSL_NO_SSL2 */
|
||||
|| mode_ == SSLv3
|
||||
|| mode_ == SSLv3_server)
|
||||
{
|
||||
// Note: The STACK_OF(X509_NAME) pointer is a copy of the pointer in
|
||||
// the CTX; any changes to it by way of these function calls will
|
||||
// change the CTX directly.
|
||||
STACK_OF (X509_NAME) * cert_names = 0;
|
||||
cert_names = ::SSL_CTX_get_client_CA_list (this->context_);
|
||||
bool error = false;
|
||||
|
||||
// Add CAs from both the file and dir, if specified. There should
|
||||
// already be a STACK_OF(X509_NAME) in the CTX, but if not, we create
|
||||
// one.
|
||||
if (ca_file)
|
||||
{
|
||||
if (cert_names == 0)
|
||||
{
|
||||
if ((cert_names = ::SSL_load_client_CA_file (ca_file)) != 0)
|
||||
::SSL_CTX_set_client_CA_list (this->context_, cert_names);
|
||||
else
|
||||
error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new certificate names to the list.
|
||||
error = (0 == ::SSL_add_file_cert_subjects_to_stack (cert_names,
|
||||
ca_file));
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (ACE::debug ())
|
||||
ACE_SSL_Context::report_error ();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// SSL_add_dir_cert_subjects_to_stack is defined at 0.9.8a (but not
|
||||
// on OpenVMS or Mac Classic); it may be available earlier. Change
|
||||
// this comparison if so. It's still (1.0.1g) broken on windows too.
|
||||
#if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090801fL)
|
||||
# if !defined (OPENSSL_SYS_VMS) && !defined (OPENSSL_SYS_MACINTOSH_CLASSIC)
|
||||
# if !defined (OPENSSL_SYS_WIN32)
|
||||
|
||||
if (ca_dir != 0)
|
||||
{
|
||||
if (cert_names == 0)
|
||||
{
|
||||
if ((cert_names = sk_X509_NAME_new_null ()) == 0)
|
||||
{
|
||||
if (ACE::debug ())
|
||||
ACE_SSL_Context::report_error ();
|
||||
return -1;
|
||||
}
|
||||
::SSL_CTX_set_client_CA_list (this->context_, cert_names);
|
||||
}
|
||||
if (0 == ::SSL_add_dir_cert_subjects_to_stack (cert_names, ca_dir))
|
||||
{
|
||||
if (ACE::debug ())
|
||||
ACE_SSL_Context::report_error ();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
# endif /* !OPENSSL_SYS_WIN32 */
|
||||
# endif /* !OPENSSL_SYS_VMS && !OPENSSL_SYS_MACINTOSH_CLASSIC */
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0.9.8a release */
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
this->private_key_ = ACE_SSL_Data_File ();
|
||||
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)
|
||||
{
|
||||
this->certificate_ = ACE_SSL_Data_File ();
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ACE_SSL_Context::certificate (X509* cert)
|
||||
{
|
||||
// Is it really a good idea to return 0 if we're not setting the
|
||||
// certificate?
|
||||
if (this->certificate_.type () != -1)
|
||||
return 0;
|
||||
|
||||
this->check_context();
|
||||
|
||||
if (::SSL_CTX_use_certificate (this->context_, cert) <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No file is associated with the certificate, set this to a fictional
|
||||
// value so we don't reset it later.
|
||||
this->certificate_ = ACE_SSL_Data_File ("MEMORY CERTIFICATE");
|
||||
|
||||
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)
|
||||
{
|
||||
int len = ACE_Utils::truncate_cast<int> (ACE_OS::strlen (seed));
|
||||
::RAND_seed (seed, len);
|
||||
|
||||
#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 actual 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 the file reads ok, check RAND_status to
|
||||
// see if it got enough entropy.
|
||||
if (::RAND_load_file (seed_file, bytes) > 0)
|
||||
#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 */
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
ACE_SSL_Context::report_error (unsigned long error_code)
|
||||
{
|
||||
if (error_code == 0)
|
||||
return;
|
||||
|
||||
char error_string[256];
|
||||
|
||||
// OpenSSL < 0.9.6a doesn't have ERR_error_string_n() function.
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x0090601fL
|
||||
(void) ::ERR_error_string_n (error_code, error_string, sizeof error_string);
|
||||
#else /* OPENSSL_VERSION_NUMBER >= 0x0090601fL */
|
||||
(void) ::ERR_error_string (error_code, error_string);
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x0090601fL */
|
||||
|
||||
ACELIB_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 err = ::ERR_get_error ();
|
||||
ACE_SSL_Context::report_error (err);
|
||||
ACE_OS::last_error (err);
|
||||
}
|
||||
|
||||
int
|
||||
ACE_SSL_Context::dh_params (const char *file_name,
|
||||
int type)
|
||||
{
|
||||
if (this->dh_params_.type () != -1)
|
||||
return 0;
|
||||
|
||||
// For now we only support PEM encodings
|
||||
if (type != SSL_FILETYPE_PEM)
|
||||
return -1;
|
||||
|
||||
this->dh_params_ = ACE_SSL_Data_File (file_name, type);
|
||||
|
||||
this->check_context ();
|
||||
|
||||
{
|
||||
// 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")) == 0)
|
||||
{
|
||||
this->dh_params_ = ACE_SSL_Data_File ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = PEM_read_bio_DHparams (bio, 0, 0, 0);
|
||||
BIO_free (bio);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
this->dh_params_ = ACE_SSL_Data_File ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (::SSL_CTX_set_tmp_dh (this->context_, ret) < 0)
|
||||
{
|
||||
this->dh_params_ = ACE_SSL_Data_File ();
|
||||
return -1;
|
||||
}
|
||||
DH_free (ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ****************************************************************
|
||||
ACE_SINGLETON_TEMPLATE_INSTANTIATE(ACE_Unmanaged_Singleton, ACE_SSL_Context, ACE_SYNCH_MUTEX)
|
||||
|
||||
ACE_END_VERSIONED_NAMESPACE_DECL
|
||||
Reference in New Issue
Block a user