SSLIOP_CredentialsAcquirer.cpp

Go to the documentation of this file.
00001 // $Id: SSLIOP_CredentialsAcquirer.cpp 77001 2007-02-12 07:54:49Z johnnyw $
00002 
00003 #include "orbsvcs/SSLIOP/SSLIOP_CredentialsAcquirer.h"
00004 #include "orbsvcs/SSLIOP/SSLIOP_OwnCredentials.h"
00005 
00006 #include "tao/debug.h"
00007 #include "tao/ORB_Constants.h"
00008 
00009 #include "ace/SSL/SSL_Context.h"
00010 
00011 #include "ace/OS_NS_stdio.h"
00012 
00013 #include <openssl/x509.h>
00014 #include <openssl/pem.h>
00015 
00016 
00017 ACE_RCSID (SSLIOP,
00018            SSLIOP_CredentialsAcquirer,
00019            "$Id: SSLIOP_CredentialsAcquirer.cpp 77001 2007-02-12 07:54:49Z johnnyw $")
00020 
00021 
00022 // -------------------------------------------------------
00023 
00024 #if (defined (TAO_HAS_VERSIONED_NAMESPACE) && TAO_HAS_VERSIONED_NAMESPACE == 1)
00025 # define TAO_SSLIOP_PASSWORD_CALLBACK_NAME ACE_PREPROC_CONCATENATE(TAO_VERSIONED_NAMESPACE_NAME, _TAO_SSLIOP_password_callback)
00026 #else
00027 # define TAO_SSLIOP_PASSWORD_CALLBACK_NAME TAO_SSLIOP_password_callback
00028 #endif  /* TAO_HAS_VERSIONED_NAMESPACE == 1 */
00029 
00030 
00031 extern "C"
00032 int
00033 TAO_SSLIOP_PASSWORD_CALLBACK_NAME (char *buf,
00034                                    int size,
00035                                    int /* rwflag */,
00036                                    void *userdata)
00037 {
00038   // @@ I'm probably over complicating this implementation, but that's
00039   //    what you get when you try to be overly efficient.  :-)
00040   //        -Ossama
00041 
00042   const char * password = static_cast<char *> (userdata);
00043 
00044   int pwlen = -1;
00045 
00046   if (password != 0)
00047     {
00048       pwlen = ACE_OS::strlen (password);
00049 
00050       int copy_len = pwlen + 1;  // Include the NULL terminator
00051 
00052       // Clear the portion of the buffer that exceeds the space that
00053       // will be occupied by the password.
00054       if (copy_len < size)
00055         ACE_OS::memset (buf + copy_len, 0, size - copy_len);
00056 
00057       // Make sure we don't overflow the OpenSSL supplied buffer.
00058       // Truncate the password if necessary.
00059       copy_len = (copy_len > size) ? size : copy_len;
00060 
00061       ACE_OS::memcpy (buf, password, copy_len);
00062 
00063       // NULL terminate the truncated password.
00064       if (copy_len > size)
00065         {
00066           pwlen = size - 1;
00067           buf[pwlen] = '\0';
00068         }
00069     }
00070 
00071   return pwlen;
00072 }
00073 
00074 // -------------------------------------------------------
00075 
00076 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00077 
00078 TAO::SSLIOP::CredentialsAcquirer::CredentialsAcquirer (
00079    TAO::SL3::CredentialsCurator_ptr curator,
00080    const CORBA::Any & acquisition_arguments)
00081   : lock_ (),
00082     curator_ (TAO::SL3::CredentialsCurator::_duplicate (curator)),
00083     acquisition_arguments_ (acquisition_arguments),
00084     destroyed_ (false)
00085 {
00086 }
00087 
00088 TAO::SSLIOP::CredentialsAcquirer::~CredentialsAcquirer (void)
00089 {
00090 }
00091 
00092 char *
00093 TAO::SSLIOP::CredentialsAcquirer::acquisition_method (void)
00094 {
00095   this->check_validity ();
00096 
00097   return CORBA::string_dup ("SL3TLS");
00098 }
00099 
00100 SecurityLevel3::AcquisitionStatus
00101 TAO::SSLIOP::CredentialsAcquirer::current_status (void)
00102 {
00103   this->check_validity ();
00104 
00105   return SecurityLevel3::AQST_Succeeded;  // @@ Really?
00106 }
00107 
00108 CORBA::ULong
00109 TAO::SSLIOP::CredentialsAcquirer::nth_iteration (void)
00110 {
00111   this->check_validity ();
00112 
00113   // SSL/TLS credentials is single-step process from the point-of-view
00114   // of the caller.
00115   return 1;
00116 }
00117 
00118 CORBA::Any *
00119 TAO::SSLIOP::CredentialsAcquirer::get_continuation_data ()
00120 {
00121   // SSL/TLS credentials acquisition does generate continuation data.
00122   throw CORBA::BAD_INV_ORDER ();
00123 }
00124 
00125 SecurityLevel3::AcquisitionStatus
00126 TAO::SSLIOP::CredentialsAcquirer::continue_acquisition (
00127     const CORBA::Any & /* acquisition_arguments */)
00128 {
00129   // SSL/TLS credentials acquisition does generate continuation data.
00130   throw CORBA::BAD_INV_ORDER ();
00131 }
00132 
00133 SecurityLevel3::OwnCredentials_ptr
00134 TAO::SSLIOP::CredentialsAcquirer::get_credentials (CORBA::Boolean on_list)
00135 {
00136   this->check_validity ();
00137 
00138   ::SSLIOP::AuthData *data;
00139 
00140   if (!(this->acquisition_arguments_ >>= data))
00141     throw CORBA::BAD_PARAM ();
00142 
00143   TAO::SSLIOP::X509_var x509 = this->make_X509 (data->certificate);
00144 
00145   if (x509.in () == 0)
00146     throw CORBA::BAD_PARAM ();
00147 
00148   TAO::SSLIOP::EVP_PKEY_var evp = this->make_EVP_PKEY (data->key);
00149 
00150   if (evp.in () == 0)
00151     throw CORBA::BAD_PARAM ();
00152 
00153   // Verify that the private key is consistent with the certificate.
00154   if (::X509_check_private_key (x509.in (), evp.in ()) != 1)
00155     {
00156       if (TAO_debug_level > 0)
00157         ACE_DEBUG ((LM_ERROR,
00158                     ACE_TEXT ("(%P|%t) ERROR: Private key is not ")
00159                     ACE_TEXT ("consistent with X.509 certificate")));
00160 
00161       throw CORBA::BAD_PARAM ();
00162     }
00163 
00164   TAO::SSLIOP::OwnCredentials * creds;
00165   ACE_NEW_THROW_EX (creds,
00166                     TAO::SSLIOP::OwnCredentials (x509.in (), evp.in ()),
00167                     CORBA::NO_MEMORY ());
00168 
00169   SecurityLevel3::OwnCredentials_var credentials = creds;
00170 
00171   if (on_list)
00172     {
00173       this->curator_->_tao_add_own_credentials (creds);
00174     }
00175 
00176   this->destroy ();
00177 
00178   return credentials._retn ();
00179 }
00180 
00181 void
00182 TAO::SSLIOP::CredentialsAcquirer::destroy (void)
00183 {
00184   this->check_validity ();
00185 
00186   ACE_GUARD (TAO_SYNCH_MUTEX,
00187              guard,
00188              this->lock_);
00189 
00190   if (!this->destroyed_)
00191     {
00192       this->destroyed_ = true;
00193 
00194       // Release our reference to the CredentialsCurator.
00195       (void) this->curator_.out ();
00196     }
00197 }
00198 
00199 void
00200 TAO::SSLIOP::CredentialsAcquirer::check_validity (void)
00201 {
00202   ACE_GUARD (TAO_SYNCH_MUTEX,
00203              guard,
00204              this->lock_);
00205 
00206   if (this->destroyed_)
00207     throw CORBA::BAD_INV_ORDER ();
00208 }
00209 
00210 ::X509 *
00211 TAO::SSLIOP::CredentialsAcquirer::make_X509 (const ::SSLIOP::File &certificate)
00212 {
00213   // No password is used or needed when reading ASN.1 encoded
00214   // certificates.
00215 
00216   const char *filename = certificate.filename.in ();
00217 
00218   if (filename == 0)
00219     return 0;
00220 
00221   FILE *fp = 0;
00222   ::X509 *x = 0;
00223 
00224   if (certificate.type == ::SSLIOP::ASN1)
00225     {
00226       // ASN.1/DER encoded certificate
00227 
00228       // No password is used or needed when reading ASN.1 encoded
00229       // certificates.
00230 
00231       const char *filename = certificate.filename.in ();
00232 
00233       if (filename == 0)
00234         return 0;
00235 
00236       fp = ACE_OS::fopen (filename, "rb");
00237 
00238       if (fp == 0)
00239         {
00240           if (TAO_debug_level > 0)
00241             ACE_ERROR ((LM_ERROR,
00242                         ACE_TEXT ("(%P|%t) SSLIOP::CredentialsAcquirer::make_X509 - %p\n"),
00243                         ACE_TEXT ("fopen")));
00244 
00245           return 0;
00246         }
00247 
00248       // Read ASN.1 / DER encoded X.509 certificate from a file, and
00249       // convert it to OpenSSL's internal X.509 format.
00250       x = ::d2i_X509_fp (fp, 0);
00251     }
00252   else
00253     {
00254       // PEM encoded certificate
00255 
00256       fp = ACE_OS::fopen (filename, "r");
00257 
00258       if (fp == 0)
00259         {
00260           if (TAO_debug_level > 0)
00261             ACE_ERROR ((LM_ERROR,
00262                         ACE_TEXT ("(%P|%t) SSLIOP::CredentialsAcquirer::make_X509 - %p\n"),
00263                         ACE_TEXT ("fopen")));
00264 
00265           return 0;
00266         }
00267 
00268       const char *password = certificate.password.in ();
00269 
00270       // Read PEM encoded X.509 certificate from a file, and convert
00271       // it to OpenSSL's internal X.509 format.
00272       x = PEM_read_X509 (fp,
00273                          0,
00274                          TAO_SSLIOP_PASSWORD_CALLBACK_NAME,
00275                          const_cast<char *> (password));
00276     }
00277 
00278   (void) ACE_OS::fclose (fp);
00279 
00280   if (x == 0 && TAO_debug_level > 0)
00281     ACE_SSL_Context::report_error ();
00282 
00283   return x;
00284 }
00285 
00286 ::EVP_PKEY *
00287 TAO::SSLIOP::CredentialsAcquirer::make_EVP_PKEY (const ::SSLIOP::File &key)
00288 {
00289   // No password is used or needed when reading ASN.1 encoded
00290   // private keys.
00291 
00292   const char *filename = key.filename.in ();
00293 
00294   if (filename == 0)
00295     return 0;
00296 
00297   FILE *fp = 0;
00298   ::EVP_PKEY *evp = 0;
00299 
00300   if (key.type == ::SSLIOP::ASN1)
00301     {
00302       // ASN.1/DER encoded private key
00303 
00304       // No password is used or needed when reading ASN.1 encoded
00305       // private keys.
00306 
00307       const char *filename = key.filename.in ();
00308 
00309       if (filename == 0)
00310         return 0;
00311 
00312       fp = ACE_OS::fopen (filename, "rb");
00313 
00314       if (fp == 0)
00315         {
00316           if (TAO_debug_level > 0)
00317             ACE_ERROR ((LM_ERROR,
00318                         ACE_TEXT ("(%P|%t) SSLIOP::CredentialsAcquirer::make_EVP_PKEY ")
00319                         ACE_TEXT ("- %p\n"),
00320                         ACE_TEXT ("fopen")));
00321 
00322           return 0;
00323         }
00324 
00325       // Read ASN.1 / DER encoded private key from a file, and convert
00326       // it to OpenSSL's internal private key format.
00327       evp = ::d2i_PrivateKey_fp (fp, 0);
00328     }
00329   else
00330     {
00331       // PEM encoded private key
00332 
00333       fp = ACE_OS::fopen (filename, "r");
00334 
00335       if (fp == 0)
00336         {
00337           if (TAO_debug_level > 0)
00338             ACE_ERROR ((LM_ERROR,
00339                         ACE_TEXT ("(%P|%t) SSLIOP::CredentialsAcquirer::make_EVP_PKEY ")
00340                         ACE_TEXT ("- %p\n"),
00341                         ACE_TEXT ("fopen")));
00342 
00343           return 0;
00344         }
00345 
00346       const char *password = key.password.in ();
00347 
00348       // Read PEM encoded private key from a file, and convert it to
00349       // OpenSSL's internal private key format.
00350       evp = PEM_read_PrivateKey (fp,
00351                                  0,
00352                                  TAO_SSLIOP_PASSWORD_CALLBACK_NAME,
00353                                  const_cast<char *> (password));
00354     }
00355 
00356   (void) ACE_OS::fclose (fp);
00357 
00358   if (evp == 0 && TAO_debug_level > 0)
00359     ACE_SSL_Context::report_error ();
00360 
00361   return evp;
00362 }
00363 
00364 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 16:12:24 2008 for TAO_SSLIOP by doxygen 1.3.6