00001 #include "SSL_Context.h"
00002
00003 #include "sslconf.h"
00004
00005 #if !defined(__ACE_INLINE__)
00006 #include "SSL_Context.inl"
00007 #endif
00008
00009 #include "ace/Guard_T.h"
00010 #include "ace/Object_Manager.h"
00011 #include "ace/Log_Msg.h"
00012 #include "ace/Singleton.h"
00013 #include "ace/Synch_Traits.h"
00014 #include "ace/Truncate.h"
00015 #include "ace/ACE.h"
00016 #include "ace/OS_NS_errno.h"
00017 #include "ace/OS_NS_string.h"
00018
00019 #ifdef ACE_HAS_THREADS
00020 # include "ace/Thread_Mutex.h"
00021 # include "ace/OS_NS_Thread.h"
00022 #endif
00023
00024 #include <openssl/x509.h>
00025 #include <openssl/err.h>
00026 #include <openssl/rand.h>
00027 #include <openssl/safestack.h>
00028
00029 ACE_RCSID (ACE_SSL,
00030 SSL_Context,
00031 "$Id: SSL_Context.cpp 85202 2009-04-28 18:52:57Z johnnyw $")
00032
00033
00034 namespace
00035 {
00036
00037
00038 int ssl_library_init_count = 0;
00039
00040
00041
00042
00043 #ifdef ACE_HAS_THREADS
00044
00045
00046 ACE_SSL_Context::lock_type * ssl_locks = 0;
00047
00048
00049 #endif
00050 }
00051
00052 #ifdef ACE_HAS_THREADS
00053
00054 # if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
00055 # define ACE_SSL_LOCKING_CALLBACK_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_locking_callback)
00056 # define ACE_SSL_THREAD_ID_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_thread_id)
00057 # else
00058 # define ACE_SSL_LOCKING_CALLBACK_NAME ACE_SSL_locking_callback
00059 # define ACE_SSL_THREAD_ID_NAME ACE_SSL_thread_id
00060 # endif
00061
00062
00063
00064 extern "C"
00065 {
00066 void
00067 ACE_SSL_LOCKING_CALLBACK_NAME (int mode,
00068 int type,
00069 const char * ,
00070 int )
00071 {
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 if (mode & CRYPTO_LOCK)
00085 (void) ssl_locks[type].acquire ();
00086 else
00087 (void) ssl_locks[type].release ();
00088 }
00089
00090
00091
00092
00093
00094 unsigned long
00095 ACE_SSL_THREAD_ID_NAME (void)
00096 {
00097 return (unsigned long) ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::thr_self ();
00098 }
00099 }
00100 #endif
00101
00102
00103
00104
00105 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00106
00107 #ifdef ACE_HAS_THREADS
00108 ACE_SSL_Context::lock_type * ACE_SSL_Context::locks_ = 0;
00109 #endif
00110
00111 ACE_SSL_Context::ACE_SSL_Context (void)
00112 : context_ (0),
00113 mode_ (-1),
00114 default_verify_mode_ (SSL_VERIFY_NONE),
00115 default_verify_callback_ (0),
00116 have_ca_ (0)
00117 {
00118 ACE_SSL_Context::ssl_library_init ();
00119 }
00120
00121 ACE_SSL_Context::~ACE_SSL_Context (void)
00122 {
00123 if (this->context_)
00124 {
00125 ::SSL_CTX_free (this->context_);
00126 this->context_ = 0;
00127 }
00128
00129 ACE_SSL_Context::ssl_library_fini ();
00130 }
00131
00132 ACE_SSL_Context *
00133 ACE_SSL_Context::instance (void)
00134 {
00135 return ACE_Unmanaged_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::instance ();
00136 }
00137
00138 void
00139 ACE_SSL_Context::ssl_library_init (void)
00140 {
00141 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
00142 ace_ssl_mon,
00143 *ACE_Static_Object_Lock::instance ()));
00144
00145 if (ssl_library_init_count == 0)
00146 {
00147
00148
00149 #ifdef ACE_HAS_THREADS
00150 int const num_locks = ::CRYPTO_num_locks ();
00151
00152 this->locks_ = new lock_type[num_locks];
00153 ssl_locks = this->locks_;
00154
00155 # if !defined (WIN32)
00156
00157
00158 ::CRYPTO_set_id_callback (ACE_SSL_THREAD_ID_NAME);
00159 # endif
00160 ::CRYPTO_set_locking_callback (ACE_SSL_LOCKING_CALLBACK_NAME);
00161 #endif
00162
00163 ::SSLeay_add_ssl_algorithms ();
00164 ::SSL_load_error_strings ();
00165
00166
00167
00168
00169
00170 #ifdef WIN32
00171
00172 ::RAND_screen ();
00173 #endif
00174
00175 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
00176
00177
00178 const char *egd_socket_file =
00179 ACE_OS::getenv (ACE_SSL_EGD_FILE_ENV);
00180
00181 if (egd_socket_file != 0)
00182 (void) this->egd_file (egd_socket_file);
00183 #endif
00184
00185 const char *rand_file = ACE_OS::getenv (ACE_SSL_RAND_FILE_ENV);
00186
00187 if (rand_file != 0)
00188 {
00189 (void) this->seed_file (rand_file);
00190 }
00191
00192
00193
00194 }
00195
00196 ++ssl_library_init_count;
00197 }
00198
00199 void
00200 ACE_SSL_Context::ssl_library_fini (void)
00201 {
00202 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
00203 ace_ssl_mon,
00204 *ACE_Static_Object_Lock::instance ()));
00205
00206 --ssl_library_init_count;
00207 if (ssl_library_init_count == 0)
00208 {
00209
00210 ACE_Unmanaged_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::close();
00211
00212 ::ERR_free_strings ();
00213 ::EVP_cleanup ();
00214
00215
00216
00217 #ifdef ACE_HAS_THREADS
00218 ::CRYPTO_set_locking_callback (0);
00219 ssl_locks = 0;
00220
00221 delete [] this->locks_;
00222 this->locks_ = 0;
00223
00224 #endif
00225 }
00226 }
00227
00228 int
00229 ACE_SSL_Context::set_mode (int mode)
00230 {
00231 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
00232 ace_ssl_mon,
00233 *ACE_Static_Object_Lock::instance (),
00234 -1));
00235
00236 if (this->context_ != 0)
00237 return -1;
00238
00239 #if OPENSSL_VERSION_NUMBER >= 0x10000002
00240 const SSL_METHOD *method = 0;
00241 #else
00242 SSL_METHOD *method = 0;
00243 #endif
00244
00245 switch (mode)
00246 {
00247 case ACE_SSL_Context::SSLv2_client:
00248 method = ::SSLv2_client_method ();
00249 break;
00250 case ACE_SSL_Context::SSLv2_server:
00251 method = ::SSLv2_server_method ();
00252 break;
00253 case ACE_SSL_Context::SSLv2:
00254 method = ::SSLv2_method ();
00255 break;
00256 case ACE_SSL_Context::SSLv3_client:
00257 method = ::SSLv3_client_method ();
00258 break;
00259 case ACE_SSL_Context::SSLv3_server:
00260 method = ::SSLv3_server_method ();
00261 break;
00262 case ACE_SSL_Context::SSLv3:
00263 method = ::SSLv3_method ();
00264 break;
00265 case ACE_SSL_Context::SSLv23_client:
00266 method = ::SSLv23_client_method ();
00267 break;
00268 case ACE_SSL_Context::SSLv23_server:
00269 method = ::SSLv23_server_method ();
00270 break;
00271 case ACE_SSL_Context::SSLv23:
00272 method = ::SSLv23_method ();
00273 break;
00274 case ACE_SSL_Context::TLSv1_client:
00275 method = ::TLSv1_client_method ();
00276 break;
00277 case ACE_SSL_Context::TLSv1_server:
00278 method = ::TLSv1_server_method ();
00279 break;
00280 case ACE_SSL_Context::TLSv1:
00281 method = ::TLSv1_method ();
00282 break;
00283 default:
00284 method = ::SSLv3_method ();
00285 break;
00286 }
00287
00288 this->context_ = ::SSL_CTX_new (method);
00289 if (this->context_ == 0)
00290 return -1;
00291
00292 this->mode_ = mode;
00293
00294
00295
00296
00297
00298
00299
00300 (void) this->load_trusted_ca ();
00301
00302 return 0;
00303 }
00304
00305 int
00306 ACE_SSL_Context::load_trusted_ca (const char* ca_file,
00307 const char* ca_dir,
00308 bool use_env_defaults)
00309 {
00310 this->check_context ();
00311
00312 if (ca_file == 0 && use_env_defaults)
00313 {
00314
00315 ca_file = ACE_OS::getenv (ACE_SSL_CERT_FILE_ENV);
00316 #ifdef ACE_DEFAULT_SSL_CERT_FILE
00317 if (ca_file == 0)
00318 ca_file = ACE_DEFAULT_SSL_CERT_FILE;
00319 #endif
00320 }
00321
00322 if (ca_dir == 0 && use_env_defaults)
00323 {
00324
00325 ca_dir = ACE_OS::getenv (ACE_SSL_CERT_DIR_ENV);
00326 #ifdef ACE_DEFAULT_SSL_CERT_DIR
00327 if (ca_dir == 0)
00328 ca_dir = ACE_DEFAULT_SSL_CERT_DIR;
00329 #endif
00330 }
00331
00332
00333 if (::SSL_CTX_load_verify_locations (this->context_,
00334 ca_file,
00335 ca_dir) <= 0)
00336 {
00337 if (ACE::debug ())
00338 ACE_SSL_Context::report_error ();
00339 return -1;
00340 }
00341
00342 ++this->have_ca_;
00343
00344
00345
00346 if (mode_ == SSLv23
00347 || mode_ == SSLv23_server
00348 || mode_ == TLSv1
00349 || mode_ == TLSv1_server
00350 || mode_ == SSLv3
00351 || mode_ == SSLv3_server
00352 || mode_ == SSLv2
00353 || mode_ == SSLv2_server)
00354 {
00355
00356
00357
00358 STACK_OF (X509_NAME) * cert_names = 0;
00359 cert_names = ::SSL_CTX_get_client_CA_list (this->context_);
00360 bool error = false;
00361
00362
00363
00364
00365 if (ca_file)
00366 {
00367 if (cert_names == 0)
00368 {
00369 if ((cert_names = ::SSL_load_client_CA_file (ca_file)) != 0)
00370 ::SSL_CTX_set_client_CA_list (this->context_, cert_names);
00371 else
00372 error = true;
00373 }
00374 else
00375 {
00376
00377 error = (0 == ::SSL_add_file_cert_subjects_to_stack (cert_names,
00378 ca_file));
00379 }
00380
00381 if (error)
00382 {
00383 if (ACE::debug ())
00384 ACE_SSL_Context::report_error ();
00385 return -1;
00386 }
00387 }
00388
00389
00390
00391
00392 #if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090801fL)
00393 # if !defined (OPENSSL_SYS_VMS) && !defined (OPENSSL_SYS_MACINTOSH_CLASSIC)
00394 # if !defined (OPENSSL_SYS_WIN32) || (OPENSSL_VERSION_NUMBER > 0x0090807fL)
00395
00396 if (ca_dir != 0)
00397 {
00398 if (cert_names == 0)
00399 {
00400 if ((cert_names = sk_X509_NAME_new_null ()) == 0)
00401 {
00402 if (ACE::debug ())
00403 ACE_SSL_Context::report_error ();
00404 return -1;
00405 }
00406 ::SSL_CTX_set_client_CA_list (this->context_, cert_names);
00407 }
00408 if (0 == ::SSL_add_dir_cert_subjects_to_stack (cert_names, ca_dir))
00409 {
00410 if (ACE::debug ())
00411 ACE_SSL_Context::report_error ();
00412 return -1;
00413 }
00414 }
00415 # endif
00416 # endif
00417 #endif
00418
00419 }
00420
00421 return 0;
00422 }
00423
00424
00425 int
00426 ACE_SSL_Context::private_key (const char *file_name,
00427 int type)
00428 {
00429 if (this->private_key_.type () != -1)
00430 return 0;
00431
00432 this->check_context ();
00433
00434 this->private_key_ = ACE_SSL_Data_File (file_name, type);
00435
00436 if (::SSL_CTX_use_PrivateKey_file (this->context_,
00437 this->private_key_.file_name (),
00438 this->private_key_.type ()) <= 0)
00439 {
00440 this->private_key_ = ACE_SSL_Data_File ();
00441 return -1;
00442 }
00443 else
00444 return this->verify_private_key ();
00445 }
00446
00447 int
00448 ACE_SSL_Context::verify_private_key (void)
00449 {
00450 this->check_context ();
00451
00452 return (::SSL_CTX_check_private_key (this->context_) <= 0 ? -1 : 0);
00453 }
00454
00455 int
00456 ACE_SSL_Context::certificate (const char *file_name,
00457 int type)
00458 {
00459 if (this->certificate_.type () != -1)
00460 return 0;
00461
00462 this->certificate_ = ACE_SSL_Data_File (file_name, type);
00463
00464 this->check_context ();
00465
00466 if (::SSL_CTX_use_certificate_file (this->context_,
00467 this->certificate_.file_name (),
00468 this->certificate_.type ()) <= 0)
00469 {
00470 this->certificate_ = ACE_SSL_Data_File ();
00471 return -1;
00472 }
00473 else
00474 return 0;
00475 }
00476
00477 int
00478 ACE_SSL_Context::certificate (X509* cert)
00479 {
00480
00481
00482 if (this->certificate_.type () != -1)
00483 return 0;
00484
00485 this->check_context();
00486
00487 if (::SSL_CTX_use_certificate (this->context_, cert) <= 0)
00488 {
00489 return -1;
00490 }
00491 else
00492 {
00493
00494
00495 this->certificate_ = ACE_SSL_Data_File ("MEMORY CERTIFICATE");
00496
00497 return 0;
00498 }
00499 }
00500
00501 void
00502 ACE_SSL_Context::set_verify_peer (int strict, int once, int depth)
00503 {
00504 this->check_context ();
00505
00506
00507
00508 int verify_mode = SSL_VERIFY_PEER;
00509 if (once)
00510 verify_mode |= SSL_VERIFY_CLIENT_ONCE;
00511 if (strict)
00512 verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00513
00514
00515 this->default_verify_mode (verify_mode);
00516
00517
00518
00519 if (depth > 0)
00520 ::SSL_CTX_set_verify_depth (this->context_, depth + 1);
00521 }
00522
00523
00524 int
00525 ACE_SSL_Context::random_seed (const char * seed)
00526 {
00527 int len = ACE_Utils::truncate_cast<int> (ACE_OS::strlen (seed));
00528 ::RAND_seed (seed, len);
00529
00530 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
00531
00532 return (::RAND_status () == 1 ? 0 : -1);
00533 #else
00534 return 0;
00535 #endif
00536 }
00537
00538 int
00539 ACE_SSL_Context::egd_file (const char * socket_file)
00540 {
00541 #if OPENSSL_VERSION_NUMBER < 0x00905100L
00542
00543 ACE_UNUSED_ARG (socket_file);
00544 ACE_NOTSUP_RETURN (-1);
00545 #else
00546
00547
00548
00549 if (::RAND_egd (socket_file) > 0)
00550 return 0;
00551 else
00552 return -1;
00553 #endif
00554 }
00555
00556 int
00557 ACE_SSL_Context::seed_file (const char * seed_file, long bytes)
00558 {
00559
00560
00561
00562 if (::RAND_load_file (seed_file, bytes) > 0)
00563 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
00564
00565 return (::RAND_status () == 1 ? 0 : -1);
00566 #else
00567 return 0;
00568 #endif
00569 else
00570 return -1;
00571 }
00572
00573 void
00574 ACE_SSL_Context::report_error (unsigned long error_code)
00575 {
00576 if (error_code == 0)
00577 return;
00578
00579 char error_string[256];
00580
00581
00582 #if OPENSSL_VERSION_NUMBER >= 0x0090601fL
00583 (void) ::ERR_error_string_n (error_code, error_string, sizeof error_string);
00584 #else
00585 (void) ::ERR_error_string (error_code, error_string);
00586 #endif
00587
00588 ACE_ERROR ((LM_ERROR,
00589 ACE_TEXT ("ACE_SSL (%P|%t) error code: %u - %C\n"),
00590 error_code,
00591 error_string));
00592 }
00593
00594 void
00595 ACE_SSL_Context::report_error (void)
00596 {
00597 unsigned long err = ::ERR_get_error ();
00598 ACE_SSL_Context::report_error (err);
00599 ACE_OS::last_error (err);
00600 }
00601
00602 int
00603 ACE_SSL_Context::dh_params (const char *file_name,
00604 int type)
00605 {
00606 if (this->dh_params_.type () != -1)
00607 return 0;
00608
00609
00610 if (type != SSL_FILETYPE_PEM)
00611 return -1;
00612
00613 this->dh_params_ = ACE_SSL_Data_File (file_name, type);
00614
00615 this->check_context ();
00616
00617 {
00618
00619 DH * ret=0;
00620 BIO * bio = 0;
00621
00622 if ((bio = ::BIO_new_file (this->dh_params_.file_name (), "r")) == 0)
00623 {
00624 this->dh_params_ = ACE_SSL_Data_File ();
00625 return -1;
00626 }
00627
00628 ret = PEM_read_bio_DHparams (bio, 0, 0, 0);
00629 BIO_free (bio);
00630
00631 if (ret == 0)
00632 {
00633 this->dh_params_ = ACE_SSL_Data_File ();
00634 return -1;
00635 }
00636
00637 if (::SSL_CTX_set_tmp_dh (this->context_, ret) < 0)
00638 {
00639 this->dh_params_ = ACE_SSL_Data_File ();
00640 return -1;
00641 }
00642 DH_free (ret);
00643 }
00644
00645 return 0;
00646 }
00647
00648
00649
00650 #if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
00651
00652 template ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX> *
00653 ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::singleton_;
00654
00655 #endif
00656
00657 ACE_END_VERSIONED_NAMESPACE_DECL