SSLIOP_Connector.cpp

Go to the documentation of this file.
00001 #include "orbsvcs/SSLIOP/SSLIOP_Connector.h"
00002 #include "orbsvcs/SSLIOP/SSLIOP_OwnCredentials.h"
00003 #include "orbsvcs/SSLIOP/SSLIOP_Profile.h"
00004 #include "orbsvcs/SSLIOP/SSLIOP_X509.h"
00005 
00006 #include "orbsvcs/SecurityLevel2C.h"
00007 
00008 #include "tao/debug.h"
00009 #include "tao/ORB_Core.h"
00010 #include "tao/Client_Strategy_Factory.h"
00011 #include "tao/Environment.h"
00012 #include "tao/Base_Transport_Property.h"
00013 #include "tao/Transport_Cache_Manager.h"
00014 #include "tao/Thread_Lane_Resources.h"
00015 #include "tao/Stub.h"
00016 #include "tao/Transport_Connector.h"
00017 #include "tao/Blocked_Connect_Strategy.h"
00018 #include "tao/Wait_Strategy.h"
00019 #include "tao/Profile_Transport_Resolver.h"
00020 #include "ace/Auto_Ptr.h"
00021 #include "ace/os_include/os_netdb.h"
00022 
00023 ACE_RCSID (SSLIOP,
00024            SSLIOP_Connector,
00025            "SSLIOP_Connector.cpp,v 1.106 2006/04/21 07:22:18 jwillemsen Exp")
00026 
00027 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00028 
00029 TAO::SSLIOP::Connector::Connector (::Security::QOP qop)
00030   : TAO::IIOP_SSL_Connector (),
00031     qop_ (qop),
00032     connect_strategy_ (),
00033     base_connector_ ()
00034 {
00035 }
00036 
00037 int
00038 TAO::SSLIOP::Connector::open (TAO_ORB_Core *orb_core)
00039 {
00040   // Since the ACE_Strategy_Connector (and ACE_Connector) cannot
00041   // handle non-blocking connections with protocols that have more
00042   // than one handshake, such as SSL, force blocking connections for
00043   // SSLIOP.  This deficiency will be addressed soon.
00044   ACE_NEW_RETURN (this->active_connect_strategy_,
00045                   TAO_Blocked_Connect_Strategy (orb_core),
00046                   -1);
00047 
00048   if (this->TAO::IIOP_SSL_Connector::open (orb_core) == -1)
00049     return -1;
00050 
00051   // Our connect creation strategy
00052   CONNECT_CREATION_STRATEGY *connect_creation_strategy = 0;
00053 
00054   ACE_NEW_RETURN (connect_creation_strategy,
00055                   CONNECT_CREATION_STRATEGY
00056                       (orb_core->thr_mgr (),
00057                        orb_core,
00058                        0 /* Forcibly disable TAO's GIOPlite feature.
00059                             It introduces a security hole. */),
00060                   -1);
00061 
00062   // Our activation strategy
00063   CONNECT_CONCURRENCY_STRATEGY *concurrency_strategy = 0;
00064 
00065   ACE_NEW_RETURN (concurrency_strategy,
00066                   CONNECT_CONCURRENCY_STRATEGY (orb_core),
00067                   -1);
00068 
00069   ACE_Reactor *r = this->orb_core ()->reactor ();
00070 
00071   return this->base_connector_.open (r,
00072                                      connect_creation_strategy,
00073                                      &this->connect_strategy_,
00074                                      concurrency_strategy);
00075 }
00076 
00077 int
00078 TAO::SSLIOP::Connector::close (void)
00079 {
00080   (void) this->TAO::IIOP_SSL_Connector::close ();
00081 
00082   delete this->base_connector_.creation_strategy ();
00083   delete this->base_connector_.concurrency_strategy ();
00084   return this->base_connector_.close ();
00085 }
00086 
00087 TAO_Transport *
00088 TAO::SSLIOP::Connector::connect (TAO::Profile_Transport_Resolver *resolver,
00089                                  TAO_Transport_Descriptor_Interface *desc,
00090                                  ACE_Time_Value *timeout
00091                                  ACE_ENV_ARG_DECL)
00092 {
00093   if (TAO_debug_level > 0)
00094       ACE_DEBUG ((LM_DEBUG,
00095                   ACE_TEXT ("TAO (%P|%t) - Connector::connect, ")
00096                   ACE_TEXT ("looking for SSLIOP connection.\n")));
00097 
00098   TAO_Endpoint *endpoint = desc->endpoint ();
00099 
00100   if (endpoint->tag () != IOP::TAG_INTERNET_IOP)
00101     return 0;
00102 
00103   TAO_SSLIOP_Endpoint *ssl_endpoint =
00104     dynamic_cast<TAO_SSLIOP_Endpoint *> (endpoint);
00105 
00106   if (ssl_endpoint == 0)
00107     return 0;
00108 
00109   // @@ TODO:  The EstablishTrust policy should be evaluated once per
00110   //           connection, not once per invocation.  This should
00111   //           improve performance.
00112   //
00113   // Check if the user overrode the default establishment of trust
00114   // policy for the current object.
00115   CORBA::Policy_var policy =
00116     resolver->stub ()->get_policy (::Security::SecEstablishTrustPolicy
00117                                    ACE_ENV_ARG_PARAMETER);
00118   ACE_CHECK_RETURN (0);
00119 
00120   SecurityLevel2::EstablishTrustPolicy_var trust_policy =
00121     SecurityLevel2::EstablishTrustPolicy::_narrow (policy.in ()
00122                                                    ACE_ENV_ARG_PARAMETER);
00123   ACE_CHECK_RETURN (0);
00124 
00125   // We use a pointer and temporary to make it obvious to determine
00126   // if no establishment of trust policy was set.  Specifically, if
00127   // the "trust" pointer below is zero, then the SSLIOP pluggable
00128   // protocol default value will be used.
00129   ::Security::EstablishTrust trust = { 0 , 0 };
00130   if (!CORBA::is_nil (trust_policy.in ()))
00131     {
00132       trust = trust_policy->trust (ACE_ENV_SINGLE_ARG_PARAMETER);
00133       ACE_CHECK_RETURN (0);
00134     }
00135 
00136   // Flag that states whether any form of establishment of trust
00137   // should occur.
00138   CORBA::Boolean const establish_trust =
00139     trust.trust_in_target || trust.trust_in_client;
00140 
00141   // @@ Should this be in a "policy validator?"
00142   //
00143   // If the SSL port is zero, then no SSLIOP tagged component was
00144   // available in the IOR, meaning that there is no way to establish
00145   // trust.  Throw an exception.
00146   if (ssl_endpoint->ssl_component ().port == 0
00147       && establish_trust)
00148     {
00149       if (TAO_debug_level > 0)
00150         {
00151           ACE_ERROR ((LM_ERROR,
00152                       ACE_TEXT ("TAO_SSLIOP (%P|%t) ERROR: ")
00153                       ACE_TEXT ("Cannot establish trust since ")
00154                       ACE_TEXT ("no SSLIOP tagged component was ")
00155                       ACE_TEXT ("found in the IOR.\n")));
00156         }
00157 
00158       ACE_THROW_RETURN (CORBA::INV_POLICY (),   // @@ Correct exception?
00159                         0);
00160     }
00161 
00162   // Check if the user overrode the default Quality-of-Protection for
00163   // the current object.
00164   policy = resolver->stub ()->get_policy (::Security::SecQOPPolicy
00165                                           ACE_ENV_ARG_PARAMETER);
00166   ACE_CHECK_RETURN (0);
00167 
00168   SecurityLevel2::QOPPolicy_var qop_policy =
00169     SecurityLevel2::QOPPolicy::_narrow (policy.in ()
00170                                         ACE_ENV_ARG_PARAMETER);
00171   ACE_CHECK_RETURN (0);
00172 
00173   // Temporary variable used to avoid overwriting the default value
00174   // set when the ORB was initialized.
00175   ::Security::QOP qop = this->qop_;
00176 
00177   if (!CORBA::is_nil (qop_policy.in ()))
00178     {
00179       qop = qop_policy->qop (ACE_ENV_SINGLE_ARG_PARAMETER);
00180       ACE_CHECK_RETURN (0);
00181     }
00182 
00183   // If the SSL port is zero, then no SSLIOP tagged component was
00184   // available in the IOR, meaning that there is no way to make a
00185   // secure invocation.  Throw an exception.
00186   if (qop != ::Security::SecQOPNoProtection
00187       && ssl_endpoint->ssl_component ().port == 0)
00188     {
00189       if (TAO_debug_level > 0)
00190         {
00191           ACE_ERROR ((LM_ERROR,
00192                       ACE_TEXT ("TAO_SSLIOP (%P|%t) ERROR: ")
00193                       ACE_TEXT ("Cannot make secure invocation since ")
00194                       ACE_TEXT ("no SSLIOP tagged component was ")
00195                       ACE_TEXT ("found in the IOR.\n")));
00196         }
00197 
00198       ACE_THROW_RETURN (CORBA::INV_POLICY (),   // @@ Correct exception?
00199                         0);
00200     }
00201 
00202   if ((!establish_trust && qop == ::Security::SecQOPNoProtection)
00203       || ssl_endpoint->ssl_component ().port == 0)
00204     {
00205       return this->iiop_connect (ssl_endpoint,
00206                                  resolver,
00207                                  timeout
00208                                  ACE_ENV_ARG_PARAMETER);
00209     }
00210 
00211   return this->ssliop_connect (ssl_endpoint,
00212                                qop,
00213                                trust,
00214                                resolver,
00215                                desc,
00216                                timeout
00217                                ACE_ENV_ARG_PARAMETER);
00218 }
00219 
00220 
00221 TAO_Profile *
00222 TAO::SSLIOP::Connector::create_profile (TAO_InputCDR& cdr)
00223 {
00224   TAO_Profile *pfile = 0;
00225   ACE_NEW_RETURN (pfile,
00226                   TAO_SSLIOP_Profile (this->orb_core ()),
00227                   0);
00228 
00229   const int r = pfile->decode (cdr);
00230   if (r == -1)
00231     {
00232       pfile->_decr_refcnt ();
00233       pfile = 0;
00234     }
00235 
00236   return pfile;
00237 }
00238 
00239 TAO_Profile *
00240 TAO::SSLIOP::Connector::make_profile (ACE_ENV_SINGLE_ARG_DECL)
00241 {
00242   // The endpoint should be of the form:
00243   //    N.n@host:port/object_key
00244   // or:
00245   //    host:port/object_key
00246 
00247   TAO_Profile *profile = 0;
00248   ACE_NEW_THROW_EX (profile,
00249                     TAO_SSLIOP_Profile (this->orb_core (),
00250                                           0), // SSL component
00251                     CORBA::NO_MEMORY (
00252                       CORBA::SystemException::_tao_minor_code (
00253                         TAO::VMCID,
00254                         ENOMEM),
00255                       CORBA::COMPLETED_NO));
00256   ACE_CHECK_RETURN (0);
00257 
00258   return profile;
00259 }
00260 
00261 
00262 TAO_Profile *
00263 TAO::SSLIOP::Connector::make_secure_profile (ACE_ENV_SINGLE_ARG_DECL)
00264 {
00265   // The endpoint should be of the form:
00266   //    N.n@host:port/object_key
00267   // or:
00268   //    host:port/object_key
00269 
00270   TAO_Profile *profile = 0;
00271   ACE_NEW_THROW_EX (profile,
00272                     TAO_SSLIOP_Profile (this->orb_core (),
00273                                           1), // SSL component
00274                     CORBA::NO_MEMORY (
00275                       CORBA::SystemException::_tao_minor_code (
00276                         TAO::VMCID,
00277                         ENOMEM),
00278                       CORBA::COMPLETED_NO));
00279   ACE_CHECK_RETURN (0);
00280 
00281   return profile;
00282 }
00283 
00284 
00285 
00286 TAO_Profile *
00287 TAO::SSLIOP::Connector::corbaloc_scan (const char *endpoint,
00288                                        size_t &len
00289                                        ACE_ENV_ARG_DECL)
00290 {
00291    int ssl_only = 0;
00292    if (this->check_prefix (endpoint) == 0)
00293    {
00294        ssl_only = 1;
00295    }
00296    else
00297    {
00298        if (this->TAO_IIOP_Connector::check_prefix (endpoint) != 0)
00299          return 0;
00300    }
00301 
00302    // Determine the (first in a list of possibly > 1) endpoint address
00303    const char *comma_pos = ACE_OS::strchr (endpoint,',');
00304    const char *slash_pos = ACE_OS::strchr (endpoint,'/');
00305    if (comma_pos == 0 && slash_pos == 0)
00306    {
00307        if (TAO_debug_level)
00308        {
00309             ACE_DEBUG ((LM_DEBUG,
00310                         ACE_TEXT("(%P|%t) SSLIOP_Connector::corbaloc_scan warning: ")
00311                         ACE_TEXT("supplied string contains no comma or slash: %s\n"),
00312                         endpoint));
00313        }
00314        len = ACE_OS::strlen (endpoint);
00315    }
00316    else if (slash_pos != 0 || comma_pos > slash_pos)
00317    {
00318        // The endpoint address does not extend past the first '/' or ','
00319        len = slash_pos - endpoint;
00320    }
00321    else
00322    {
00323        len = comma_pos - endpoint;
00324    }
00325 
00326    //Create the corresponding profile
00327    TAO_Profile *ptmp = 0;
00328    if (ssl_only)
00329      {
00330        ptmp = this->make_secure_profile (ACE_ENV_SINGLE_ARG_PARAMETER);
00331        ACE_CHECK_RETURN (0);
00332      }
00333    else
00334      {
00335        ptmp = this->make_profile (ACE_ENV_SINGLE_ARG_PARAMETER);
00336        ACE_CHECK_RETURN (0);
00337      }
00338 
00339    return ptmp;
00340 }
00341 
00342 
00343 int
00344 TAO::SSLIOP::Connector::check_prefix (const char *endpoint)
00345 {
00346   // Check for a valid string
00347   if (!endpoint || !*endpoint) return -1;  // Failure
00348 
00349   const char *protocol[] = { "ssliop", "sslioploc" };
00350 
00351   size_t first_slot = ACE_OS::strchr (endpoint, ':') - endpoint;
00352 
00353   size_t len0 = ACE_OS::strlen (protocol[0]);
00354   size_t len1 = ACE_OS::strlen (protocol[1]);
00355 
00356   // Check for the proper prefix in the IOR.  If the proper prefix
00357   // isn't in the IOR then it is not an IOR we can use.
00358   if (first_slot == len0 && ACE_OS::strncmp (endpoint, protocol[0], len0) == 0)
00359     return 0;
00360 
00361   if (first_slot == len1 && ACE_OS::strncmp (endpoint, protocol[1], len1) == 0)
00362     return 0;
00363 
00364   // Failure: not an SSLIOP IOR
00365   // DO NOT throw an exception here.
00366   return -1;
00367 }
00368 
00369 
00370 TAO_Transport*
00371 TAO::SSLIOP::Connector::iiop_connect (
00372   TAO_SSLIOP_Endpoint *ssl_endpoint,
00373   TAO::Profile_Transport_Resolver *resolver,
00374   ACE_Time_Value *timeout
00375   ACE_ENV_ARG_DECL)
00376 {
00377   const ::SSLIOP::SSL &ssl_component = ssl_endpoint->ssl_component ();
00378 
00379   // Only allow connection to the insecure IIOP port if the endpoint
00380   // explicitly allows it, i.e. if the Security::NoProtection security
00381   // association bit is set in the SSLIOP::SSL::target_supports field.
00382   // The server performs the same permission check, so this check is
00383   // an optimization since a connection will not be established
00384   // needlessly, i.e. rejected due to lack of permission.
00385   //
00386   // Note that it is still possible for the standard non-SSLIOP aware
00387   // IIOP pluggable protocol to attempt to connect to the insecure
00388   // port.  In that case, the server will have to prevent the
00389   // connection, and subsequently the request, from completing.
00390   if (ACE_BIT_DISABLED (ssl_component.target_supports,
00391                         ::Security::NoProtection))
00392     ACE_THROW_RETURN (CORBA::NO_PERMISSION (
00393                         CORBA::SystemException::_tao_minor_code (
00394                           TAO::VMCID,
00395                           EPERM),
00396                         CORBA::COMPLETED_NO),
00397                       0);
00398 
00399   TAO_IIOP_Endpoint *iiop_endpoint = ssl_endpoint->iiop_endpoint ();
00400 
00401   // An IIOP-only transport descriptor must be used instead of the one
00402   // passed to this method since the latter is used for SSLIOP
00403   // connections.  Doing so prevents an IIOP-only cached transport
00404   // from being associated with an SSLIOP connection.
00405   TAO_Base_Transport_Property iiop_desc (iiop_endpoint);
00406 
00407   // Note that the IIOP-only transport descriptor is used!
00408   return
00409     this->TAO::IIOP_SSL_Connector::connect (
00410       resolver,
00411       &iiop_desc,
00412       timeout
00413       ACE_ENV_ARG_PARAMETER);
00414 }
00415 
00416 TAO_Transport *
00417 TAO::SSLIOP::Connector::ssliop_connect (
00418   TAO_SSLIOP_Endpoint *ssl_endpoint,
00419   ::Security::QOP qop,
00420   const ::Security::EstablishTrust &trust,
00421   TAO::Profile_Transport_Resolver *resolver,
00422   TAO_Transport_Descriptor_Interface *desc,
00423   ACE_Time_Value *max_wait_time
00424   ACE_ENV_ARG_DECL)
00425 {
00426   const ::SSLIOP::SSL &ssl_component = ssl_endpoint->ssl_component ();
00427 
00428   // @@ The following check for "required insecurity" seems odd, but
00429   //    I haven't seen anything in the Security spec that says this
00430   //    policy isn't possible.
00431   //      -Ossama
00432 
00433   // If the endpoint requires an insecure connection, i.e. the
00434   // Security::NoProtection security association bit in the
00435   // SSLIOP::SSL::target_requires field is enabled, then prevent an
00436   // SSL connection from occuring.
00437   if (ACE_BIT_ENABLED (ssl_component.target_requires,
00438                        ::Security::NoProtection))
00439     ACE_THROW_RETURN (CORBA::NO_PERMISSION (
00440                         CORBA::SystemException::_tao_minor_code (
00441                           TAO::VMCID,
00442                           EPERM),
00443                         CORBA::COMPLETED_NO),
00444                       0);
00445 
00446   // If the invocation wants integrity without confidentiality but the
00447   // server does not support "no protection," then it won't be
00448   // possible to provide integrity.  In order to support integrity
00449   // without confidentiality, encryption must be disabled but secure
00450   // hashes must remain enabled.  This is achieved using the "eNULL"
00451   // cipher.  However, the "eNULL" cipher is only enabled on the
00452   // server side if "no protection" is enabled.
00453   if (ACE_BIT_DISABLED (ssl_component.target_supports,
00454                         ::Security::NoProtection)
00455       && qop == ::Security::SecQOPIntegrity)
00456     ACE_THROW_RETURN (CORBA::INV_POLICY (), 0);
00457 
00458   const ACE_INET_Addr &remote_address =
00459     ssl_endpoint->object_addr ();
00460 
00461   // Verify that the remote ACE_INET_Addr was initialized
00462   // properly.  Failure can occur if hostname lookup failed when
00463   // initializing the remote ACE_INET_Addr.
00464   if (remote_address.get_type () != AF_INET)
00465     {
00466       if (TAO_debug_level > 0)
00467         {
00468           ACE_DEBUG ((LM_DEBUG,
00469                       ACE_TEXT ("TAO (%P|%t) SSLIOP connection failed.\n")
00470                       ACE_TEXT ("TAO (%P|%t) This is most likely ")
00471                       ACE_TEXT ("due to a hostname lookup ")
00472                       ACE_TEXT ("failure.\n")));
00473         }
00474 
00475       return 0;
00476     }
00477 
00478   int result = 0;
00479   TAO::SSLIOP::Connection_Handler *svc_handler = 0;
00480   TAO_Transport *transport = 0;
00481 
00482   // Before we can check the cache to find an existing connection, we
00483   // need to make sure the ssl_endpoint is fully initialized with the
00484   // local security information. This endpoint initalized by the
00485   // profile does not (and cannot) contain the desired QOP, trust, or
00486   // credential information which is necesary to uniquely identify
00487   // this connection.
00488   if (!ssl_endpoint->credentials_set ())
00489     {
00490       if (TAO_debug_level > 2)
00491         ACE_DEBUG ((LM_ERROR,
00492                     ACE_TEXT ("TAO (%P|%t) Initializing SSLIOP_Endpoint \n")
00493                     ));
00494 
00495       if (this->base_connector_.creation_strategy ()->make_svc_handler (
00496                svc_handler) != 0)
00497         {
00498           if (TAO_debug_level > 0)
00499             ACE_DEBUG ((LM_ERROR,
00500                         ACE_TEXT ("TAO (%P|%t) Unable to create SSLIOP ")
00501                         ACE_TEXT ("service handler.\n")));
00502 
00503           return 0;
00504         }
00505 
00506       ACE_Auto_Basic_Ptr<TAO::SSLIOP::Connection_Handler>
00507         safe_handler (svc_handler);
00508       TAO::SSLIOP::OwnCredentials_var credentials =
00509         this->retrieve_credentials (resolver->stub (),
00510                                     svc_handler->peer ().ssl ()
00511                                     ACE_ENV_ARG_PARAMETER);
00512       ACE_CHECK_RETURN (0);
00513 
00514       svc_handler = safe_handler.release ();
00515       ssl_endpoint->set_sec_attrs (qop, trust, credentials.in());
00516     }
00517 
00518   // Check the Cache first for connections
00519   if (this->orb_core ()->lane_resources ().transport_cache ().find_transport (
00520         desc,
00521         transport) == 0)
00522     {
00523       if (TAO_debug_level > 2)
00524         ACE_DEBUG ((LM_DEBUG,
00525                     ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, ")
00526                     ACE_TEXT ("got existing transport[%d]\n"),
00527                     transport->id ()));
00528 
00529       // When the transport is not connected wait for completion
00530       if (!transport->is_connected())
00531         {
00532           if (!this->wait_for_connection_completion (resolver,
00533                                                      transport,
00534                                                      max_wait_time))
00535             {
00536               ACE_ERROR ((LM_ERROR,
00537                           ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect,")
00538                           ACE_TEXT ("wait for completion failed\n")));
00539 
00540             }
00541         }
00542     }
00543   else
00544     {
00545       if (TAO_debug_level > 4)
00546         ACE_DEBUG ((LM_DEBUG,
00547                     ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, ")
00548                     ACE_TEXT ("making a new connection \n")));
00549 
00550       // Purge connections (if necessary)
00551       this->orb_core ()->lane_resources ().transport_cache ().purge ();
00552 
00553       // The svc_handler is created beforehand so that we can get
00554       // access to the underlying ACE_SSL_SOCK_Stream (the peer) and
00555       // its SSL pointer member prior to descending into the
00556       // ACE_Strategy_Connector (the "base_connector_").  This is
00557       // thread-safe and reentrant, hence no synchronization is
00558       // necessary.
00559       //
00560       // The make_svc_handler() method creates the service handler and
00561       // bumps the #REFCOUNT# up one extra.  The extra reference count
00562       // in TAO_Connect_Creation_Strategy::make_svc_handler() is
00563       // needed in the case when connection completion is pending and
00564       // we are going to wait on a variable in the handler to changes,
00565       // signifying success or failure.  Note, that this increment
00566       // cannot be done once the connect() returns since this might be
00567       // too late if another thread pick up the completion and
00568       // potentially deletes the handler before we get a chance to
00569       // increment the reference count.
00570       if (svc_handler == 0 &&
00571           this->base_connector_.creation_strategy ()->make_svc_handler (
00572                svc_handler) != 0)
00573         {
00574           if (TAO_debug_level > 0)
00575             ACE_DEBUG ((LM_ERROR,
00576                         ACE_TEXT ("TAO (%P|%t) Unable to create SSLIOP ")
00577                         ACE_TEXT ("service handler.\n")));
00578 
00579           return 0;
00580         }
00581 
00582       ACE_Auto_Basic_Ptr<TAO::SSLIOP::Connection_Handler>
00583         safe_handler (svc_handler);
00584 
00585       // Setup the establishment of trust connection properties, if
00586       // any.
00587       int verify_mode = 0;
00588 
00589       // On the server side, "trust_in_client" requires that a peer
00590       // (client) certificate exist.  Fail if one doesn't exist.
00591       //
00592       // In SSLIOP's case, trust_in_client also implies
00593       // trust_in_target.
00594       if (trust.trust_in_client)
00595         verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00596 
00597       // Require verification of the target's certificate.
00598       else if (trust.trust_in_target)
00599         verify_mode = SSL_VERIFY_PEER;
00600 
00601       // Trust in neither the client nor the target is explicitly
00602       // specified.  Use the default setting.
00603       else
00604         verify_mode =
00605           ACE_SSL_Context::instance ()->default_verify_mode ();
00606 
00607       ::SSL_set_verify (svc_handler->peer ().ssl (),
00608                         verify_mode,
00609                         0);
00610 
00611       // The "eNULL" cipher disables encryption but still uses a
00612       // secure hash (e.g. SHA1 or MD5) to ensure integrity.  (Try the
00613       // command "openssl ciphers -v eNULL".)
00614       //
00615       // Note that it is not possible to completely disable protection
00616       // here.
00617       if ((qop == ::Security::SecQOPNoProtection
00618           || qop == ::Security::SecQOPIntegrity)
00619           && ::SSL_set_cipher_list (svc_handler->peer ().ssl (),
00620                                     "eNULL") == 0)
00621         {
00622           if (TAO_debug_level > 0)
00623             ACE_DEBUG ((LM_ERROR,
00624                         ACE_TEXT ("(%P|%t) Unable to set eNULL ")
00625                         ACE_TEXT ("SSL cipher.\n")));
00626 
00627           ACE_THROW_RETURN (CORBA::INV_POLICY (), 0);
00628         }
00629 
00630       svc_handler = safe_handler.release ();
00631 
00632       // Get the right synch options
00633       ACE_Synch_Options synch_options;
00634 
00635       this->active_connect_strategy_->synch_options (max_wait_time,
00636                                                      synch_options);
00637 
00638       // If we don't need to block for a transport just set the timeout to
00639       // be zero.
00640       ACE_Time_Value tmp_zero (ACE_Time_Value::zero);
00641       if (!resolver->blocked_connect ())
00642         {
00643           synch_options.timeout (ACE_Time_Value::zero);
00644           max_wait_time = &tmp_zero;
00645         }
00646 
00647       // We obtain the transport in the <svc_handler> variable.  As we
00648       // know now that the connection is not available in Cache we can
00649       // make a new connection
00650       result = this->base_connector_.connect (svc_handler,
00651                                               remote_address,
00652                                               synch_options);
00653 
00654       // There are three possibilities from calling connect(): (a)
00655       // connection succeeds immediately - in this case, the
00656       // #REFCOUNT# on the handler is two; (b) connection completion
00657       // is pending - in this case, the #REFCOUNT# on the handler is
00658       // also two; (c) connection fails immediately - in this case,
00659       // the #REFCOUNT# on the handler is one since close() gets
00660       // called on the handler.
00661 
00662       // Make sure that we always do a remove_reference
00663       ACE_Event_Handler_var svc_handler_auto_ptr (svc_handler);
00664 
00665       transport =
00666         svc_handler->transport ();
00667 
00668       if (result == -1)
00669         {
00670           // No immediate result, wait for completion
00671           if (errno == EWOULDBLOCK)
00672             {
00673               // Try to wait until connection completion. Incase we block, then we
00674               // get a connected transport or not. In case of non block we get
00675               // a connected or not connected transport
00676               if (!this->wait_for_connection_completion (resolver,
00677                                                          transport,
00678                                                          max_wait_time))
00679                 {
00680                   if (TAO_debug_level > 2)
00681                     ACE_ERROR ((LM_ERROR, "TAO (%P|%t) - SSLIOP_Connector::"
00682                                           "ssliop_connect, "
00683                                           "wait for completion failed\n"));
00684                 }
00685             }
00686           else
00687             {
00688               // Transport is not usable
00689               transport = 0;
00690             }
00691         }
00692 
00693       // In case of errors transport is zero
00694       if (transport == 0)
00695         {
00696           // Give users a clue to the problem.
00697           if (TAO_debug_level)
00698             {
00699               char buffer [MAXHOSTNAMELEN + 6 + 1];
00700               ssl_endpoint->addr_to_string (buffer,
00701                                             sizeof (buffer) - 1);
00702               ACE_DEBUG ((LM_ERROR,
00703                           ACE_TEXT ("TAO (%P|%t) - SSL connection to ")
00704                           ACE_TEXT ("<%s:%d> failed (%p)\n"),
00705                           buffer,
00706                           remote_address.get_port_number (),
00707                           ACE_TEXT ("errno")));
00708             }
00709 
00710           return 0;
00711         }
00712 
00713       // At this point, the connection has be successfully connected.
00714       // #REFCOUNT# is one.
00715       if (TAO_debug_level > 2)
00716         ACE_DEBUG ((LM_DEBUG,
00717                     "TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, "
00718                     "new SSL connection to port %d on transport[%d]\n",
00719                     remote_address.get_port_number (),
00720                     svc_handler->peer ().get_handle ()));
00721 
00722       // Add the handler to Cache
00723       int retval =
00724         this->orb_core ()->
00725           lane_resources ().transport_cache ().cache_transport (desc,
00726                                                                 transport);
00727 
00728       // Failure in adding to cache.
00729       if (retval != 0)
00730         {
00731           // Close the handler.
00732           svc_handler->close ();
00733 
00734           if (TAO_debug_level > 0)
00735             {
00736               ACE_ERROR ((LM_ERROR,
00737                           "TAO (%P|%t) - SLIIOP_Connector::ssliop_connect, "
00738                           "could not add the new connection to cache\n"));
00739             }
00740 
00741           return 0;
00742         }
00743 
00744       if (transport->is_connected () &&
00745           transport->wait_strategy ()->register_handler () != 0)
00746         {
00747           // Registration failures.
00748 
00749           // Purge from the connection cache, if we are not in the cache, this
00750           // just does nothing.
00751           (void) transport->purge_entry ();
00752 
00753           // Close the handler.
00754           (void) transport->close_connection ();
00755 
00756           if (TAO_debug_level > 0)
00757             ACE_ERROR ((LM_ERROR,
00758                         "TAO (%P|%t) - SSLIOP_Connector [%d]::ssliop_connect, "
00759                         "could not register the transport "
00760                         "in the reactor.\n",
00761                         transport->id ()));
00762 
00763           return 0;
00764         }
00765     }
00766 
00767   return transport;
00768 }
00769 
00770 TAO::SSLIOP::OwnCredentials *
00771 TAO::SSLIOP::Connector::retrieve_credentials (TAO_Stub *stub,
00772                                               SSL *ssl
00773                                               ACE_ENV_ARG_DECL)
00774 {
00775   // Check if the user overrode the default invocation credentials.
00776   CORBA::Policy_var policy =
00777     stub->get_policy (::SecurityLevel3::ContextEstablishmentPolicyType
00778                       ACE_ENV_ARG_PARAMETER);
00779   ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
00780 
00781   SecurityLevel3::ContextEstablishmentPolicy_var creds_policy =
00782     SecurityLevel3::ContextEstablishmentPolicy::_narrow (
00783       policy.in ()
00784       ACE_ENV_ARG_PARAMETER);
00785   ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
00786 
00787   TAO::SSLIOP::OwnCredentials_var ssliop_credentials;
00788 
00789   // Set the Credentials (X.509 certificates and corresponding private
00790   // keys) to be used for this invocation.
00791   if (!CORBA::is_nil (creds_policy.in ()))
00792     {
00793       SecurityLevel3::OwnCredentialsList_var creds_list =
00794         creds_policy->creds_list (ACE_ENV_SINGLE_ARG_PARAMETER);
00795       ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
00796 
00797       if (creds_list->length () > 0)
00798         {
00799           // Assume that we've got an SSLIOP credential.
00800           SecurityLevel3::Credentials_ptr credentials =
00801             creds_list[0u];
00802 
00803           ssliop_credentials =
00804             TAO::SSLIOP::OwnCredentials::_narrow (credentials
00805                                                   ACE_ENV_ARG_PARAMETER);
00806           ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
00807 
00808           if (!CORBA::is_nil (ssliop_credentials.in ()))
00809             {
00810               TAO::SSLIOP::X509_var x509 = ssliop_credentials->x509 ();
00811               if (::SSL_use_certificate (ssl, x509.in ()) != 1)
00812                 return TAO::SSLIOP::OwnCredentials::_nil ();
00813 
00814               TAO::SSLIOP::EVP_PKEY_var evp = ssliop_credentials->evp ();
00815               if (evp.in () != 0
00816                   && ::SSL_use_PrivateKey (ssl, evp.in ()) != 1)
00817                 {
00818                   // Invalidate the certificate we just set.
00819                   (void) ::SSL_use_certificate (ssl, 0);
00820                   return TAO::SSLIOP::OwnCredentials::_nil ();
00821                 }
00822             }
00823         }
00824     }
00825   else
00826     {
00827       // Use the default certificate and private key, i.e. the one set
00828       // in the SSL_CTX that was used when creating the SSL data
00829       // structure.
00830 
00831       /**
00832        * @todo Check if the CredentialsCurator contains a default set
00833        *       of SSLIOP OwnCredentials.
00834        */
00835 
00836       TAO::SSLIOP::OwnCredentials_ptr & c = ssliop_credentials.out ();
00837       ACE_NEW_THROW_EX (c,
00838                         TAO::SSLIOP::OwnCredentials (
00839                           ::SSL_get_certificate (ssl),
00840                           ::SSL_get_privatekey (ssl)),
00841                         CORBA::NO_MEMORY ());
00842       ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
00843     }
00844 
00845   return ssliop_credentials._retn ();
00846 }
00847 
00848 int
00849 TAO::SSLIOP::Connector::cancel_svc_handler (
00850   TAO_Connection_Handler * svc_handler)
00851 {
00852   TAO::SSLIOP::Connection_Handler* handler=
00853     dynamic_cast<TAO::SSLIOP::Connection_Handler*> (svc_handler);
00854 
00855   if (handler)
00856     // Cancel from the connector
00857     return this->base_connector_.cancel (handler);
00858 
00859   return -1;
00860 }
00861 
00862 TAO_END_VERSIONED_NAMESPACE_DECL

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