TAO::SSLIOP::Connector Class Reference

SSLIOP-specific Connector bridge for pluggable protocols. More...

#include <SSLIOP_Connector.h>

Collaboration diagram for TAO::SSLIOP::Connector:

Collaboration graph
[legend]
List of all members.

Public Types

typedef TAO_Connect_Concurrency_Strategy<
Connection_Handler
CONNECT_CONCURRENCY_STRATEGY
typedef TAO_Connect_Creation_Strategy<
Connection_Handler
CONNECT_CREATION_STRATEGY
typedef ACE_Connect_Strategy<
Connection_Handler, ACE_SSL_SOCK_CONNECTOR > 
CONNECT_STRATEGY
typedef ACE_Strategy_Connector<
Connection_Handler, ACE_SSL_SOCK_CONNECTOR > 
BASE_CONNECTOR

Public Member Functions

 Connector (::Security::QOP qop)
 Constructor.
The TAO_Connector methods
Please check the documentation in Transport_Connector.h

virtual int open (TAO_ORB_Core *orb_core)
virtual int close (void)
virtual TAO_Transportconnect (TAO::Profile_Transport_Resolver *r, TAO_Transport_Descriptor_Interface *desc, ACE_Time_Value *timeout)
virtual TAO_Profilecreate_profile (TAO_InputCDR &cdr)
virtual int check_prefix (const char *endpoint)
virtual TAO_Profilecorbaloc_scan (const char *ior, size_t &len)

Protected Member Functions

TAO_Profilemake_secure_profile (void)
 SSL-specific profile.
TAO_Transportiiop_connect (TAO_SSLIOP_Endpoint *ssliop_endpoint, TAO::Profile_Transport_Resolver *r, ACE_Time_Value *timeout)
 IIOP-specific connection establishment.
TAO_Transportssliop_connect (TAO_SSLIOP_Endpoint *ssliop_endpoint,::Security::QOP qop, const ::Security::EstablishTrust &trust, TAO::Profile_Transport_Resolver *r, TAO_Transport_Descriptor_Interface *desc, ACE_Time_Value *timeout)
 SSLIOP-specific connection establishment.
TAO::SSLIOP::OwnCredentialsretrieve_credentials (TAO_Stub *stub, SSL *ssl)
@c TAO_Connector Methods
Methods required by the TAO_Connector base class.

See also:
TAO_Connector


virtual TAO_Profilemake_profile (void)
virtual int cancel_svc_handler (TAO_Connection_Handler *svc_handler)

Private Attributes

::Security::QOP qop_
CONNECT_STRATEGY connect_strategy_
 Our connect strategy.
BASE_CONNECTOR base_connector_
 The connector initiating connection requests for IIOP.

Detailed Description

SSLIOP-specific Connector bridge for pluggable protocols.

Concrete instance of the TAO_Connector class. Responsible for establishing a connection with a server and is called from the Connector_Registry.

Definition at line 55 of file SSLIOP_Connector.h.


Member Typedef Documentation

typedef ACE_Strategy_Connector<Connection_Handler, ACE_SSL_SOCK_CONNECTOR> TAO::SSLIOP::Connector::BASE_CONNECTOR

Definition at line 132 of file SSLIOP_Connector.h.

typedef TAO_Connect_Concurrency_Strategy<Connection_Handler> TAO::SSLIOP::Connector::CONNECT_CONCURRENCY_STRATEGY

Definition at line 121 of file SSLIOP_Connector.h.

typedef TAO_Connect_Creation_Strategy<Connection_Handler> TAO::SSLIOP::Connector::CONNECT_CREATION_STRATEGY

Definition at line 124 of file SSLIOP_Connector.h.

typedef ACE_Connect_Strategy<Connection_Handler, ACE_SSL_SOCK_CONNECTOR> TAO::SSLIOP::Connector::CONNECT_STRATEGY

Definition at line 128 of file SSLIOP_Connector.h.


Constructor & Destructor Documentation

TAO_BEGIN_VERSIONED_NAMESPACE_DECL TAO::SSLIOP::Connector::Connector ( ::Security::QOP  qop  ) 

Constructor.

Definition at line 28 of file SSLIOP_Connector.cpp.

00029   : TAO::IIOP_SSL_Connector (),
00030     qop_ (qop),
00031     connect_strategy_ (),
00032     base_connector_ ()
00033 {
00034 }


Member Function Documentation

int TAO::SSLIOP::Connector::cancel_svc_handler ( TAO_Connection_Handler svc_handler  )  [protected, virtual]

Definition at line 845 of file SSLIOP_Connector.cpp.

References base_connector_, and ACE_Connector< SVC_HANDLER, >::cancel().

00847 {
00848   TAO::SSLIOP::Connection_Handler* handler=
00849     dynamic_cast<TAO::SSLIOP::Connection_Handler*> (svc_handler);
00850 
00851   if (handler)
00852     // Cancel from the connector
00853     return this->base_connector_.cancel (handler);
00854 
00855   return -1;
00856 }

int TAO::SSLIOP::Connector::check_prefix ( const char *  endpoint  )  [virtual]

Definition at line 317 of file SSLIOP_Connector.cpp.

References ACE_OS::strchr(), ACE_OS::strlen(), and ACE_OS::strncmp().

