Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

SSL_Context.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 #include "SSL_Context.h"
00004 
00005 #include "sslconf.h"
00006 
00007 #if !defined(__ACE_INLINE__)
00008 #include "SSL_Context.inl"
00009 #endif /* __ACE_INLINE__ */
00010 
00011 #include "ace/Synch.h"
00012 #include "ace/Object_Manager.h"
00013 #include "ace/Log_Msg.h"
00014 
00015 #include <openssl/x509.h>
00016 #include <openssl/err.h>
00017 #include <openssl/rand.h>
00018 
00019 ACE_RCSID (ACE_SSL,
00020            SSL_Context,
00021            "$Id: SSL_Context.cpp,v 1.1.1.2 2003/02/21 18:36:32 chad Exp $")
00022 
00023 #ifdef ACE_HAS_THREADS
00024 ACE_mutex_t * ACE_SSL_Context::lock_ = 0;
00025 #endif  /* ACE_HAS_THREADS */
00026 
00027 
00028 int ACE_SSL_Context::library_init_count_ = 0;
00029 
00030 ACE_SSL_Context::ACE_SSL_Context (void)
00031   : context_ (0),
00032     mode_ (-1),
00033     default_verify_mode_ (SSL_VERIFY_NONE),
00034     have_ca_ (0)
00035 {
00036   ACE_SSL_Context::ssl_library_init ();
00037 }
00038 
00039 ACE_SSL_Context::~ACE_SSL_Context (void)
00040 {
00041   if (this->context_)
00042     {
00043       ::SSL_CTX_free (this->context_);
00044       this->context_ = 0;
00045     }
00046 
00047   ACE_SSL_Context::ssl_library_fini ();
00048 }
00049 
00050 void
00051 ACE_SSL_Context::ssl_library_init (void)
00052 {
00053   ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
00054                      ace_ssl_mon,
00055                      *ACE_Static_Object_Lock::instance ()));
00056 
00057   if (ACE_SSL_Context::library_init_count_ == 0)
00058     {
00059       // Initialize the locking callbacks before initializing anything
00060       // else.
00061 #ifdef ACE_HAS_THREADS
00062       int num_locks = ::CRYPTO_num_locks ();
00063 
00064       ACE_NEW (ACE_SSL_Context::lock_,
00065                ACE_mutex_t[num_locks]);
00066 
00067       for (int i = 0; i < num_locks; ++i)
00068         {
00069           // rwlock_init(&(ACE_SSL_Context::lock_[i]), USYNC_THREAD,
00070           // 0);
00071           if (ACE_OS::mutex_init (&(ACE_SSL_Context::lock_[i]),
00072                                   USYNC_THREAD) != 0)
00073             ACE_ERROR ((LM_ERROR,
00074                         ACE_TEXT ("(%P|%t) ACE_SSL_Context::ssl_library_init ")
00075                         ACE_TEXT ("- %p\n"),
00076                         ACE_TEXT ("mutex_init")));
00077         }
00078 
00079 # if !defined (WIN32)
00080       // This call isn't necessary on some platforms.  See the CRYPTO
00081       // library's threads(3) man page for details.
00082       ::CRYPTO_set_id_callback (ACE_SSL_thread_id);
00083 # endif  /* WIN32 */
00084       ::CRYPTO_set_locking_callback (ACE_SSL_locking_callback);
00085 #endif  /* ACE_HAS_THREADS */
00086 
00087       ::SSLeay_add_ssl_algorithms ();
00088       ::SSL_load_error_strings ();
00089 
00090       // Seed the random number generator.  Note that the random
00091       // number generator can be seeded more than once to "stir" its
00092       // state.
00093 
00094 #ifdef WIN32
00095       // Seed the random number generator by sampling the screen.
00096       ::RAND_screen ();
00097 #endif  /* WIN32 */
00098 
00099 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
00100       // OpenSSL < 0.9.5 doesn't have EGD support.
00101 
00102       const char *egd_socket_file =
00103         ACE_OS::getenv (ACE_SSL_EGD_FILE_ENV);
00104 
00105       if (egd_socket_file != 0)
00106         (void) this->egd_file (egd_socket_file);
00107 #endif  /* OPENSSL_VERSION_NUMBER */
00108 
00109       const char *rand_file =
00110         ACE_OS::getenv (ACE_SSL_RAND_FILE_ENV);
00111 
00112       if (rand_file != 0)
00113         (void) this->seed_file (rand_file);
00114 
00115       // Initialize the mutexes that will be used by the SSL and
00116       // crypto library.
00117 
00118     }
00119 
00120   ACE_SSL_Context::library_init_count_++;
00121 }
00122 
00123 void
00124 ACE_SSL_Context::ssl_library_fini (void)
00125 {
00126   ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
00127                      ace_ssl_mon,
00128                      *ACE_Static_Object_Lock::instance ()));
00129 
00130   ACE_SSL_Context::library_init_count_--;
00131   if (ACE_SSL_Context::library_init_count_ == 0)
00132     {
00133       ::ERR_free_strings ();
00134       ::EVP_cleanup ();
00135 
00136       // Clean up the locking callbacks after everything else has been
00137       // cleaned up.
00138 #ifdef ACE_HAS_THREADS
00139       int num_locks = ::CRYPTO_num_locks ();
00140 
00141       ::CRYPTO_set_locking_callback (0);
00142       for (int i = 0; i < num_locks; ++i)
00143         ACE_OS::mutex_destroy (&(ACE_SSL_Context::lock_[i]));
00144 
00145       delete [] ACE_SSL_Context::lock_;
00146 #endif  /* ACE_HAS_THREADS */
00147     }
00148 }
00149 
00150 int
00151 ACE_SSL_Context::set_mode (int mode)
00152 {
00153   ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
00154                             ace_ssl_mon,
00155                             *ACE_Static_Object_Lock::instance (),
00156                             -1));
00157 
00158   if (this->context_ != 0)
00159     return -1;
00160 
00161   SSL_METHOD *method = 0;
00162 
00163   switch (mode)
00164     {
00165     case ACE_SSL_Context::SSLv2_client:
00166       method = ::SSLv2_client_method ();
00167       break;
00168     case ACE_SSL_Context::SSLv2_server:
00169       method = ::SSLv2_server_method ();
00170       break;
00171     case ACE_SSL_Context::SSLv2:
00172       method = ::SSLv2_method ();
00173       break;
00174     case ACE_SSL_Context::SSLv3_client:
00175       method = ::SSLv3_client_method ();
00176       break;
00177     case ACE_SSL_Context::SSLv3_server:
00178       method = ::SSLv3_server_method ();
00179       break;
00180     case ACE_SSL_Context::SSLv3:
00181       method = ::SSLv3_method ();
00182       break;
00183     case ACE_SSL_Context::SSLv23_client:
00184       method = ::SSLv23_client_method ();
00185       break;
00186     case ACE_SSL_Context::SSLv23_server:
00187       method = ::SSLv23_server_method ();
00188       break;
00189     case ACE_SSL_Context::SSLv23:
00190       method = ::SSLv23_method ();
00191       break;
00192     case ACE_SSL_Context::TLSv1_client:
00193       method = ::TLSv1_client_method ();
00194       break;
00195     case ACE_SSL_Context::TLSv1_server:
00196       method = ::TLSv1_server_method ();
00197       break;
00198     case ACE_SSL_Context::TLSv1:
00199       method = ::TLSv1_method ();
00200       break;
00201     default:
00202       method = ::SSLv3_method ();
00203       break;
00204     }
00205 
00206   this->context_ = ::SSL_CTX_new (method);
00207   if (this->context_ == 0)
00208     return -1;
00209 
00210   this->mode_ = mode;
00211 
00212   // Load the trusted certificate authority (default) certificate
00213   // locations. But do not return -1 on error, doing so confuses CTX
00214   // allocation (severe error) with the less important loading of CA
00215   // certificate location error.  If it is important for your
00216   // application then call ACE_SSL_Context::have_trusted_ca(),
00217   // immediately following this call to set_mode().
00218   (void) this->load_trusted_ca ();
00219 
00220   return 0;
00221 }
00222 
00223 int
00224 ACE_SSL_Context::load_trusted_ca (const char* ca_file, const char* ca_dir)
00225 {
00226   this->check_context ();
00227 
00228   if (ca_file == 0)
00229     {
00230       // Use the default environment settings.
00231       ca_file = ACE_OS::getenv (ACE_SSL_CERT_FILE_ENV);
00232       if (ca_file == 0)
00233         ca_file = ACE_DEFAULT_SSL_CERT_FILE;
00234     }
00235 
00236   if (ca_dir == 0)
00237     {
00238       // Use the default environment settings.
00239       ca_dir = ACE_OS::getenv (ACE_SSL_CERT_DIR_ENV);
00240       if (ca_dir == 0)
00241         ca_dir = ACE_DEFAULT_SSL_CERT_DIR;
00242     }
00243 
00244   // NOTE: SSL_CTX_load_verify_locations() returns 0 on error.
00245   if (::SSL_CTX_load_verify_locations (this->context_,
00246                                        ca_file,
00247                                        ca_dir) <= 0)
00248     {
00249       if (ACE::debug ())
00250         ACE_SSL_Context::report_error ();
00251       return -1;
00252     }
00253   else
00254     {
00255       this->have_ca_++;
00256 
00257       // for TLS/SSL servers scan all certificates in ca_file and list
00258       // then as acceptable CAs when requesting a client certificate.
00259       if (mode_ == SSLv23
00260           || mode_ == SSLv23_server
00261           || mode_ == TLSv1
00262           || mode_ == TLSv1_server
00263           || mode_ == SSLv3
00264           || mode_ == SSLv3_server
00265           || mode_ == SSLv2
00266           || mode_ == SSLv2_server)
00267         {
00268           STACK_OF (X509_NAME) * cert_names;
00269           cert_names = ::SSL_CTX_get_client_CA_list(this->context_);
00270 
00271           if (cert_names == 0)
00272             {
00273               // Set the first certificate authorith list.
00274               cert_names = ::SSL_load_client_CA_file (ca_file);
00275               if (cert_names != 0 )
00276                 ::SSL_CTX_set_client_CA_list (this->context_,
00277                                               cert_names);
00278             }
00279           else
00280             {
00281               // Add new certificate names to the list.
00282               if (!::SSL_add_file_cert_subjects_to_stack (cert_names,
00283                                                           ca_file))
00284                 cert_names = 0;
00285             }
00286 
00287           if (cert_names == 0)
00288             {
00289               if (ACE::debug ())
00290                 ACE_SSL_Context::report_error ();
00291               return -1;
00292             }
00293 
00294           // @todo
00295           // If warranted do the same for ca_dir when the function
00296           // SSL_add_dir_cert_subjects_to_stack() is portable to
00297           // WIN32, VMS, MAC_OS_pre_X (nb. it is not defined for those
00298           // platforms by OpenSSL).
00299         }
00300     }
00301 
00302   return 0;
00303 }
00304 
00305 
00306 int
00307 ACE_SSL_Context::private_key (const char *file_name,
00308                               int type)
00309 {
00310   if (this->private_key_.type () != -1)
00311     return 0;
00312 
00313   this->check_context ();
00314 
00315   this->private_key_ = ACE_SSL_Data_File (file_name, type);
00316 
00317   if (::SSL_CTX_use_PrivateKey_file (this->context_,
00318                                      this->private_key_.file_name (),
00319                                      this->private_key_.type ()) <= 0)
00320     return -1;
00321   else
00322     return this->verify_private_key ();
00323 }
00324 
00325 int
00326 ACE_SSL_Context::verify_private_key (void)
00327 {
00328   this->check_context ();
00329 
00330   return (::SSL_CTX_check_private_key (this->context_) <= 0 ? -1 : 0);
00331 }
00332 
00333 int
00334 ACE_SSL_Context::certificate (const char *file_name,
00335                               int type)
00336 {
00337   if (this->certificate_.type () != -1)
00338     return 0;
00339 
00340   this->certificate_ = ACE_SSL_Data_File (file_name, type);
00341 
00342   this->check_context ();
00343 
00344   if (::SSL_CTX_use_certificate_file (this->context_,
00345                                       this->certificate_.file_name (),
00346                                       this->certificate_.type ()) <= 0)
00347     return -1;
00348   else
00349     return 0;
00350 }
00351 
00352 void
00353 ACE_SSL_Context::set_verify_peer (int strict, int once, int depth)
00354 {
00355   this->check_context ();
00356 
00357   // Setup the peer verififcation mode.
00358 
00359   int verify_mode = SSL_VERIFY_PEER;
00360   if (once)
00361     verify_mode |= SSL_VERIFY_CLIENT_ONCE;
00362   if (strict)
00363     verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00364 
00365   // set the default verify mode
00366   this->default_verify_mode (verify_mode);
00367 
00368   // Set the max certificate depth but later let the verify_callback
00369   // catch the depth error by adding one to the required depth.
00370   if (depth > 0)
00371     ::SSL_CTX_set_verify_depth (this->context_, depth + 1);
00372 }
00373 
00374 
00375 int
00376 ACE_SSL_Context::random_seed (const char * seed)
00377 {
00378   ::RAND_seed (seed, ACE_OS::strlen (seed));
00379 
00380 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
00381   // RAND_status() returns 1 if the PRNG has enough entropy.
00382   return (::RAND_status () == 1 ? 0 : -1);
00383 #else
00384   return 0;  // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status().
00385 #endif  /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
00386 }
00387 
00388 int
00389 ACE_SSL_Context::egd_file (const char * socket_file)
00390 {
00391 #if OPENSSL_VERSION_NUMBER < 0x00905100L
00392   // OpenSSL < 0.9.5 doesn't have EGD support.
00393   ACE_UNUSED_ARG (socket_file);
00394   ACE_NOTSUP_RETURN (-1);
00395 #else
00396   // RAND_egd() returns the amount of entropy used to seed the random
00397   // number generator.  The actually value should be greater than 16,
00398   // i.e. 128 bits.
00399   if (::RAND_egd (socket_file) > 0)
00400     return 0;
00401   else
00402     return -1;
00403 #endif  /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
00404 }
00405 
00406 int
00407 ACE_SSL_Context::seed_file (const char * seed_file, long bytes)
00408 {
00409   // RAND_load_file() returns the number of bytes used to seed the
00410   // random number generator.
00411   if (::RAND_load_file (seed_file, bytes) > 0)
00412     return 0;
00413   else
00414     return -1;
00415 }
00416 
00417 void
00418 ACE_SSL_Context::report_error (unsigned long error_code)
00419 {
00420   if (error_code == 0)
00421     return;
00422 
00423   char error_string[256];
00424 
00425   (void) ::ERR_error_string (error_code, error_string);
00426 
00427   ACE_ERROR ((LM_ERROR,
00428               ACE_TEXT ("ACE_SSL (%P|%t) error code: %u - %C\n"),
00429               error_code,
00430               error_string));
00431 }
00432 
00433 void
00434 ACE_SSL_Context::report_error (void)
00435 {
00436   unsigned long error = ::ERR_get_error ();
00437   ACE_SSL_Context::report_error (error);
00438   ACE_OS::last_error (error);
00439 }
00440 
00441 int
00442 ACE_SSL_Context::dh_params (const char *file_name,
00443                             int type)
00444 {
00445   if (this->dh_params_.type () != -1)
00446     return 0;
00447 
00448   this->dh_params_ = ACE_SSL_Data_File (file_name, type);
00449 
00450   this->check_context ();
00451 
00452   {
00453     // For now we only support PEM encodings
00454     if (this->dh_params_.type () != SSL_FILETYPE_PEM)
00455       return -1;
00456 
00457     // Swiped from Rescorla's examples and the OpenSSL s_server.c app
00458     DH *ret=0;
00459     BIO *bio = 0;
00460 
00461     if ((bio = ::BIO_new_file (this->dh_params_.file_name (), "r")) == NULL)
00462       return -1;
00463 
00464     ret = PEM_read_bio_DHparams (bio, NULL, NULL, NULL);
00465     BIO_free (bio);
00466 
00467     if (ret == 0)
00468       return -1;
00469 
00470     if(::SSL_CTX_set_tmp_dh (this->context_, ret) < 0)
00471       return -1;
00472     DH_free (ret);
00473   }
00474 
00475   return 0;
00476 }
00477 
00478 // ****************************************************************
00479 
00480 #ifdef ACE_HAS_THREADS
00481 
00482 void
00483 ACE_SSL_locking_callback (int mode,
00484                           int type,
00485                           const char * /* file */,
00486                           int /* line */)
00487 {
00488   // #ifdef undef
00489   //   fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
00490   //           CRYPTO_thread_id(),
00491   //           (mode&CRYPTO_LOCK)?"l":"u",
00492   //           (type&CRYPTO_READ)?"r":"w",file,line);
00493   // #endif
00494   //   /*
00495   //     if (CRYPTO_LOCK_SSL_CERT == type)
00496   //     fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
00497   //     CRYPTO_thread_id(),
00498   //     mode,file,line);
00499   //   */
00500   if (mode & CRYPTO_LOCK)
00501     ACE_OS::mutex_lock (&(ACE_SSL_Context::lock_[type]));
00502   else
00503     ACE_OS::mutex_unlock (&(ACE_SSL_Context::lock_[type]));
00504 }
00505 
00506 
00507 
00508 unsigned long
00509 ACE_SSL_thread_id (void)
00510 {
00511   return (unsigned long) ACE_OS::thr_self ();
00512 }
00513 #endif  /* ACE_HAS_THREADS */
00514 
00515 // ****************************************************************
00516 
00517 
00518 
00519 #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
00520 
00521 template class ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>;
00522 
00523 #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
00524 
00525 #pragma instantiate ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>
00526 
00527 #elif defined (__GNUC__) && (defined (_AIX) || defined (__hpux))
00528 
00529 template ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX> *
00530   ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::singleton_;
00531 
00532 #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */

Generated on Mon Jun 16 13:15:55 2003 for ACE_SSL by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002