SSL_Context.cpp

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

Generated on Thu Nov 9 11:41:56 2006 for ACE_SSL by doxygen 1.3.6