SSLIOP_Factory.cpp

Go to the documentation of this file.
00001 #include "orbsvcs/SSLIOP/SSLIOP_Factory.h"
00002 #include "orbsvcs/SSLIOP/SSLIOP_Acceptor.h"
00003 #include "orbsvcs/SSLIOP/SSLIOP_Connector.h"
00004 #include "orbsvcs/SSLIOP/SSLIOP_ORBInitializer.h"
00005 #include "ace/OS_NS_strings.h"
00006 
00007 #include "orbsvcs/Security/Security_ORBInitializer.h"  /// @todo should go away
00008 
00009 #include "tao/debug.h"
00010 #include "tao/ORBInitializer_Registry.h"
00011 
00012 #include "ace/SSL/sslconf.h"
00013 #include "ace/SSL/SSL_Context.h"
00014 
00015 ACE_RCSID (SSLIOP,
00016            SSLIOP_Factory,
00017            "$Id: SSLIOP_Factory.cpp 80431 2008-01-15 19:06:41Z johnnyw $")
00018 
00019 
00020 // An SSL session id seed value. Needs not be too unique, just somewhat
00021 // different. See the OpenSSL manual
00022 static const unsigned char session_id_context_[] =
00023   "$Id: SSLIOP_Factory.cpp 80431 2008-01-15 19:06:41Z johnnyw $";
00024 
00025 // Protocol name prefix
00026 static const char * const the_prefix[] = {"iiop", "ssliop"};
00027 
00028 // An OS-dependent path separator character
00029 static ACE_TCHAR const TAO_PATH_SEPARATOR_STRING[] =
00030 #if defined(ACE_WIN32)
00031   ACE_TEXT (";");
00032 #else
00033   ACE_TEXT (":");
00034 #endif
00035 
00036 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00037 
00038 namespace TAO
00039 {
00040   namespace SSLIOP
00041   {
00042     static const long ACCEPT_TIMEOUT = 10;  // Default accept timeout
00043                                             // in seconds.
00044   }
00045 }
00046 
00047 TAO::SSLIOP::Protocol_Factory::Protocol_Factory (void)
00048   :  TAO_Protocol_Factory (IOP::TAG_INTERNET_IOP),
00049      qop_ (::Security::SecQOPIntegrityAndConfidentiality),
00050      timeout_ (TAO::SSLIOP::ACCEPT_TIMEOUT)
00051 {
00052 }
00053 
00054 TAO::SSLIOP::Protocol_Factory::~Protocol_Factory (void)
00055 {
00056 }
00057 
00058 int
00059 TAO::SSLIOP::Protocol_Factory::match_prefix (const ACE_CString &prefix)
00060 {
00061   // Check for the proper prefix for this protocol.
00062   return (ACE_OS::strcasecmp (prefix.c_str (), ::the_prefix[0]) == 0)
00063      || (ACE_OS::strcasecmp (prefix.c_str (), ::the_prefix[1]) == 0);
00064 }
00065 
00066 const char *
00067 TAO::SSLIOP::Protocol_Factory::prefix (void) const
00068 {
00069    // Note: This method doesn't seem to be used anywhere. Moreover,
00070    // keeping it may make things more confusing - a Factory can
00071    // well be handling multiple protocol prefixes, not just one!
00072    // Shouldn't it be deprecated?
00073   return ::the_prefix[0];
00074 }
00075 
00076 char
00077 TAO::SSLIOP::Protocol_Factory::options_delimiter (void) const
00078 {
00079   return '/';
00080 }
00081 
00082 TAO_Acceptor *
00083 TAO::SSLIOP::Protocol_Factory::make_acceptor (void)
00084 {
00085   TAO_Acceptor *acceptor = 0;
00086 
00087   ACE_NEW_RETURN (acceptor,
00088                   TAO::SSLIOP::Acceptor (this->qop_,
00089                                          this->timeout_),
00090                   0);
00091 
00092   return acceptor;
00093 }
00094 
00095 
00096 // Parses a X509 path. Beware: This function modifies
00097 // the buffer pointed to by arg!
00098 int
00099 TAO::SSLIOP::Protocol_Factory::parse_x509_file (char *arg, char **path)
00100 {
00101   ACE_ASSERT (arg != 0);
00102   ACE_ASSERT (path != 0);
00103 
00104   char *lst = 0;
00105   const char *type_name = ACE_OS::strtok_r (arg, ":", &lst);
00106   *path = ACE_OS::strtok_r (0, "", &lst);
00107 
00108   if (ACE_OS::strcasecmp (type_name, "ASN1") == 0)
00109       return SSL_FILETYPE_ASN1;
00110 
00111   if (ACE_OS::strcasecmp (type_name, "PEM") == 0)
00112       return SSL_FILETYPE_PEM;
00113 
00114   return -1;
00115 }
00116 
00117 
00118 int
00119 TAO::SSLIOP::Protocol_Factory::init (int argc, char* argv[])
00120 {
00121   char *certificate_path = 0;
00122   char *private_key_path = 0;
00123   char *dhparams_path = 0;
00124   char *ca_file = 0;
00125   char *ca_dir = 0;
00126   char *rand_path = 0;
00127 
00128   int certificate_type = -1;
00129   int private_key_type = -1;
00130   int dhparams_type = -1;
00131 
00132   int prevdebug = -1;
00133 
00134   CSIIOP::AssociationOptions csiv2_target_supports =
00135     CSIIOP::Integrity | CSIIOP::Confidentiality;
00136   CSIIOP::AssociationOptions csiv2_target_requires =
00137     CSIIOP::Integrity | CSIIOP::Confidentiality;
00138 
00139   // Force the Singleton instance to be initialized/instantiated.
00140   // Some SSLIOP option combinations below will result in the
00141   // Singleton instance never being initialized.  In that case,
00142   // problems may occur later on due to lack of initialization of the
00143   // underlying SSL library (e.g. OpenSSL), which occurs when an
00144   // ACE_SSL_Context is instantiated.
00145 
00146   // The code is cleaner this way anyway.
00147   ACE_SSL_Context * ssl_ctx = ACE_SSL_Context::instance ();
00148   ACE_ASSERT (ssl_ctx != 0);
00149 
00150   size_t session_id_len =
00151     (sizeof session_id_context_ >= SSL_MAX_SSL_SESSION_ID_LENGTH)
00152       ? SSL_MAX_SSL_SESSION_ID_LENGTH
00153       : sizeof session_id_context_;
00154 
00155   // Note that this function returns 1, if the operation succeded.
00156   // See SSL_CTX_set_session_id_context(3)
00157   if( 1 != ::SSL_CTX_set_session_id_context (ssl_ctx->context(),
00158                                              session_id_context_,
00159                                              session_id_len))
00160   {
00161     if (TAO_debug_level > 0)
00162       ACE_ERROR ((LM_ERROR,
00163                   ACE_TEXT ("TAO (%P|%t) Unable to set the session id ")
00164                   ACE_TEXT ("context to \'%s\'\n"), session_id_context_));
00165 
00166     return -1;
00167   }
00168 
00169   for (int curarg = 0; curarg != argc; ++curarg)
00170     {
00171       if ((ACE_OS::strcasecmp (argv[curarg],
00172                                "-verbose") == 0)
00173           || (ACE_OS::strcasecmp (argv[curarg],
00174                                   "-v") == 0))
00175         {
00176           if (TAO_debug_level == 0)
00177             {
00178               prevdebug = TAO_debug_level;
00179               TAO_debug_level = 1;
00180             }
00181         }
00182 
00183       else if (ACE_OS::strcasecmp (argv[curarg],
00184                                    "-SSLNoProtection") == 0)
00185         {
00186           // Enable the eNULL cipher.  Note that enabling the "eNULL"
00187           // cipher only disables encryption.  However, certificate
00188           // exchanges will still occur.
00189           if (::SSL_CTX_set_cipher_list (ssl_ctx->context (),
00190                                          "DEFAULT:eNULL") == 0)
00191             {
00192               if (TAO_debug_level > 0)
00193                 ACE_DEBUG ((LM_ERROR,
00194                             ACE_TEXT ("TAO (%P|%t) Unable to set eNULL ")
00195                             ACE_TEXT ("SSL cipher in SSLIOP ")
00196                             ACE_TEXT ("factory.\n")));
00197 
00198               return -1;
00199             }
00200 
00201           // This does not disable secure invocations on the server
00202           // side.  It merely enables insecure ones.  On the client
00203           // side, secure invocations will be disabled unless
00204           // overridden by a SecurityLevel2::QOPPolicy in the object
00205           // reference.
00206           this->qop_ = ::Security::SecQOPNoProtection;
00207 
00208           ACE_SET_BITS (csiv2_target_supports,
00209                         CSIIOP::NoProtection);
00210 
00211           ACE_CLR_BITS (csiv2_target_requires,
00212                         CSIIOP::Confidentiality);
00213         }
00214 
00215       else if (ACE_OS::strcasecmp (argv[curarg],
00216                                    "-SSLCertificate") == 0)
00217         {
00218           curarg++;
00219           if (curarg < argc)
00220             {
00221               certificate_type = parse_x509_file (argv[curarg], &certificate_path);
00222             }
00223         }
00224 
00225       else if (ACE_OS::strcasecmp (argv[curarg],
00226                                    "-SSLPrivateKey") == 0)
00227         {
00228           curarg++;
00229           if (curarg < argc)
00230             {
00231               private_key_type = parse_x509_file (argv[curarg], &private_key_path);
00232             }
00233         }
00234 
00235       else if (ACE_OS::strcasecmp (argv[curarg],
00236                                    "-SSLAuthenticate") == 0)
00237         {
00238           curarg++;
00239           if (curarg < argc)
00240             {
00241               int mode = SSL_VERIFY_NONE;
00242               if (ACE_OS::strcasecmp (argv[curarg], "NONE") == 0)
00243                 {
00244                   mode = SSL_VERIFY_NONE;
00245                 }
00246               else if (ACE_OS::strcasecmp (argv[curarg], "SERVER") == 0)
00247                 {
00248                   mode = SSL_VERIFY_PEER;
00249 
00250                   ACE_SET_BITS (csiv2_target_supports,
00251                                 CSIIOP::EstablishTrustInTarget
00252                                 | CSIIOP::EstablishTrustInClient);
00253                 }
00254               else if (ACE_OS::strcasecmp (argv[curarg], "CLIENT") == 0
00255                        || ACE_OS::strcasecmp (argv[curarg],
00256                                               "SERVER_AND_CLIENT") == 0)
00257                 {
00258                   mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00259 
00260                   ACE_SET_BITS (csiv2_target_supports,
00261                                 CSIIOP::EstablishTrustInTarget
00262                                 | CSIIOP::EstablishTrustInClient);
00263 
00264                   ACE_SET_BITS (csiv2_target_requires,
00265                                 CSIIOP::EstablishTrustInClient);
00266                 }
00267 
00268               ssl_ctx->default_verify_mode (mode);
00269             }
00270         }
00271 
00272       else if (ACE_OS::strcasecmp (argv[curarg],
00273                                    "-SSLAcceptTimeout") == 0)
00274         {
00275           curarg++;
00276           if (curarg < argc)
00277             {
00278               float timeout = 0;
00279 
00280               if (sscanf (argv[curarg], "%f", &timeout) != 1
00281                   || timeout < 0)
00282                 ACE_ERROR_RETURN ((LM_ERROR,
00283                                    "ERROR: Invalid -SSLAcceptTimeout "
00284                                    "value: %s.\n",
00285                                    argv[curarg]),
00286                                   -1);
00287               else
00288                 this->timeout_.set (timeout);
00289             }
00290         }
00291 
00292       else if (ACE_OS::strcasecmp (argv[curarg],
00293                                    "-SSLDHparams") == 0)
00294         {
00295           curarg++;
00296           if (curarg < argc)
00297             {
00298               dhparams_type = parse_x509_file (argv[curarg], &dhparams_path);
00299             }
00300         }
00301 
00302       else if (ACE_OS::strcasecmp (argv[curarg],
00303                                    "-SSLCAfile") == 0)
00304         {
00305           curarg++;
00306           if (curarg < argc)
00307             {
00308               (void) parse_x509_file (argv[curarg], &ca_file);
00309             }
00310         }
00311 
00312       else if (ACE_OS::strcasecmp (argv[curarg],
00313                                    "-SSLCApath") == 0)
00314         {
00315           curarg++;
00316           if (curarg < argc)
00317             {
00318               ca_dir = argv[curarg];
00319             }
00320         }
00321 
00322       else if (ACE_OS::strcasecmp (argv[curarg],
00323                                    "-SSLrand") == 0)
00324         {
00325           curarg++;
00326           if (curarg < argc)
00327             {
00328               rand_path = argv[curarg];
00329             }
00330         }
00331     }
00332 
00333   // Load some (more) entropy from the user specified sources
00334   // in addition to what's pointed to by ACE_SSL_RAND_FILE_ENV
00335   if (rand_path != 0)
00336   {
00337     short errors = 0;
00338     char *file_name = 0;
00339     const char *path = ACE_OS::strtok_r (rand_path,
00340                                          TAO_PATH_SEPARATOR_STRING,
00341                                          &file_name);
00342     while ( path != 0)
00343     {
00344       if( -1 == ssl_ctx->seed_file (path, -1))
00345       {
00346         ++errors;
00347 
00348         if (TAO_debug_level > 0)
00349           ACE_ERROR ((LM_ERROR,
00350                       ACE_TEXT ("TAO (%P|%t) Failed to load ")
00351                       ACE_TEXT ("more entropy from <%s>: %m\n"), path));
00352       }
00353       else
00354       {
00355           if (TAO_debug_level > 0)
00356             ACE_DEBUG ((LM_DEBUG,
00357                         ACE_TEXT ("TAO (%P|%t) Loaded ")
00358                         ACE_TEXT ("more entropy from <%s>\n"), path));
00359       }
00360 
00361       path = ACE_OS::strtok_r (0, TAO_PATH_SEPARATOR_STRING, &file_name);
00362     }
00363 
00364     if (errors > 0)
00365       return -1;
00366   }
00367 
00368   // Load any trusted certificates explicitely rather than relying on
00369   // previously set SSL_CERT_FILE and/or SSL_CERT_PATH environment variable
00370   if (ca_file != 0 || ca_dir != 0)
00371     {
00372       if (ssl_ctx->load_trusted_ca (ca_file, ca_dir) != 0)
00373         {
00374           if (TAO_debug_level > 0)
00375             ACE_ERROR ((LM_ERROR,
00376                         ACE_TEXT ("TAO (%P|%t) Unable to load ")
00377                         ACE_TEXT ("CA certs from %s%s%s\n"),
00378                         ((ca_file != 0) ? ca_file : ACE_TEXT ("a file pointed to by ")
00379                                                     ACE_TEXT (ACE_SSL_CERT_FILE_ENV)
00380                                                     ACE_TEXT (" env var (if any)")),
00381                         ACE_TEXT (" and "),
00382                         ((ca_dir != 0) ? ca_dir : ACE_TEXT ("a directory pointed to by ")
00383                                                   ACE_TEXT (ACE_SSL_CERT_DIR_ENV)
00384                                                   ACE_TEXT (" env var (if any)"))));
00385 
00386           return -1;
00387         }
00388       else
00389         {
00390           if (TAO_debug_level > 0)
00391             ACE_DEBUG ((LM_INFO,
00392                         ACE_TEXT ("TAO (%P|%t) SSLIOP loaded ")
00393                         ACE_TEXT ("Trusted Certificates from %s%s%s\n"),
00394                         ((ca_file != 0) ? ca_file : ACE_TEXT ("a file pointed to by ")
00395                                                     ACE_TEXT (ACE_SSL_CERT_FILE_ENV)
00396                                                     ACE_TEXT (" env var (if any)")),
00397                         ACE_TEXT (" and "),
00398                         ((ca_dir != 0) ? ca_dir : ACE_TEXT ("a directory pointed to by ")
00399                                                   ACE_TEXT (ACE_SSL_CERT_DIR_ENV)
00400                                                   ACE_TEXT (" env var (if any)"))));
00401         }
00402     }
00403 
00404   // Load in the DH params.  If there was a file explicitly specified,
00405   // then we do that here, otherwise we load them in from the cert file.
00406   // Note that we only do this on the server side, I think so we might
00407   // need to defer this 'til later in the acceptor or something...
00408   if (dhparams_path == 0)
00409     {
00410       // If the user didn't explicitly specify a DH parameters file, we
00411       // also might find it concatenated in the certificate file.
00412       // So, we set the dhparams to that if it wasn't explicitly set.
00413       dhparams_path = certificate_path;
00414       dhparams_type = certificate_type;
00415     }
00416 
00417   if (dhparams_path != 0)
00418     {
00419       if (ssl_ctx->dh_params (dhparams_path,
00420                               dhparams_type) != 0)
00421         {
00422           if (dhparams_path != certificate_path)
00423             {
00424               // We only want to fail catastrophically if the user specified
00425               // a dh parameter file and we were unable to actually find it
00426               // and load from it.
00427               if (TAO_debug_level > 0)
00428                 ACE_ERROR ((LM_ERROR,
00429                             ACE_TEXT ("(%P|%t) SSLIOP_Factory: ")
00430                             ACE_TEXT ("unable to set ")
00431                             ACE_TEXT ("DH parameters <%s>\n"),
00432                             dhparams_path));
00433               return -1;
00434             }
00435           else
00436             {
00437               if (TAO_debug_level > 0)
00438                 ACE_DEBUG ((LM_INFO,
00439                             ACE_TEXT ("(%P|%t) SSLIOP_Factory: ")
00440                             ACE_TEXT ("No DH parameters found in ")
00441                             ACE_TEXT ("certificate <%s>; either none ")
00442                             ACE_TEXT ("are needed (RSA) or problems ")
00443                             ACE_TEXT ("will ensue later.\n"),
00444                             dhparams_path));
00445             }
00446         }
00447       else
00448         {
00449           if (TAO_debug_level > 0)
00450             ACE_DEBUG ((LM_INFO,
00451                         ACE_TEXT ("(%P|%t) SSLIOP loaded ")
00452                         ACE_TEXT ("Diffie-Hellman params ")
00453                         ACE_TEXT ("from %s\n"),
00454                         dhparams_path));
00455         }
00456     }
00457 
00458   // The certificate must be set before the private key since the
00459   // ACE_SSL_Context attempts to check the private key for
00460   // consistency.  That check requires the certificate to be available
00461   // in the underlying SSL_CTX.
00462   if (certificate_path != 0)
00463     {
00464       if (ssl_ctx->certificate (certificate_path,
00465                                 certificate_type) != 0)
00466         {
00467           if (TAO_debug_level > 0)
00468             ACE_ERROR ((LM_ERROR,
00469                         ACE_TEXT ("TAO (%P|%t) Unable to set ")
00470                         ACE_TEXT ("SSL certificate <%s> ")
00471                         ACE_TEXT ("in SSLIOP factory.\n"),
00472                         certificate_path));
00473 
00474           return -1;
00475         }
00476       else
00477         {
00478           if (TAO_debug_level > 0)
00479             ACE_DEBUG ((LM_INFO,
00480                         ACE_TEXT ("TAO (%P|%t) SSLIOP loaded ")
00481                         ACE_TEXT ("SSL certificate ")
00482                         ACE_TEXT ("from %s\n"),
00483                         certificate_path));
00484         }
00485     }
00486 
00487   if (private_key_path != 0)
00488     {
00489       if (ssl_ctx->private_key (private_key_path, private_key_type) != 0)
00490         {
00491           if (TAO_debug_level > 0)
00492             {
00493               ACE_ERROR ((LM_ERROR,
00494                           ACE_TEXT ("TAO (%P|%t) Unable to set ")
00495                           ACE_TEXT ("SSL private key ")
00496                           ACE_TEXT ("<%s> in SSLIOP factory.\n"),
00497                           private_key_path));
00498             }
00499 
00500           return -1;
00501         }
00502       else
00503         {
00504           if (TAO_debug_level > 0)
00505             ACE_DEBUG ((LM_INFO,
00506                         ACE_TEXT ("TAO (%P|%t) SSLIOP loaded ")
00507                         ACE_TEXT ("Private Key ")
00508                         ACE_TEXT ("from %s\n"),
00509                         private_key_path));
00510         }
00511     }
00512 
00513   if (this->register_orb_initializer (csiv2_target_supports,
00514                                       csiv2_target_requires) != 0)
00515     return -1;
00516 
00517   if (prevdebug != -1)
00518     TAO_debug_level = prevdebug;
00519 
00520   return 0;
00521 }
00522 
00523 int
00524 TAO::SSLIOP::Protocol_Factory::register_orb_initializer (
00525   CSIIOP::AssociationOptions csiv2_target_supports,
00526   CSIIOP::AssociationOptions csiv2_target_requires)
00527 {
00528   try
00529     {
00530       // @todo: This hard-coding should be fixed once SECIOP is
00531       // supported.
00532       // Register the Security ORB initializer.
00533       PortableInterceptor::ORBInitializer_ptr tmp;
00534       ACE_NEW_THROW_EX (tmp,
00535                         TAO::Security::ORBInitializer,
00536                         CORBA::NO_MEMORY (
00537                           CORBA::SystemException::_tao_minor_code (
00538                             TAO::VMCID,
00539                             ENOMEM),
00540                           CORBA::COMPLETED_NO));
00541 
00542       PortableInterceptor::ORBInitializer_var initializer = tmp;
00543 
00544       PortableInterceptor::register_orb_initializer (initializer.in ());
00545 
00546       // Register the SSLIOP ORB initializer.
00547       // PortableInterceptor::ORBInitializer_ptr tmp;
00548       ACE_NEW_THROW_EX (tmp,
00549                         TAO::SSLIOP::ORBInitializer (this->qop_,
00550                                                      csiv2_target_supports,
00551                                                      csiv2_target_requires),
00552                         CORBA::NO_MEMORY (
00553                           CORBA::SystemException::_tao_minor_code (
00554                             TAO::VMCID,
00555                             ENOMEM),
00556                           CORBA::COMPLETED_NO));
00557 
00558       //PortableInterceptor::ORBInitializer_var initializer = tmp;
00559       initializer = tmp;
00560 
00561       PortableInterceptor::register_orb_initializer (initializer.in ());
00562     }
00563   catch (const CORBA::Exception& ex)
00564     {
00565       ex._tao_print_exception (
00566         "Unable to register SSLIOP ORB initializer.");
00567       return -1;
00568     }
00569 
00570   return 0;
00571 }
00572 
00573 
00574 TAO_Connector *
00575 TAO::SSLIOP::Protocol_Factory::make_connector (void)
00576 {
00577   TAO_Connector *connector = 0;
00578 
00579   ACE_NEW_RETURN (connector,
00580                   TAO::SSLIOP::Connector (this->qop_),
00581                   0);
00582   return connector;
00583 }
00584 
00585 int
00586 TAO::SSLIOP::Protocol_Factory::requires_explicit_endpoint (void) const
00587 {
00588   return 0;
00589 }
00590 
00591 TAO_END_VERSIONED_NAMESPACE_DECL
00592 
00593 ACE_STATIC_SVC_DEFINE (TAO_SSLIOP_Protocol_Factory,
00594                        ACE_TEXT ("SSLIOP_Factory"),
00595                        ACE_SVC_OBJ_T,
00596                        &ACE_SVC_NAME (TAO_SSLIOP_Protocol_Factory),
00597                        ACE_Service_Type::DELETE_THIS
00598                        | ACE_Service_Type::DELETE_OBJ,
00599                        0)
00600 
00601 ACE_FACTORY_DEFINE (TAO_SSLIOP, TAO_SSLIOP_Protocol_Factory)

Generated on Tue Feb 2 17:48:44 2010 for TAO_SSLIOP by  doxygen 1.4.7