00318 {
00319   // Check for a valid string
00320   if (!endpoint || !*endpoint) return -1;  // Failure
00321 
00322   const char *protocol[] = { "ssliop", "sslioploc" };
00323 
00324   size_t first_slot = ACE_OS::strchr (endpoint, ':') - endpoint;
00325 
00326   size_t len0 = ACE_OS::strlen (protocol[0]);
00327   size_t len1 = ACE_OS::strlen (protocol[1]);
00328 
00329   // Check for the proper prefix in the IOR.  If the proper prefix
00330   // isn't in the IOR then it is not an IOR we can use.
00331   if (first_slot == len0 && ACE_OS::strncmp (endpoint, protocol[0], len0) == 0)
00332     return 0;
00333 
00334   if (first_slot == len1 && ACE_OS::strncmp (endpoint, protocol[1], len1) == 0)
00335     return 0;
00336 
00337   // Failure: not an SSLIOP IOR
00338   // DO NOT throw an exception here.
00339   return -1;
00340 }

int TAO::SSLIOP::Connector::close ( void   )  [virtual]

Definition at line 75 of file SSLIOP_Connector.cpp.

References base_connector_, ACE_Strategy_Connector< SVC_HANDLER, >::close(), ACE_Strategy_Connector< SVC_HANDLER, >::concurrency_strategy(), and ACE_Strategy_Connector< SVC_HANDLER, >::creation_strategy().

00076 {
00077   (void) this->TAO::IIOP_SSL_Connector::close ();
00078 
00079   delete this->base_connector_.creation_strategy ();
00080   delete this->base_connector_.concurrency_strategy ();
00081   return this->base_connector_.close ();
00082 }

TAO_Transport * TAO::SSLIOP::Connector::connect ( TAO::Profile_Transport_Resolver *  r,
TAO_Transport_Descriptor_Interface desc,
ACE_Time_Value timeout 
) [virtual]

Definition at line 85 of file SSLIOP_Connector.cpp.

References ACE_DEBUG, ACE_ERROR, ACE_TEXT(), TAO_Transport_Descriptor_Interface::endpoint(), TAO_Objref_Var_T< T >::in(), CORBA::is_nil(), LM_DEBUG, LM_ERROR, SSLIOP::SSL::port, qop_, Security::SecEstablishTrustPolicy, Security::SecQOPNoProtection, Security::SecQOPPolicy, TAO_SSLIOP_Endpoint::ssl_component(), ssliop_connect(), TAO_Endpoint::tag(), and TAO_debug_level.

00088 {
00089   if (TAO_debug_level > 0)
00090       ACE_DEBUG ((LM_DEBUG,
00091                   ACE_TEXT ("TAO_SSLIOP (%P|%t) - Connector::connect, ")
00092                   ACE_TEXT ("looking for SSLIOP connection.\n")));
00093 
00094   TAO_Endpoint *endpoint = desc->endpoint ();
00095 
00096   if (endpoint->tag () != IOP::TAG_INTERNET_IOP)
00097     return 0;
00098 
00099   TAO_SSLIOP_Endpoint *ssl_endpoint =
00100     dynamic_cast<TAO_SSLIOP_Endpoint *> (endpoint);
00101 
00102   if (ssl_endpoint == 0)
00103     return 0;
00104 
00105   // @@ TODO:  The EstablishTrust policy should be evaluated once per
00106   //           connection, not once per invocation.  This should
00107   //           improve performance.
00108   //
00109   // Check if the user overrode the default establishment of trust
00110   // policy for the current object.
00111   CORBA::Policy_var policy =
00112     resolver->stub ()->get_policy (::Security::SecEstablishTrustPolicy);
00113 
00114   SecurityLevel2::EstablishTrustPolicy_var trust_policy =
00115     SecurityLevel2::EstablishTrustPolicy::_narrow (policy.in ());
00116 
00117   // We use a pointer and temporary to make it obvious to determine
00118   // if no establishment of trust policy was set.  Specifically, if
00119   // the "trust" pointer below is zero, then the SSLIOP pluggable
00120   // protocol default value will be used.
00121   ::Security::EstablishTrust trust = { 0 , 0 };
00122   if (!CORBA::is_nil (trust_policy.in ()))
00123     {
00124       trust = trust_policy->trust ();
00125     }
00126 
00127   // Flag that states whether any form of establishment of trust
00128   // should occur.
00129   CORBA::Boolean const establish_trust =
00130     trust.trust_in_target || trust.trust_in_client;
00131 
00132   // @@ Should this be in a "policy validator?"
00133   //
00134   // If the SSL port is zero, then no SSLIOP tagged component was
00135   // available in the IOR, meaning that there is no way to establish
00136   // trust.  Throw an exception.
00137   if (ssl_endpoint->ssl_component ().port == 0
00138       && establish_trust)
00139     {
00140       if (TAO_debug_level > 0)
00141         {
00142           ACE_ERROR ((LM_ERROR,
00143                       ACE_TEXT ("TAO_SSLIOP (%P|%t) ERROR: ")
00144                       ACE_TEXT ("Cannot establish trust since ")
00145                       ACE_TEXT ("no SSLIOP tagged component was ")
00146                       ACE_TEXT ("found in the IOR.\n")));
00147         }
00148 
00149       throw CORBA::INV_POLICY ();
00150     }
00151 
00152   // Check if the user overrode the default Quality-of-Protection for
00153   // the current object.
00154   policy = resolver->stub ()->get_policy (::Security::SecQOPPolicy);
00155 
00156   SecurityLevel2::QOPPolicy_var qop_policy =
00157     SecurityLevel2::QOPPolicy::_narrow (policy.in ());
00158 
00159   // Temporary variable used to avoid overwriting the default value
00160   // set when the ORB was initialized.
00161   ::Security::QOP qop = this->qop_;
00162 
00163   if (!CORBA::is_nil (qop_policy.in ()))
00164     {
00165       qop = qop_policy->qop ();
00166     }
00167 
00168   // If the SSL port is zero, then no SSLIOP tagged component was
00169   // available in the IOR, meaning that there is no way to make a
00170   // secure invocation.  Throw an exception.
00171   if (qop != ::Security::SecQOPNoProtection
00172       && ssl_endpoint->ssl_component ().port == 0)
00173     {
00174       if (TAO_debug_level > 0)
00175         {
00176           ACE_ERROR ((LM_ERROR,
00177                       ACE_TEXT ("TAO_SSLIOP (%P|%t) ERROR: ")
00178                       ACE_TEXT ("Cannot make secure invocation since ")
00179                       ACE_TEXT ("no SSLIOP tagged component was ")
00180                       ACE_TEXT ("found in the IOR.\n")));
00181         }
00182 
00183       throw CORBA::INV_POLICY ();
00184     }
00185 
00186   if ((!establish_trust && qop == ::Security::SecQOPNoProtection)
00187       || ssl_endpoint->ssl_component ().port == 0)
00188     {
00189       return this->iiop_connect (ssl_endpoint, resolver, timeout);
00190     }
00191 
00192   return this->ssliop_connect (ssl_endpoint,
00193                                qop,
00194                                trust,
00195                                resolver,
00196                                desc,
00197                                timeout);
00198 }

