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/Base_Transport_Property.h"
00012 #include "tao/Transport_Cache_Manager.h"
00013 #include "tao/Thread_Lane_Resources.h"
00014 #include "tao/Stub.h"
00015 #include "tao/Transport_Connector.h"
00016 #include "tao/Blocked_Connect_Strategy.h"
00017 #include "tao/Wait_Strategy.h"
00018 #include "tao/Profile_Transport_Resolver.h"
00019 #include "ace/Auto_Ptr.h"
00020 #include "ace/os_include/os_netdb.h"
00021 
00022 ACE_RCSID (SSLIOP,
00023            SSLIOP_Connector,
00024            "$Id: SSLIOP_Connector.cpp 79388 2007-08-17 16:05:00Z wilsond $")
00025 
00026 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00027 
00028 TAO::SSLIOP::Connector::Connector (::Security::QOP qop)
00029   : TAO::IIOP_SSL_Connector (),
00030     qop_ (qop),
00031     connect_strategy_ (),
00032     base_connector_ ()
00033 {
00034 }
00035 
00036 int
00037 TAO::SSLIOP::Connector::open (TAO_ORB_Core *orb_core)
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 }
00073 
00074 int
00075 TAO::SSLIOP::Connector::close (void)
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 }
00083 
00084 TAO_Transport *
00085 TAO::SSLIOP::Connector::connect (TAO::Profile_Transport_Resolver *resolver,
00086                                  TAO_Transport_Descriptor_Interface *desc,
00087                                  ACE_Time_Value *timeout)
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 }
00199 
00200 
00201 TAO_Profile *
00202 TAO::SSLIOP::Connector::create_profile (TAO_InputCDR& cdr)
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 }
00217 
00218 TAO_Profile *
00219 TAO::SSLIOP::Connector::make_profile (void)
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 }
00238 
00239 
00240 TAO_Profile *
00241 TAO::SSLIOP::Connector::make_secure_profile (void)
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 }
00260 
00261 
00262 
00263 TAO_Profile *
00264 TAO::SSLIOP::Connector::corbaloc_scan (const char *endpoint, size_t &len)
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 }
00314 
00315 
00316 int
00317 TAO::SSLIOP::Connector::check_prefix (const char *endpoint)
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 }
00341 
00342 
00343 TAO_Transport*
00344 TAO::SSLIOP::Connector::iiop_connect (
00345   TAO_SSLIOP_Endpoint *ssl_endpoint,
00346   TAO::Profile_Transport_Resolver *resolver,
00347   ACE_Time_Value *timeout)
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 }
00384 
00385 TAO_Transport *
00386 TAO::SSLIOP::Connector::ssliop_connect (
00387   TAO_SSLIOP_Endpoint *ssl_endpoint,
00388   ::Security::QOP qop,
00389   const ::Security::EstablishTrust &trust,
00390   TAO::Profile_Transport_Resolver *resolver,
00391   TAO_Transport_Descriptor_Interface *desc,
00392   ACE_Time_Value *max_wait_time)
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_ERROR,
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_Auto_Basic_Ptr<TAO::SSLIOP::Connection_Handler>
00477         safe_handler (svc_handler);
00478       TAO::SSLIOP::OwnCredentials_var credentials =
00479         this->retrieve_credentials (resolver->stub (),
00480                                     svc_handler->peer ().ssl ());
00481 
00482       svc_handler = safe_handler.release ();
00483       ssl_endpoint->set_sec_attrs (qop, trust, credentials.in());
00484     }
00485 
00486   // Check the Cache first for connections
00487   if (this->orb_core ()->lane_resources ().transport_cache ().find_transport (
00488         desc,
00489         transport) == 0)
00490     {
00491       if (TAO_debug_level > 2)
00492         ACE_DEBUG ((LM_DEBUG,
00493                     ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, ")
00494                     ACE_TEXT ("got existing transport[%d]\n"),
00495                     transport->id ()));
00496 
00497       // When the transport is not connected wait for completion
00498       if (!transport->is_connected())
00499         {
00500           if (!this->wait_for_connection_completion (resolver,
00501                                                      transport,
00502                                                      max_wait_time))
00503             {
00504               ACE_ERROR ((LM_ERROR,
00505                           ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect,")
00506                           ACE_TEXT ("wait for completion failed\n")));
00507 
00508             }
00509         }
00510     }
00511   else
00512     {
00513       if (TAO_debug_level > 4)
00514         ACE_DEBUG ((LM_DEBUG,
00515                     ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, ")
00516                     ACE_TEXT ("making a new connection \n")));
00517 
00518       // Purge connections (if necessary)
00519       this->orb_core ()->lane_resources ().transport_cache ().purge ();
00520 
00521       // The svc_handler is created beforehand so that we can get
00522       // access to the underlying ACE_SSL_SOCK_Stream (the peer) and
00523       // its SSL pointer member prior to descending into the
00524       // ACE_Strategy_Connector (the "base_connector_").  This is
00525       // thread-safe and reentrant, hence no synchronization is
00526       // necessary.
00527       //
00528       // The make_svc_handler() method creates the service handler and
00529       // bumps the #REFCOUNT# up one extra.  The extra reference count
00530       // in TAO_Connect_Creation_Strategy::make_svc_handler() is
00531       // needed in the case when connection completion is pending and
00532       // we are going to wait on a variable in the handler to changes,
00533       // signifying success or failure.  Note, that this increment
00534       // cannot be done once the connect() returns since this might be
00535       // too late if another thread pick up the completion and
00536       // potentially deletes the handler before we get a chance to
00537       // increment the reference count.
00538       if (svc_handler == 0 &&
00539           this->base_connector_.creation_strategy ()->make_svc_handler (
00540                svc_handler) != 0)
00541         {
00542           if (TAO_debug_level > 0)
00543             ACE_DEBUG ((LM_ERROR,
00544                         ACE_TEXT ("TAO (%P|%t) Unable to create SSLIOP ")
00545                         ACE_TEXT ("service handler.\n")));
00546 
00547           return 0;
00548         }
00549 
00550       ACE_Auto_Basic_Ptr<TAO::SSLIOP::Connection_Handler>
00551         safe_handler (svc_handler);
00552 
00553       // Setup the establishment of trust connection properties, if
00554       // any.
00555       int verify_mode = 0;
00556 
00557       // On the server side, "trust_in_client" requires that a peer
00558       // (client) certificate exist.  Fail if one doesn't exist.
00559       //
00560       // In SSLIOP's case, trust_in_client also implies
00561       // trust_in_target.
00562       if (trust.trust_in_client)
00563         verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00564 
00565       // Require verification of the target's certificate.
00566       else if (trust.trust_in_target)
00567         verify_mode = SSL_VERIFY_PEER;
00568 
00569       // Trust in neither the client nor the target is explicitly
00570       // specified.  Use the default setting.
00571       else
00572         verify_mode = ACE_SSL_Context::instance ()->default_verify_mode ();
00573 
00574       ::SSL_set_verify (svc_handler->peer ().ssl (),
00575                         verify_mode,
00576                         0);
00577 
00578       // The "eNULL" cipher disables encryption but still uses a
00579       // secure hash (e.g. SHA1 or MD5) to ensure integrity.  (Try the
00580       // command "openssl ciphers -v eNULL".)
00581       //
00582       // Note that it is not possible to completely disable protection
00583       // here.
00584       if ((qop == ::Security::SecQOPNoProtection
00585           || qop == ::Security::SecQOPIntegrity)
00586           && ::SSL_set_cipher_list (svc_handler->peer ().ssl (),
00587                                     "eNULL") == 0)
00588         {
00589           if (TAO_debug_level > 0)
00590             ACE_DEBUG ((LM_ERROR,
00591                         ACE_TEXT ("(%P|%t) Unable to set eNULL ")
00592                         ACE_TEXT ("SSL cipher.\n")));
00593 
00594           throw CORBA::INV_POLICY ();
00595         }
00596 
00597       svc_handler = safe_handler.release ();
00598 
00599       // Get the right synch options
00600       ACE_Synch_Options synch_options;
00601 
00602       this->active_connect_strategy_->synch_options (max_wait_time,
00603                                                      synch_options);
00604 
00605       // The code used to set the timeout to zero, with the intent of
00606       // polling the reactor for connection completion. However, the side-effect
00607       // was to cause the connection to timeout immediately.
00608 
00609       // We obtain the transport in the <svc_handler> variable.  As we
00610       // know now that the connection is not available in Cache we can
00611       // make a new connection
00612       result = this->base_connector_.connect (svc_handler,
00613                                               remote_address,
00614                                               synch_options);
00615 
00616       // base_connector_.connect() will increment the handler's
00617       // #REFCOUNT# once more. This is not required as we already hold
00618       // a reference to the handler, so we discard this second
00619       // reference.
00620       svc_handler->remove_reference ();
00621 
00622       // There are three possibilities from calling connect(): (a)
00623       // connection succeeds immediately - in this case, the
00624       // #REFCOUNT# on the handler is two; (b) connection completion
00625       // is pending - in this case, the #REFCOUNT# on the handler is
00626       // also two; (c) connection fails immediately - in this case,
00627       // the #REFCOUNT# on the handler is one since close() gets
00628       // called on the handler.
00629 
00630       // Make sure that we always do a remove_reference
00631       ACE_Event_Handler_var svc_handler_auto_ptr (svc_handler);
00632 
00633       transport =
00634         svc_handler->transport ();
00635 
00636       if (result == -1)
00637         {
00638           // No immediate result, wait for completion
00639           if (errno == EWOULDBLOCK)
00640             {
00641               // Try to wait until connection completion. Incase we block, then we
00642               // get a connected transport or not. In case of non block we get
00643               // a connected or not connected transport
00644               if (!this->wait_for_connection_completion (resolver,
00645                                                          transport,
00646                                                          max_wait_time))
00647                 {
00648                   if (TAO_debug_level > 2)
00649                     ACE_ERROR ((LM_ERROR, "TAO (%P|%t) - SSLIOP_Connector::"
00650                                           "ssliop_connect, "
00651                                           "wait for completion failed\n"));
00652                 }
00653             }
00654           else
00655             {
00656               // Transport is not usable
00657               transport = 0;
00658             }
00659         }
00660 
00661       // In case of errors transport is zero
00662       if (transport == 0)
00663         {
00664           // Give users a clue to the problem.
00665           if (TAO_debug_level)
00666             {
00667               char buffer [MAXHOSTNAMELEN + 6 + 1];
00668               ssl_endpoint->addr_to_string (buffer,
00669                                             sizeof (buffer) - 1);
00670               ACE_DEBUG ((LM_ERROR,
00671                           ACE_TEXT ("TAO (%P|%t) - SSL connection to ")
00672                           ACE_TEXT ("<%s:%d> failed (%p)\n"),
00673                           buffer,
00674                           remote_address.get_port_number (),
00675                           ACE_TEXT ("errno")));
00676             }
00677 
00678           return 0;
00679         }
00680 
00681       // fix for bug 2654
00682       if (svc_handler->keep_waiting ())
00683         {
00684           svc_handler->connection_pending ();
00685         }
00686 
00687       // fix for bug 2654
00688       if (svc_handler->error_detected ())
00689         {
00690           svc_handler->cancel_pending_connection ();
00691         }
00692 
00693       // At this point, the connection has be successfully connected.
00694       // #REFCOUNT# is one.
00695       if (TAO_debug_level > 2)
00696         ACE_DEBUG ((LM_DEBUG,
00697                     "TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, "
00698                     "new SSL connection to port %d on transport[%d]\n",
00699                     remote_address.get_port_number (),
00700                     svc_handler->peer ().get_handle ()));
00701 
00702       // Add the handler to Cache
00703       int retval =
00704         this->orb_core ()->
00705           lane_resources ().transport_cache ().cache_transport (desc,
00706                                                                 transport);
00707 
00708       // Failure in adding to cache.
00709       if (retval != 0)
00710         {
00711           // Close the handler.
00712           svc_handler->close ();
00713 
00714           if (TAO_debug_level > 0)
00715             {
00716               ACE_ERROR ((LM_ERROR,
00717                           "TAO (%P|%t) - SLIIOP_Connector::ssliop_connect, "
00718                           "could not add the new connection to cache\n"));
00719             }
00720 
00721           return 0;
00722         }
00723 
00724       // fix for bug 2654
00725       if (svc_handler->error_detected ())
00726         {
00727           svc_handler->cancel_pending_connection ();
00728           transport->purge_entry();
00729           return 0;
00730         }
00731 
00732       if (transport->is_connected () &&
00733           transport->wait_strategy ()->register_handler () != 0)
00734         {
00735           // Registration failures.
00736 
00737           // Purge from the connection cache, if we are not in the cache, this
00738           // just does nothing.
00739           (void) transport->purge_entry ();
00740 
00741           // Close the handler.
00742           (void) transport->close_connection ();
00743 
00744           if (TAO_debug_level > 0)
00745             ACE_ERROR ((LM_ERROR,
00746                         "TAO (%P|%t) - SSLIOP_Connector [%d]::ssliop_connect, "
00747                         "could not register the transport "
00748                         "in the reactor.\n",
00749                         transport->id ()));
00750 
00751           return 0;
00752         }
00753     }
00754 
00755   return transport;
00756 }
00757 
00758 TAO::SSLIOP::OwnCredentials *
00759 TAO::SSLIOP::Connector::retrieve_credentials (TAO_Stub *stub,
00760                                               SSL *ssl)
00761 {
00762   // Check if the user overrode the default invocation credentials.
00763   CORBA::Policy_var policy =
00764     stub->get_policy (::SecurityLevel3::ContextEstablishmentPolicyType);
00765 
00766   SecurityLevel3::ContextEstablishmentPolicy_var creds_policy =
00767     SecurityLevel3::ContextEstablishmentPolicy::_narrow (
00768       policy.in ());
00769 
00770   TAO::SSLIOP::OwnCredentials_var ssliop_credentials;
00771 
00772   // Set the Credentials (X.509 certificates and corresponding private
00773   // keys) to be used for this invocation.
00774   if (!CORBA::is_nil (creds_policy.in ()))
00775     {
00776       SecurityLevel3::OwnCredentialsList_var creds_list =
00777         creds_policy->creds_list ();
00778 
00779       if (creds_list->length () > 0)
00780         {
00781           // Assume that we've got an SSLIOP credential.
00782           SecurityLevel3::Credentials_ptr credentials =
00783             creds_list[0u];
00784 
00785           ssliop_credentials =
00786             TAO::SSLIOP::OwnCredentials::_narrow (credentials);
00787 
00788           if (!CORBA::is_nil (ssliop_credentials.in ()))
00789             {
00790               TAO::SSLIOP::X509_var x509 = ssliop_credentials->x509 ();
00791               if (::SSL_use_certificate (ssl, x509.in ()) != 1)
00792                 return TAO::SSLIOP::OwnCredentials::_nil ();
00793 
00794               TAO::SSLIOP::EVP_PKEY_var evp = ssliop_credentials->evp ();
00795               if (evp.in () != 0
00796                   && ::SSL_use_PrivateKey (ssl, evp.in ()) != 1)
00797                 {
00798                   // Invalidate the certificate we just set.
00799                   (void) ::SSL_use_certificate (ssl, 0);
00800                   return TAO::SSLIOP::OwnCredentials::_nil ();
00801                 }
00802             }
00803         }
00804     }
00805   else
00806     {
00807       // Use the default certificate and private key, i.e. the one set
00808       // in the SSL_CTX that was used when creating the SSL data
00809       // structure.
00810 
00811       /**
00812        * @todo Check if the CredentialsCurator contains a default set
00813        *       of SSLIOP OwnCredentials.
00814        */
00815 
00816       TAO::SSLIOP::OwnCredentials_ptr & c = ssliop_credentials.out ();
00817       ACE_NEW_THROW_EX (c,
00818                         TAO::SSLIOP::OwnCredentials (
00819                           ::SSL_get_certificate (ssl),
00820                           ::SSL_get_privatekey (ssl)),
00821                         CORBA::NO_MEMORY ());
00822     }
00823 
00824   return ssliop_credentials._retn ();
00825 }
00826 
00827 int
00828 TAO::SSLIOP::Connector::cancel_svc_handler (
00829   TAO_Connection_Handler * svc_handler)
00830 {
00831   TAO::SSLIOP::Connection_Handler* handler=
00832     dynamic_cast<TAO::SSLIOP::Connection_Handler*> (svc_handler);
00833 
00834   if (handler)
00835     // Cancel from the connector
00836     return this->base_connector_.cancel (handler);
00837 
00838   return -1;
00839 }
00840 
00841 TAO_END_VERSIONED_NAMESPACE_DECL

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