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            "SSLIOP_Factory.cpp,v 1.40 2006/03/14 06:14:35 jtc Exp")
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   "SSLIOP_Factory.cpp,v 1.40 2006/03/14 06:14:35 jtc Exp";
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,
00100                                                 char **path)
00101 {
00102   ACE_ASSERT (arg != 0);
00103   ACE_ASSERT (path != 0);
00104 
00105   char *lst = 0;
00106   const char *type_name = ACE_OS::strtok_r (arg, ":", &lst);
00107   *path = ACE_OS::strtok_r (0, "", &lst);
00108 
00109   if (ACE_OS::strcasecmp (type_name, "ASN1") == 0)
00110       return SSL_FILETYPE_ASN1;
00111 
00112   if (ACE_OS::strcasecmp (type_name, "PEM") == 0)
00113       return SSL_FILETYPE_PEM;
00114 
00115   return -1;
00116 }
00117 
00118 
00119 int
00120 TAO::SSLIOP::Protocol_Factory::init (int argc,
00121                                      char* argv[])
00122 {
00123   char *certificate_path = 0;
00124   char *private_key_path = 0;
00125   char *dhparams_path = 0;
00126   char *ca_file = 0;
00127   char *ca_dir = 0;
00128   char *rand_path = 0;
00129 
00130   int certificate_type = -1;
00131   int private_key_type = -1;
00132   int dhparams_type = -1;
00133 
00134   int prevdebug = -1;
00135 
00136   CSIIOP::AssociationOptions csiv2_target_supports =
00137     CSIIOP::Integrity | CSIIOP::Confidentiality;
00138   CSIIOP::AssociationOptions csiv2_target_requires =
00139     CSIIOP::Integrity | CSIIOP::Confidentiality;
00140 
00141   // Force the Singleton instance to be initialized/instantiated.
00142   // Some SSLIOP option combinations below will result in the
00143   // Singleton instance never being initialized.  In that case,
00144   // problems may occur later on due to lack of initialization of the
00145   // underlying SSL library (e.g. OpenSSL), which occurs when an
00146   // ACE_SSL_Context is instantiated.
00147 
00148   // The code is cleaner this way anyway.
00149   ACE_SSL_Context * ssl_ctx = ACE_SSL_Context::instance ();
00150   ACE_ASSERT (ssl_ctx != 0);
00151 
00152   size_t session_id_len =
00153     (sizeof session_id_context_ >= SSL_MAX_SSL_SESSION_ID_LENGTH)
00154       ? SSL_MAX_SSL_SESSION_ID_LENGTH
00155       : sizeof session_id_context_;
00156 
00157   // Note that this function returns 1, if the operation succeded.
00158   // See SSL_CTX_set_session_id_context(3)
00159   if( 1 != ::SSL_CTX_set_session_id_context (ssl_ctx->context(),
00160                                              session_id_context_,
00161                                              session_id_len))
00162   {
00163     if (TAO_debug_level > 0)
00164       ACE_DEBUG ((LM_ERROR,
00165                   ACE_TEXT ("TAO (%P|%t) Unable to set the session id ")
00166                   ACE_TEXT ("context to \'%s\'\n"), session_id_context_));
00167 
00168     return -1;
00169   }
00170 
00171   for (int curarg = 0; curarg != argc; ++curarg)
00172     {
00173       if ((ACE_OS::strcasecmp (argv[curarg],
00174                                "-verbose") == 0)
00175           || (ACE_OS::strcasecmp (argv[curarg],
00176                                   "-v") == 0))
00177         {
00178           if (TAO_debug_level == 0)
00179             {
00180               prevdebug = TAO_debug_level;
00181               TAO_debug_level = 1;
00182             }
00183         }
00184 
00185       else if (ACE_OS::strcasecmp (argv[curarg],
00186                                    "-SSLNoProtection") == 0)
00187         {
00188           // Enable the eNULL cipher.  Note that enabling the "eNULL"
00189           // cipher only disables encryption.  However, certificate
00190           // exchanges will still occur.
00191           if (::SSL_CTX_set_cipher_list (ssl_ctx->context (),
00192                                          "DEFAULT:eNULL") == 0)
00193             {
00194               if (TAO_debug_level > 0)
00195                 ACE_DEBUG ((LM_ERROR,
00196                             ACE_TEXT ("TAO (%P|%t) Unable to set eNULL ")
00197                             ACE_TEXT ("SSL cipher in SSLIOP ")
00198                             ACE_TEXT ("factory.\n")));
00199 
00200               return -1;
00201             }
00202 
00203           // This does not disable secure invocations on the server
00204           // side.  It merely enables insecure ones.  On the client
00205           // side, secure invocations will be disabled unless
00206           // overridden by a SecurityLevel2::QOPPolicy in the object
00207           // reference.
00208           this->qop_ = ::Security::SecQOPNoProtection;
00209 
00210           ACE_SET_BITS (csiv2_target_supports,
00211                         CSIIOP::NoProtection);
00212 
00213           ACE_CLR_BITS (csiv2_target_requires,
00214                         CSIIOP::Confidentiality);
00215         }
00216 
00217       else if (ACE_OS::strcasecmp (argv[curarg],
00218                                    "-SSLCertificate") == 0)
00219         {
00220           curarg++;
00221           if (curarg < argc)
00222             {
00223               certificate_type = parse_x509_file (argv[curarg], &certificate_path);
00224             }
00225         }
00226 
00227       else if (ACE_OS::strcasecmp (argv[curarg],
00228                                    "-SSLPrivateKey") == 0)
00229         {
00230           curarg++;
00231           if (curarg < argc)
00232             {
00233               private_key_type = parse_x509_file (argv[curarg], &private_key_path);
00234             }
00235         }
00236 
00237       else if (ACE_OS::strcasecmp (argv[curarg],
00238                                    "-SSLAuthenticate") == 0)
00239         {
00240           curarg++;
00241           if (curarg < argc)
00242             {
00243               int mode = SSL_VERIFY_NONE;
00244               if (ACE_OS::strcasecmp (argv[curarg], "NONE") == 0)
00245                 {
00246                   mode = SSL_VERIFY_NONE;
00247                 }
00248               else if (ACE_OS::strcasecmp (argv[curarg], "SERVER") == 0)
00249                 {
00250                   mode = SSL_VERIFY_PEER;
00251 
00252                   ACE_SET_BITS (csiv2_target_supports,
00253                                 CSIIOP::EstablishTrustInTarget
00254                                 | CSIIOP::EstablishTrustInClient);
00255                 }
00256               else if (ACE_OS::strcasecmp (argv[curarg], "CLIENT") == 0
00257                        || ACE_OS::strcasecmp (argv[curarg],
00258                                               "SERVER_AND_CLIENT") == 0)
00259                 {
00260                   mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00261 
00262                   ACE_SET_BITS (csiv2_target_supports,
00263                                 CSIIOP::EstablishTrustInTarget
00264                                 | CSIIOP::EstablishTrustInClient);
00265 
00266                   ACE_SET_BITS (csiv2_target_requires,
00267                                 CSIIOP::EstablishTrustInClient);
00268                 }
00269 
00270               ssl_ctx->default_verify_mode (mode);
00271             }
00272         }
00273 
00274       else if (ACE_OS::strcasecmp (argv[curarg],
00275                                    "-SSLAcceptTimeout") == 0)
00276         {
00277           curarg++;
00278           if (curarg < argc)
00279             {
00280               float timeout = 0;
00281 
00282               if (sscanf (argv[curarg], "%f", &timeout) != 1
00283                   || timeout < 0)
00284                 ACE_ERROR_RETURN ((LM_ERROR,
00285                                    "ERROR: Invalid -SSLAcceptTimeout "
00286                                    "value: %s.\n",
00287                                    argv[curarg]),
00288                                   -1);
00289               else
00290                 this->timeout_.set (timeout);
00291             }
00292         }
00293 
00294       else if (ACE_OS::strcasecmp (argv[curarg],
00295                                    "-SSLDHparams") == 0)
00296         {
00297           curarg++;
00298           if (curarg < argc)
00299             {
00300               dhparams_type = parse_x509_file (argv[curarg], &dhparams_path);
00301             }
00302         }
00303 
00304       else if (ACE_OS::strcasecmp (argv[curarg],
00305                                    "-SSLCAfile") == 0)
00306         {
00307           curarg++;
00308           if (curarg < argc)
00309             {
00310               (void) parse_x509_file (argv[curarg], &ca_file);
00311             }
00312         }
00313 
00314       else if (ACE_OS::strcasecmp (argv[curarg],
00315                                    "-SSLCApath") == 0)
00316         {
00317           curarg++;
00318           if (curarg < argc)
00319             {
00320               ca_dir = argv[curarg];
00321             }
00322         }
00323 
00324       else if (ACE_OS::strcasecmp (argv[curarg],
00325                                    "-SSLrand") == 0)
00326         {
00327           curarg++;
00328           if (curarg < argc)
00329             {
00330               rand_path = argv[curarg];
00331             }
00332         }
00333     }
00334 
00335   // Load some (more) entropy from the user specified sources
00336   // in addition to what's pointed to by ACE_SSL_RAND_FILE_ENV
00337   if (rand_path != 0)
00338   {
00339     short errors = 0;
00340     char *file_name = 0;
00341     const char *path = ACE_OS::strtok_r (rand_path,
00342                                          TAO_PATH_SEPARATOR_STRING,
00343                                          &file_name);
00344     while ( path != 0)
00345     {
00346       if( -1 == ssl_ctx->seed_file (path, -1))
00347       {
00348         errors++;
00349 
00350         if (TAO_debug_level > 0)
00351           ACE_DEBUG ((LM_ERROR,
00352                       ACE_TEXT ("TAO (%P|%t) Failed to load ")
00353                       ACE_TEXT ("more entropy from <%s>: %m\n"), path));
00354       }
00355       else
00356       {
00357           if (TAO_debug_level > 0)
00358             ACE_DEBUG ((LM_ERROR,
00359                         ACE_TEXT ("TAO (%P|%t) Loaded ")
00360                         ACE_TEXT ("more entropy from <%s>\n"), path));
00361       }
00362 
00363       path = ACE_OS::strtok_r (0, TAO_PATH_SEPARATOR_STRING, &file_name);
00364     }
00365 
00366     if (errors > 0)
00367       return -1;
00368   }
00369 
00370   // Load any trusted certificates explicitely rather than relying on
00371   // previously set SSL_CERT_FILE and/or SSL_CERT_PATH environment variable
00372   if (ca_file != 0 || ca_dir != 0)
00373     {
00374       if (ssl_ctx->load_trusted_ca (ca_file, ca_dir) != 0)
00375         {
00376           if (TAO_debug_level > 0)
00377             ACE_DEBUG ((LM_ERROR,
00378                         ACE_TEXT ("TAO (%P|%t) Unable to load ")
00379                         ACE_TEXT ("CA certs from %s%s%s\n"),
00380                         ((ca_file != 0) ? ca_file : ACE_TEXT ("a file pointed to by ")
00381                                                     ACE_TEXT (ACE_SSL_CERT_FILE_ENV)
00382                                                     ACE_TEXT (" env var (if any)")),
00383                         ACE_TEXT (" and "),
00384                         ((ca_dir != 0) ? ca_dir : ACE_TEXT ("a directory pointed to by ")
00385                                                   ACE_TEXT (ACE_SSL_CERT_DIR_ENV)
00386                                                   ACE_TEXT (" env var (if any)"))));
00387 
00388           return -1;
00389         }
00390       else
00391         {
00392           if (TAO_debug_level > 0)
00393             ACE_DEBUG ((LM_INFO,
00394                         ACE_TEXT ("TAO (%P|%t) SSLIOP loaded ")
00395                         ACE_TEXT ("Trusted Certificates from %s%s%s\n"),
00396                         ((ca_file != 0) ? ca_file : ACE_TEXT ("a file pointed to by ")
00397                                                     ACE_TEXT (ACE_SSL_CERT_FILE_ENV)
00398                                                     ACE_TEXT (" env var (if any)")),
00399                         ACE_TEXT (" and "),
00400                         ((ca_dir != 0) ? ca_dir : ACE_TEXT ("a directory pointed to by ")
00401                                                   ACE_TEXT (ACE_SSL_CERT_DIR_ENV)
00402                                                   ACE_TEXT (" env var (if any)"))));
00403         }
00404     }
00405 
00406   // Load in the DH params.  If there was a file explicitly specified,
00407   // then we do that here, otherwise we load them in from the cert file.
00408   // Note that we only do this on the server side, I think so we might
00409   // need to defer this 'til later in the acceptor or something...
00410   if (dhparams_path == 0)
00411     {
00412       // If the user didn't explicitly specify a DH parameters file, we
00413       // also might find it concatenated in the certificate file.
00414       // So, we set the dhparams to that if it wasn't explicitly set.
00415       dhparams_path = certificate_path;
00416       dhparams_type = certificate_type;
00417     }
00418 
00419   if (dhparams_path != 0)
00420     {
00421       if (ssl_ctx->dh_params (dhparams_path,
00422                               dhparams_type) != 0)
00423         {
00424           if (dhparams_path != certificate_path)
00425             {
00426               // We only want to fail catastrophically if the user specified
00427               // a dh parameter file and we were unable to actually find it
00428               // and load from it.
00429               if (TAO_debug_level > 0)
00430                 ACE_DEBUG ((LM_ERROR,
00431                             ACE_TEXT ("(%P|%t) SSLIOP_Factory: ")
00432                             ACE_TEXT ("unable to set ")
00433                             ACE_TEXT ("DH parameters <%s>\n"),
00434                             dhparams_path));
00435               return -1;
00436             }
00437           else
00438             {
00439               if (TAO_debug_level > 0)
00440                 ACE_DEBUG ((LM_INFO,
00441                             ACE_TEXT ("(%P|%t) SSLIOP_Factory: ")
00442                             ACE_TEXT ("No DH parameters found in ")
00443                             ACE_TEXT ("certificate <%s>; either none ")
00444                             ACE_TEXT ("are needed (RSA) or problems ")
00445                             ACE_TEXT ("will ensue later.\n"),
00446                             dhparams_path));
00447             }
00448         }
00449       else
00450         {
00451           if (TAO_debug_level > 0)
00452             ACE_DEBUG ((LM_INFO,
00453                         ACE_TEXT ("(%P|%t) SSLIOP loaded ")
00454                         ACE_TEXT ("Diffie-Hellman params ")
00455                         ACE_TEXT ("from %s\n"),
00456                         dhparams_path));
00457         }
00458     }
00459 
00460   // The certificate must be set before the private key since the
00461   // ACE_SSL_Context attempts to check the private key for
00462   // consistency.  That check requires the certificate to be available
00463   // in the underlying SSL_CTX.
00464   if (certificate_path != 0)
00465     {
00466       if (ssl_ctx->certificate (certificate_path,
00467                                 certificate_type) != 0)
00468         {
00469           if (TAO_debug_level > 0)
00470             ACE_DEBUG ((LM_ERROR,
00471                         ACE_TEXT ("TAO (%P|%t) Unable to set ")
00472                         ACE_TEXT ("SSL certificate <%s> ")
00473                         ACE_TEXT ("in SSLIOP factory.\n"),
00474                         certificate_path));
00475 
00476           return -1;
00477         }
00478       else
00479         {
00480           if (TAO_debug_level > 0)
00481             ACE_DEBUG ((LM_INFO,
00482                         ACE_TEXT ("TAO (%P|%t) SSLIOP loaded ")
00483                         ACE_TEXT ("SSL certificate ")
00484                         ACE_TEXT ("from %s\n"),
00485                         certificate_path));
00486         }
00487     }
00488 
00489   if (private_key_path != 0)
00490     {
00491       if (ssl_ctx->private_key (private_key_path,
00492                                 private_key_type) != 0)
00493         {
00494           if (TAO_debug_level > 0)
00495             {
00496               ACE_DEBUG ((LM_ERROR,
00497                           ACE_TEXT ("TAO (%P|%t) Unable to set ")
00498                           ACE_TEXT ("SSL private key ")
00499                           ACE_TEXT ("<%s> in SSLIOP factory.\n"),
00500                           private_key_path));
00501             }
00502 
00503           return -1;
00504         }
00505       else
00506         {
00507           if (TAO_debug_level > 0)
00508             ACE_DEBUG ((LM_INFO,
00509                         ACE_TEXT ("TAO (%P|%t) SSLIOP loaded ")
00510                         ACE_TEXT ("Private Key ")
00511                         ACE_TEXT ("from %s\n"),
00512                         private_key_path));
00513         }
00514     }
00515 
00516   if (this->register_orb_initializer (csiv2_target_supports,
00517                                       csiv2_target_requires) != 0)
00518     return -1;
00519 
00520   if (prevdebug != -1)
00521     TAO_debug_level = prevdebug;
00522 
00523   return 0;
00524 }
00525 
00526 int
00527 TAO::SSLIOP::Protocol_Factory::register_orb_initializer (
00528   CSIIOP::AssociationOptions csiv2_target_supports,
00529   CSIIOP::AssociationOptions csiv2_target_requires)
00530 {
00531   ACE_DECLARE_NEW_CORBA_ENV;
00532   ACE_TRY
00533     {
00534       // @todo: This hard-coding should be fixed once SECIOP is
00535       // supported.
00536       // Register the Security ORB initializer.
00537       PortableInterceptor::ORBInitializer_ptr tmp;
00538       ACE_NEW_THROW_EX (tmp,
00539                         TAO::Security::ORBInitializer,
00540                         CORBA::NO_MEMORY (
00541                           CORBA::SystemException::_tao_minor_code (
00542                             TAO::VMCID,
00543                             ENOMEM),
00544                           CORBA::COMPLETED_NO));
00545       ACE_TRY_CHECK;
00546 
00547       PortableInterceptor::ORBInitializer_var initializer = tmp;
00548 
00549       PortableInterceptor::register_orb_initializer (initializer.in ()
00550                                                      ACE_ENV_ARG_PARAMETER);
00551       ACE_TRY_CHECK;
00552 
00553       // Register the SSLIOP ORB initializer.
00554       // PortableInterceptor::ORBInitializer_ptr tmp;
00555       ACE_NEW_THROW_EX (tmp,
00556                         TAO::SSLIOP::ORBInitializer (this->qop_,
00557                                                      csiv2_target_supports,
00558                                                      csiv2_target_requires),
00559                         CORBA::NO_MEMORY (
00560                           CORBA::SystemException::_tao_minor_code (
00561                             TAO::VMCID,
00562                             ENOMEM),
00563                           CORBA::COMPLETED_NO));
00564       ACE_TRY_CHECK;
00565 
00566       //PortableInterceptor::ORBInitializer_var initializer = tmp;
00567       initializer = tmp;
00568 
00569       PortableInterceptor::register_orb_initializer (initializer.in ()
00570                                                      ACE_ENV_ARG_PARAMETER);
00571       ACE_TRY_CHECK;
00572     }
00573   ACE_CATCHANY
00574     {
00575       ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
00576                            "Unable to register SSLIOP ORB "
00577                            "initializer.");
00578       return -1;
00579     }
00580   ACE_ENDTRY;
00581   ACE_CHECK_RETURN (-1);
00582 
00583   return 0;
00584 }
00585 
00586 
00587 TAO_Connector *
00588 TAO::SSLIOP::Protocol_Factory::make_connector (void)
00589 {
00590   TAO_Connector *connector = 0;
00591 
00592   ACE_NEW_RETURN (connector,
00593                   TAO::SSLIOP::Connector (this->qop_),
00594                   0);
00595   return connector;
00596 }
00597 
00598 int
00599 TAO::SSLIOP::Protocol_Factory::requires_explicit_endpoint (void) const
00600 {
00601   return 0;
00602 }
00603 
00604 TAO_END_VERSIONED_NAMESPACE_DECL
00605 
00606 ACE_STATIC_SVC_DEFINE (TAO_SSLIOP_Protocol_Factory,
00607                        ACE_TEXT ("SSLIOP_Factory"),
00608                        ACE_SVC_OBJ_T,
00609                        &ACE_SVC_NAME (TAO_SSLIOP_Protocol_Factory),
00610                        ACE_Service_Type::DELETE_THIS
00611                        | ACE_Service_Type::DELETE_OBJ,
00612                        0)
00613 
00614 ACE_FACTORY_DEFINE (TAO_SSLIOP, TAO_SSLIOP_Protocol_Factory)

Generated on Thu Nov 9 13:54:14 2006 for TAO_SSLIOP by doxygen 1.3.6