TAO_Profile * TAO::SSLIOP::Connector::corbaloc_scan ( const char *  ior,
size_t &  len 
) [virtual]

Definition at line 264 of file SSLIOP_Connector.cpp.

References ACE_DEBUG, ACE_TEXT(), LM_DEBUG, make_profile(), make_secure_profile(), ACE_OS::strchr(), ACE_OS::strlen(), and TAO_debug_level.

00265 {
00266    int ssl_only = 0;
00267    if (this->check_prefix (endpoint) == 0)
00268    {
00269        ssl_only = 1;
00270    }
00271    else
00272    {
00273        if (this->TAO_IIOP_Connector::check_prefix (endpoint) != 0)
00274          return 0;
00275    }
00276 
00277    // Determine the (first in a list of possibly > 1) endpoint address
00278    const char *comma_pos = ACE_OS::strchr (endpoint,',');
00279    const char *slash_pos = ACE_OS::strchr (endpoint,'/');
00280    if (comma_pos == 0 && slash_pos == 0)
00281    {
00282        if (TAO_debug_level)
00283        {
00284             ACE_DEBUG ((LM_DEBUG,
00285                         ACE_TEXT("(%P|%t) SSLIOP_Connector::corbaloc_scan warning: ")
00286                         ACE_TEXT("supplied string contains no comma or slash: %s\n"),
00287                         endpoint));
00288        }
00289        len = ACE_OS::strlen (endpoint);
00290    }
00291    else if (slash_pos != 0 || comma_pos > slash_pos)
00292    {
00293        // The endpoint address does not extend past the first '/' or ','
00294        len = slash_pos - endpoint;
00295    }
00296    else
00297    {
00298        len = comma_pos - endpoint;
00299    }
00300 
00301    //Create the corresponding profile
00302    TAO_Profile *ptmp = 0;
00303    if (ssl_only)
00304      {
00305        ptmp = this->make_secure_profile ();
00306      }
00307    else
00308      {
00309        ptmp = this->make_profile ();
00310      }
00311 
00312    return ptmp;
00313 }

TAO_Profile * TAO::SSLIOP::Connector::create_profile ( TAO_InputCDR cdr  )  [virtual]

Definition at line 202 of file SSLIOP_Connector.cpp.

References TAO_Profile::_decr_refcnt(), ACE_NEW_RETURN, and TAO_Profile::decode().

00203 {
00204   TAO_Profile *pfile = 0;
00205   ACE_NEW_RETURN (pfile,
00206                   TAO_SSLIOP_Profile (this->orb_core ()),
00207                   0);
00208 
00209   if (pfile->decode (cdr) == -1)
00210     {
00211       pfile->_decr_refcnt ();
00212       pfile = 0;
00213     }
00214 
00215   return pfile;
00216 }

TAO_Transport * TAO::SSLIOP::Connector::iiop_connect ( TAO_SSLIOP_Endpoint ssliop_endpoint,
TAO::Profile_Transport_Resolver *  r,
ACE_Time_Value timeout 
) [protected]

IIOP-specific connection establishment.

Note:
The IIOP endpoint is extracted from the SSLIOP endpoint.

Definition at line 344 of file SSLIOP_Connector.cpp.

References CORBA::SystemException::_tao_minor_code(), ACE_BIT_DISABLED, CORBA::COMPLETED_NO, connect(), TAO_SSLIOP_Endpoint::iiop_endpoint(), Security::NoProtection, TAO_SSLIOP_Endpoint::ssl_component(), and TAO::VMCID.

00348 {
00349 #if 0
00350   const ::SSLIOP::SSL &ssl_component = ssl_endpoint->ssl_component ();
00351 
00352   // Only allow connection to the insecure IIOP port if the endpoint
00353   // explicitly allows it, i.e. if the Security::NoProtection security
00354   // association bit is set in the SSLIOP::SSL::target_supports field.
00355   // The server performs the same permission check, so this check is
00356   // an optimization since a connection will not be established
00357   // needlessly, i.e. rejected due to lack of permission.
00358   //
00359   // Note that it is still possible for the standard non-SSLIOP aware
00360   // IIOP pluggable protocol to attempt to connect to the insecure
00361   // port.  In that case, the server will have to prevent the
00362   // connection, and subsequently the request, from completing.
00363   if (ACE_BIT_DISABLED (ssl_component.target_supports,
00364                         ::Security::NoProtection))
00365     throw CORBA::NO_PERMISSION (
00366       CORBA::SystemException::_tao_minor_code (
00367         TAO::VMCID,
00368         EPERM),
00369       CORBA::COMPLETED_NO);
00370 #endif
00371 
00372   TAO_IIOP_Endpoint *iiop_endpoint = ssl_endpoint->iiop_endpoint ();
00373 
00374   // An IIOP-only transport descriptor must be used instead of the one
00375   // passed to this method since the latter is used for SSLIOP
00376   // connections.  Doing so prevents an IIOP-only cached transport
00377   // from being associated with an SSLIOP connection.
00378   TAO_Base_Transport_Property iiop_desc (iiop_endpoint);
00379 
00380   // Note that the IIOP-only transport descriptor is used!
00381   return
00382     this->TAO::IIOP_SSL_Connector::connect (resolver, &iiop_desc, timeout);
00383 }

TAO_Profile * TAO::SSLIOP::Connector::make_profile ( void   )  [protected, virtual]

Definition at line 219 of file SSLIOP_Connector.cpp.

References CORBA::SystemException::_tao_minor_code(), ACE_NEW_THROW_EX, CORBA::COMPLETED_NO, and TAO::VMCID.

Referenced by corbaloc_scan().

00220 {
00221   // The endpoint should be of the form:
00222   //    N.n@host:port/object_key
00223   // or:
00224   //    host:port/object_key
00225 
00226   TAO_Profile *profile = 0;
00227   ACE_NEW_THROW_EX (profile,
00228                     TAO_SSLIOP_Profile (this->orb_core (),
00229                                           0), // SSL component
00230                     CORBA::NO_MEMORY (
00231                       CORBA::SystemException::_tao_minor_code (
00232                         TAO::VMCID,
00233                         ENOMEM),
00234                       CORBA::COMPLETED_NO));
00235 
00236   return profile;
00237 }

TAO_Profile * TAO::SSLIOP::Connector::make_secure_profile ( void   )  [protected]

SSL-specific profile.

Definition at line 241 of file SSLIOP_Connector.cpp.

References CORBA::SystemException::_tao_minor_code(), ACE_NEW_THROW_EX, CORBA::COMPLETED_NO, and TAO::VMCID.

Referenced by corbaloc_scan().

00242 {
00243   // The endpoint should be of the form:
00244   //    N.n@host:port/object_key
00245   // or:
00246   //    host:port/object_key
00247 
00248   TAO_Profile *profile = 0;
00249   ACE_NEW_THROW_EX (profile,
00250                     TAO_SSLIOP_Profile (this->orb_core (),
00251                                           1), // SSL component
00252                     CORBA::NO_MEMORY (
00253                       CORBA::SystemException::_tao_minor_code (
00254                         TAO::VMCID,
00255                         ENOMEM),
00256                       CORBA::COMPLETED_NO));
00257 
00258   return profile;
00259 }

int TAO::SSLIOP::Connector::open ( TAO_ORB_Core orb_core  )  [virtual]

Definition at line 37 of file SSLIOP_Connector.cpp.

References ACE_NEW_RETURN, base_connector_, ACE_Strategy_Connector< SVC_HANDLER, >::open(), and TAO_ORB_Core::thr_mgr().

00038 {
00039   // Since the ACE_Strategy_Connector (and ACE_Connector) cannot
00040   // handle non-blocking connections with protocols that have more
00041   // than one handshake, such as SSL, force blocking connections for
00042   // SSLIOP.  This deficiency will be addressed soon.
00043   ACE_NEW_RETURN (this->active_connect_strategy_,
00044                   TAO_Blocked_Connect_Strategy (orb_core),
00045                   -1);
00046 
00047   if (this->TAO::IIOP_SSL_Connector::open (orb_core) == -1)
00048     return -1;
00049 
00050   // Our connect creation strategy
00051   CONNECT_CREATION_STRATEGY *connect_creation_strategy = 0;
00052 
00053   ACE_NEW_RETURN (connect_creation_strategy,
00054                   CONNECT_CREATION_STRATEGY
00055                       (orb_core->thr_mgr (),
00056                        orb_core),
00057                   -1);
00058 
00059   // Our activation strategy
00060   CONNECT_CONCURRENCY_STRATEGY *concurrency_strategy = 0;
00061 
00062   ACE_NEW_RETURN (concurrency_strategy,
00063                   CONNECT_CONCURRENCY_STRATEGY (orb_core),
00064                   -1);
00065 
00066   ACE_Reactor *r = this->orb_core ()->reactor ();
00067 
00068   return this->base_connector_.open (r,
00069                                      connect_creation_strategy,
00070                                      &this->connect_strategy_,
00071                                      concurrency_strategy);
00072 }

TAO::SSLIOP::OwnCredentials * TAO::SSLIOP::Connector::retrieve_credentials ( TAO_Stub stub,
SSL *  ssl 
) [protected]

Retrieve SSLIOP credentials from the policy overrides list and set up the underlying SSL connection to use the X.509 certificates stored within them.

Todo:
Check if the CredentialsCurator contains a default set of SSLIOP OwnCredentials.

Definition at line 776 of file SSLIOP_Connector.cpp.

References TAO::SSLIOP::OwnCredentials::_narrow(), TAO::SSLIOP::OwnCredentials::_nil(), ACE_NEW_THROW_EX, TAO_Stub::get_policy(), TAO::SSLIOP::OpenSSL_st_var< T >::in(), TAO_Objref_Var_T< T >::in(), and CORBA::is_nil().

Referenced by ssliop_connect().

00778 {
00779   // Check if the user overrode the default invocation credentials.
00780   CORBA::Policy_var policy =
00781     stub->get_policy (::SecurityLevel3::ContextEstablishmentPolicyType);
00782 
00783   SecurityLevel3::ContextEstablishmentPolicy_var creds_policy =
00784     SecurityLevel3::ContextEstablishmentPolicy::_narrow (
00785       policy.in ());
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 ();
00795 
00796       if (creds_list->length () > 0)
00797         {
00798           // Assume that we've got an SSLIOP credential.
00799           SecurityLevel3::Credentials_ptr credentials =
00800             creds_list[0u];
00801 
00802           ssliop_credentials =
00803             TAO::SSLIOP::OwnCredentials::_narrow (credentials);
00804 
00805           if (!CORBA::is_nil (ssliop_credentials.in ()))
00806             {
00807               TAO::SSLIOP::X509_var x509 = ssliop_credentials->x509 ();
00808               if (::SSL_use_certificate (ssl, x509.in ()) != 1)
00809                 return TAO::SSLIOP::OwnCredentials::_nil ();
00810 
00811               TAO::SSLIOP::EVP_PKEY_var evp = ssliop_credentials->evp ();
00812               if (evp.in () != 0
00813                   && ::SSL_use_PrivateKey (ssl, evp.in ()) != 1)
00814                 {
00815                   // Invalidate the certificate we just set.
00816                   (void) ::SSL_use_certificate (ssl, 0);
00817                   return TAO::SSLIOP::OwnCredentials::_nil ();
00818                 }
00819             }
00820         }
00821     }
00822   else
00823     {
00824       // Use the default certificate and private key, i.e. the one set
00825       // in the SSL_CTX that was used when creating the SSL data
00826       // structure.
00827 
00828       /**
00829        * @todo Check if the CredentialsCurator contains a default set
00830        *       of SSLIOP OwnCredentials.
00831        */
00832 
00833       TAO::SSLIOP::OwnCredentials_ptr & c = ssliop_credentials.out ();
00834       ACE_NEW_THROW_EX (c,
00835                         TAO::SSLIOP::OwnCredentials (
00836                           ::SSL_get_certificate (ssl),
00837                           ::SSL_get_privatekey (ssl)),
00838                         CORBA::NO_MEMORY ());
00839     }
00840 
00841   return ssliop_credentials._retn ();
00842 }

TAO_Transport * TAO::SSLIOP::Connector::ssliop_connect ( TAO_SSLIOP_Endpoint ssliop_endpoint,
::Security::QOP  qop,
const ::Security::EstablishTrust trust,
TAO::Profile_Transport_Resolver *  r,
TAO_Transport_Descriptor_Interface desc,
ACE_Time_Value timeout 
) [protected]

SSLIOP-specific connection establishment.

Definition at line 386 of file SSLIOP_Connector.cpp.

References CORBA::SystemException::_tao_minor_code(), ACE_BIT_DISABLED, ACE_BIT_ENABLED, ACE_DEBUG, ACE_ERROR, ACE_TEXT(), TAO_SSLIOP_Endpoint::addr_to_string(), AF_INET, base_connector_, TAO_Connection_Handler::cancel_pending_connection(), TAO::SSLIOP::Connection_Handler::close(), TAO_Transport::close_connection(), CORBA::COMPLETED_NO, ACE_Connector< SVC_HANDLER, >::connect(), TAO_Connection_Handler::connection_pending(), TAO_SSLIOP_Endpoint::credentials_set(), TAO_LF_CH_Event::error_detected(), ACE_INET_Addr::get_port_number(), ACE_Addr::get_type(), TAO_Transport::id(), TAO_Pseudo_Var_T< T >::in(), TAO_Transport::is_connected(), TAO_LF_Event::keep_waiting(), LM_DEBUG, LM_ERROR, MAXHOSTNAMELEN, Security::NoProtection, TAO_SSLIOP_Endpoint::object_addr(), ACE_Svc_Handler<, >::peer(), TAO_Transport::purge_entry(), TAO_Wait_Strategy::register_handler(), ACE_Event_Handler_var::release(), ACE_Event_Handler::remove_reference(), retrieve_credentials(), Security::SecQOPIntegrity, Security::SecQOPNoProtection, TAO_SSLIOP_Endpoint::set_sec_attrs(), TAO_SSLIOP_Endpoint::ssl_component(), TAO_debug_level, TAO_Connection_Handler::transport(), TAO::VMCID, and TAO_Transport::wait_strategy().

Referenced by connect().

00393 {
00394   const ::SSLIOP::SSL &ssl_component = ssl_endpoint->ssl_component ();
00395 
00396   // @@ The following check for "required insecurity" seems odd, but
00397   //    I haven't seen anything in the Security spec that says this
00398   //    policy isn't possible.
00399   //      -Ossama
00400 
00401   // If the endpoint requires an insecure connection, i.e. the
00402   // Security::NoProtection security association bit in the
00403   // SSLIOP::SSL::target_requires field is enabled, then prevent an
00404   // SSL connection from occuring.
00405   if (ACE_BIT_ENABLED (ssl_component.target_requires,
00406                        ::Security::NoProtection))
00407     throw CORBA::NO_PERMISSION (
00408       CORBA::SystemException::_tao_minor_code (
00409         TAO::VMCID,
00410         EPERM),
00411       CORBA::COMPLETED_NO);
00412 
00413   // If the invocation wants integrity without confidentiality but the
00414   // server does not support "no protection," then it won't be
00415   // possible to provide integrity.  In order to support integrity
00416   // without confidentiality, encryption must be disabled but secure
00417   // hashes must remain enabled.  This is achieved using the "eNULL"
00418   // cipher.  However, the "eNULL" cipher is only enabled on the
00419   // server side if "no protection" is enabled.
00420   if (ACE_BIT_DISABLED (ssl_component.target_supports,
00421                         ::Security::NoProtection)
00422       && qop == ::Security::SecQOPIntegrity)
00423     throw CORBA::INV_POLICY ();
00424 
00425   const ACE_INET_Addr &remote_address = ssl_endpoint->object_addr ();
00426 
00427   // Verify that the remote ACE_INET_Addr was initialized
00428   // properly.  Failure can occur if hostname lookup failed when
00429   // initializing the remote ACE_INET_Addr.
00430   if (remote_address.get_type () != AF_INET
00431 #if defined (ACE_HAS_IPV6)
00432       && remote_address.get_type () != AF_INET6
00433 #endif /* ACE_HAS_IPV6 */
00434       )
00435     {
00436       if (TAO_debug_level > 0)
00437         {
00438           ACE_DEBUG ((LM_DEBUG,
00439                       ACE_TEXT ("TAO (%P|%t) SSLIOP connection failed.\n")
00440                       ACE_TEXT ("TAO (%P|%t) This is most likely ")
00441                       ACE_TEXT ("due to a hostname lookup ")
00442                       ACE_TEXT ("failure.\n")));
00443         }
00444 
00445       return 0;
00446     }
00447 
00448   int result = 0;
00449   TAO::SSLIOP::Connection_Handler *svc_handler = 0;
00450   TAO_Transport *transport = 0;
00451 
00452   // Before we can check the cache to find an existing connection, we
00453   // need to make sure the ssl_endpoint is fully initialized with the
00454   // local security information. This endpoint initalized by the
00455   // profile does not (and cannot) contain the desired QOP, trust, or
00456   // credential information which is necesary to uniquely identify
00457   // this connection.
00458   if (!ssl_endpoint->credentials_set ())
00459     {
00460       if (TAO_debug_level > 2)
00461         ACE_DEBUG ((LM_DEBUG,
00462                     ACE_TEXT ("TAO (%P|%t) Initializing SSLIOP_Endpoint \n")
00463                     ));
00464 
00465       if (this->base_connector_.creation_strategy ()->make_svc_handler (
00466                svc_handler) != 0)
00467         {
00468           if (TAO_debug_level > 0)
00469             ACE_DEBUG ((LM_ERROR,
00470                         ACE_TEXT ("TAO (%P|%t) Unable to create SSLIOP ")
00471                         ACE_TEXT ("service handler.\n")));
00472 
00473           return 0;
00474         }
00475 
00476       ACE_Event_Handler_var
00477         safe_handler (svc_handler);
00478       TAO::SSLIOP::OwnCredentials_var credentials =
00479         this->retrieve_credentials (resolver->stub (),
00480                                     svc_handler->peer ().ssl ());
00481 
00482       safe_handler.release ();
00483 
00484       ssl_endpoint->set_sec_attrs (qop, trust, credentials.in());
00485     }
00486 
00487   // Check the Cache first for connections
00488   if (this->orb_core ()->lane_resources ().transport_cache ().find_transport (
00489         desc,
00490         transport) == 0)
00491     {
00492       // ...eliminate svc_handle memory leak...
00493       // The make_svc_handler() method creates the service handler and
00494       // bumps the #REFCOUNT# up one extra.  The extra reference count
00495       // in TAO_Connect_Creation_Strategy::make_svc_handler() is
00496       // needed in the case when connection completion is pending and
00497       // we are going to wait on a variable in the handler to changes,
00498       // signifying success or failure.  Note, that this increment
00499       // cannot be done once the connect() returns since this might be
00500       // too late if another thread pick up the completion and
00501       // potentially deletes the handler before we get a chance to
00502       // increment the reference count.
00503       if (svc_handler)
00504           svc_handler->remove_reference();
00505 
00506       ACE_Event_Handler_var
00507         safe_handler (svc_handler);
00508 
00509       if (TAO_debug_level > 2)
00510         ACE_DEBUG ((LM_DEBUG,
00511                     ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, ")
00512                     ACE_TEXT ("got existing transport[%d]\n"),
00513                     transport->id ()));
00514 
00515       // When the transport is not connected wait for completion
00516       if (!transport->is_connected())
00517         {
00518           if (!this->wait_for_connection_completion (resolver,
00519                                                      transport,
00520                                                      max_wait_time))
00521             {
00522               ACE_ERROR ((LM_ERROR,
00523                           ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect,")
00524                           ACE_TEXT ("wait for completion failed\n")));
00525 
00526             }
00527         }
00528     }
00529   else
00530     {
00531       if (TAO_debug_level > 4)
00532         ACE_DEBUG ((LM_DEBUG,
00533                     ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, ")
00534                     ACE_TEXT ("making a new connection \n")));
00535 
00536       // Purge connections (if necessary)
00537       this->orb_core ()->lane_resources ().transport_cache ().purge ();
00538 
00539       // The svc_handler is created beforehand so that we can get
00540       // access to the underlying ACE_SSL_SOCK_Stream (the peer) and
00541       // its SSL pointer member prior to descending into the
00542       // ACE_Strategy_Connector (the "base_connector_").  This is
00543       // thread-safe and reentrant, hence no synchronization is
00544       // necessary.
00545       //
00546       // The make_svc_handler() method creates the service handler and
00547       // bumps the #REFCOUNT# up one extra.  The extra reference count
00548       // in TAO_Connect_Creation_Strategy::make_svc_handler() is
00549       // needed in the case when connection completion is pending and
00550       // we are going to wait on a variable in the handler to changes,
00551       // signifying success or failure.  Note, that this increment
00552       // cannot be done once the connect() returns since this might be
00553       // too late if another thread pick up the completion and
00554       // potentially deletes the handler before we get a chance to
00555       // increment the reference count.
00556       if (svc_handler == 0 &&
00557           this->base_connector_.creation_strategy ()->make_svc_handler (
00558                svc_handler) != 0)
00559         {
00560           if (TAO_debug_level > 0)
00561             ACE_DEBUG ((LM_ERROR,
00562                         ACE_TEXT ("TAO (%P|%t) Unable to create SSLIOP ")
00563                         ACE_TEXT ("service handler.\n")));
00564 
00565           return 0;
00566         }
00567 
00568       ACE_Event_Handler_var
00569         safe_handler (svc_handler);
00570 
00571       // Setup the establishment of trust connection properties, if
00572       // any.
00573       int verify_mode = 0;
00574 
00575       // On the server side, "trust_in_client" requires that a peer
00576       // (client) certificate exist.  Fail if one doesn't exist.
00577       //
00578       // In SSLIOP's case, trust_in_client also implies
00579       // trust_in_target.
00580       if (trust.trust_in_client)
00581         verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00582 
00583       // Require verification of the target's certificate.
00584       else if (trust.trust_in_target)
00585         verify_mode = SSL_VERIFY_PEER;
00586 
00587       // Trust in neither the client nor the target is explicitly
00588       // specified.  Use the default setting.
00589       else
00590         verify_mode = ACE_SSL_Context::instance ()->default_verify_mode ();
00591 
00592       ::SSL_set_verify (svc_handler->peer ().ssl (), verify_mode, 0);
00593 
00594       // The "eNULL" cipher disables encryption but still uses a
00595       // secure hash (e.g. SHA1 or MD5) to ensure integrity.  (Try the
00596       // command "openssl ciphers -v eNULL".)
00597       //
00598       // Note that it is not possible to completely disable protection
00599       // here.
00600       if ((qop == ::Security::SecQOPNoProtection
00601           || qop == ::Security::SecQOPIntegrity)
00602           && ::SSL_set_cipher_list (svc_handler->peer ().ssl (),
00603                                     "eNULL") == 0)
00604         {
00605           if (TAO_debug_level > 0)
00606             ACE_DEBUG ((LM_ERROR,
00607                         ACE_TEXT ("(%P|%t) Unable to set eNULL ")
00608                         ACE_TEXT ("SSL cipher.\n")));
00609 
00610           throw CORBA::INV_POLICY ();
00611         }
00612 
00613       // svc_handler is never reset..it still has the value
00614       (void)safe_handler.release ();
00615 
00616       // Get the right synch options
00617       ACE_Synch_Options synch_options;
00618 
00619       this->active_connect_strategy_->synch_options (max_wait_time,
00620                                                      synch_options);
00621 
00622       // The code used to set the timeout to zero, with the intent of
00623       // polling the reactor for connection completion. However, the side-effect
00624       // was to cause the connection to timeout immediately.
00625 
00626       // We obtain the transport in the <svc_handler> variable.  As we
00627       // know now that the connection is not available in Cache we can
00628       // make a new connection
00629       result = this->base_connector_.connect (svc_handler,
00630                                               remote_address,
00631                                               synch_options);
00632 
00633       // base_connector_.connect() will increment the handler's
00634       // #REFCOUNT# once more. This is not required as we already hold
00635       // a reference to the handler, so we discard this second
00636       // reference.
00637       svc_handler->remove_reference ();
00638 
00639       // There are three possibilities from calling connect(): (a)
00640       // connection succeeds immediately - in this case, the
00641       // #REFCOUNT# on the handler is two; (b) connection completion
00642       // is pending - in this case, the #REFCOUNT# on the handler is
00643       // also two; (c) connection fails immediately - in this case,
00644       // the #REFCOUNT# on the handler is one since close() gets
00645       // called on the handler.
00646 
00647       // Make sure that we always do a remove_reference
00648       ACE_Event_Handler_var svc_handler_auto_ptr (svc_handler);
00649 
00650       transport =
00651         svc_handler->transport ();
00652 
00653       if (result == -1)
00654         {
00655           // No immediate result, wait for completion
00656           if (errno == EWOULDBLOCK)
00657             {
00658               // Try to wait until connection completion. Incase we block, then we
00659               // get a connected transport or not. In case of non block we get
00660               // a connected or not connected transport
00661               if (!this->wait_for_connection_completion (resolver,
00662                                                          transport,
00663                                                          max_wait_time))
00664                 {
00665                   if (TAO_debug_level > 2)
00666                     ACE_ERROR ((LM_ERROR, "TAO (%P|%t) - SSLIOP_Connector::"
00667                                           "ssliop_connect, "
00668                                           "wait for completion failed\n"));
00669                 }
00670             }
00671           else
00672             {
00673               // Transport is not usable
00674               transport = 0;
00675             }
00676         }
00677 
00678       // In case of errors transport is zero
00679       if (transport == 0)
00680         {
00681           // Give users a clue to the problem.
00682           if (TAO_debug_level)
00683             {
00684               char buffer [MAXHOSTNAMELEN + 6 + 1];
00685               ssl_endpoint->addr_to_string (buffer,
00686                                             sizeof (buffer) - 1);
00687               ACE_DEBUG ((LM_ERROR,
00688                           ACE_TEXT ("TAO (%P|%t) - SSL connection to ")
00689                           ACE_TEXT ("<%s:%d> failed (%p)\n"),
00690                           buffer,
00691                           remote_address.get_port_number (),
00692                           ACE_TEXT ("errno")));
00693             }
00694 
00695           return 0;
00696         }
00697 
00698       // fix for bug 2654
00699       if (svc_handler->keep_waiting ())
00700         {
00701           svc_handler->connection_pending ();
00702         }
00703 
00704       // fix for bug 2654
00705       if (svc_handler->error_detected ())
00706         {
00707           svc_handler->cancel_pending_connection ();
00708         }
00709 
00710       // At this point, the connection has be successfully connected.
00711       // #REFCOUNT# is one.
00712       if (TAO_debug_level > 2)
00713         ACE_DEBUG ((LM_DEBUG,
00714                     "TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, "
00715                     "new SSL connection to port %d on transport[%d]\n",
00716                     remote_address.get_port_number (),
00717                     svc_handler->peer ().get_handle ()));
00718 
00719       // Add the handler to Cache
00720       int retval =
00721         this->orb_core ()->
00722           lane_resources ().transport_cache ().cache_transport (desc,
00723                                                                 transport);
00724 
00725       // Failure in adding to cache.
00726       if (retval != 0)
00727         {
00728           // Close the handler.
00729           svc_handler->close ();
00730 
00731           if (TAO_debug_level > 0)
00732             {
00733               ACE_ERROR ((LM_ERROR,
00734                           "TAO (%P|%t) - SLIIOP_Connector::ssliop_connect, "
00735                           "could not add the new connection to cache\n"));
00736             }
00737 
00738           return 0;
00739         }
00740 
00741       // fix for bug 2654
00742       if (svc_handler->error_detected ())
00743         {
00744           svc_handler->cancel_pending_connection ();
00745           transport->purge_entry();
00746           return 0;
00747         }
00748 
00749       if (transport->is_connected () &&
00750           transport->wait_strategy ()->register_handler () != 0)
00751         {
00752           // Registration failures.
00753 
00754           // Purge from the connection cache, if we are not in the cache, this
00755           // just does nothing.
00756           (void) transport->purge_entry ();
00757 
00758           // Close the handler.
00759           (void) transport->close_connection ();
00760 
00761           if (TAO_debug_level > 0)
00762             ACE_ERROR ((LM_ERROR,
00763                         "TAO (%P|%t) - SSLIOP_Connector [%d]::ssliop_connect, "
00764                         "could not register the transport "
00765                         "in the reactor.\n",
00766                         transport->id ()));
00767 
00768           return 0;
00769         }
00770     }
00771 
00772   return transport;
00773 }


Member Data Documentation

BASE_CONNECTOR TAO::SSLIOP::Connector::base_connector_ [private]

The connector initiating connection requests for IIOP.

Definition at line 144 of file SSLIOP_Connector.h.

Referenced by cancel_svc_handler(), close(), open(), and ssliop_connect().

CONNECT_STRATEGY TAO::SSLIOP::Connector::connect_strategy_ [private]

Our connect strategy.

Definition at line 141 of file SSLIOP_Connector.h.

::Security::QOP TAO::SSLIOP::Connector::qop_ [private]

If zero, connect to IIOP over SSL port by default. Otherwise, connect to the insecure IIOP port.

Definition at line 138 of file SSLIOP_Connector.h.

Referenced by connect().


The documentation for this class was generated from the following files:
Generated on Tue Feb 2 17:48:58 2010 for TAO_SSLIOP by  doxygen 1.4.7