summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp
diff options
context:
space:
mode:
authorWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:21 +0000
committerWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:21 +0000
commit3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (patch)
tree197c810e5f5bce17b1233a7cb8d7b50c0bcd25e2 /TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp
parent6b846cf03c0bcbd8c276cb0af61a181e5f98eaae (diff)
downloadATCD-3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c.tar.gz
Repo restructuring
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp')
-rw-r--r--TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp862
1 files changed, 862 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp
new file mode 100644
index 00000000000..3635555cb98
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp
@@ -0,0 +1,862 @@
+#include "orbsvcs/SSLIOP/SSLIOP_Connector.h"
+#include "orbsvcs/SSLIOP/SSLIOP_OwnCredentials.h"
+#include "orbsvcs/SSLIOP/SSLIOP_Profile.h"
+#include "orbsvcs/SSLIOP/SSLIOP_X509.h"
+
+#include "orbsvcs/SecurityLevel2C.h"
+
+#include "tao/debug.h"
+#include "tao/ORB_Core.h"
+#include "tao/Client_Strategy_Factory.h"
+#include "tao/Environment.h"
+#include "tao/Base_Transport_Property.h"
+#include "tao/Transport_Cache_Manager.h"
+#include "tao/Thread_Lane_Resources.h"
+#include "tao/Stub.h"
+#include "tao/Transport_Connector.h"
+#include "tao/Blocked_Connect_Strategy.h"
+#include "tao/Wait_Strategy.h"
+#include "tao/Profile_Transport_Resolver.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/os_include/os_netdb.h"
+
+ACE_RCSID (SSLIOP,
+ SSLIOP_Connector,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO::SSLIOP::Connector::Connector (::Security::QOP qop)
+ : TAO::IIOP_SSL_Connector (),
+ qop_ (qop),
+ connect_strategy_ (),
+ base_connector_ ()
+{
+}
+
+int
+TAO::SSLIOP::Connector::open (TAO_ORB_Core *orb_core)
+{
+ // Since the ACE_Strategy_Connector (and ACE_Connector) cannot
+ // handle non-blocking connections with protocols that have more
+ // than one handshake, such as SSL, force blocking connections for
+ // SSLIOP. This deficiency will be addressed soon.
+ ACE_NEW_RETURN (this->active_connect_strategy_,
+ TAO_Blocked_Connect_Strategy (orb_core),
+ -1);
+
+ if (this->TAO::IIOP_SSL_Connector::open (orb_core) == -1)
+ return -1;
+
+ // Our connect creation strategy
+ CONNECT_CREATION_STRATEGY *connect_creation_strategy = 0;
+
+ ACE_NEW_RETURN (connect_creation_strategy,
+ CONNECT_CREATION_STRATEGY
+ (orb_core->thr_mgr (),
+ orb_core,
+ 0 /* Forcibly disable TAO's GIOPlite feature.
+ It introduces a security hole. */),
+ -1);
+
+ // Our activation strategy
+ CONNECT_CONCURRENCY_STRATEGY *concurrency_strategy = 0;
+
+ ACE_NEW_RETURN (concurrency_strategy,
+ CONNECT_CONCURRENCY_STRATEGY (orb_core),
+ -1);
+
+ ACE_Reactor *r = this->orb_core ()->reactor ();
+
+ return this->base_connector_.open (r,
+ connect_creation_strategy,
+ &this->connect_strategy_,
+ concurrency_strategy);
+}
+
+int
+TAO::SSLIOP::Connector::close (void)
+{
+ (void) this->TAO::IIOP_SSL_Connector::close ();
+
+ delete this->base_connector_.creation_strategy ();
+ delete this->base_connector_.concurrency_strategy ();
+ return this->base_connector_.close ();
+}
+
+TAO_Transport *
+TAO::SSLIOP::Connector::connect (TAO::Profile_Transport_Resolver *resolver,
+ TAO_Transport_Descriptor_Interface *desc,
+ ACE_Time_Value *timeout
+ ACE_ENV_ARG_DECL)
+{
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) - Connector::connect, ")
+ ACE_TEXT ("looking for SSLIOP connection.\n")));
+
+ TAO_Endpoint *endpoint = desc->endpoint ();
+
+ if (endpoint->tag () != IOP::TAG_INTERNET_IOP)
+ return 0;
+
+ TAO_SSLIOP_Endpoint *ssl_endpoint =
+ dynamic_cast<TAO_SSLIOP_Endpoint *> (endpoint);
+
+ if (ssl_endpoint == 0)
+ return 0;
+
+ // @@ TODO: The EstablishTrust policy should be evaluated once per
+ // connection, not once per invocation. This should
+ // improve performance.
+ //
+ // Check if the user overrode the default establishment of trust
+ // policy for the current object.
+ CORBA::Policy_var policy =
+ resolver->stub ()->get_policy (::Security::SecEstablishTrustPolicy
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ SecurityLevel2::EstablishTrustPolicy_var trust_policy =
+ SecurityLevel2::EstablishTrustPolicy::_narrow (policy.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // We use a pointer and temporary to make it obvious to determine
+ // if no establishment of trust policy was set. Specifically, if
+ // the "trust" pointer below is zero, then the SSLIOP pluggable
+ // protocol default value will be used.
+ ::Security::EstablishTrust trust = { 0 , 0 };
+ if (!CORBA::is_nil (trust_policy.in ()))
+ {
+ trust = trust_policy->trust (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ }
+
+ // Flag that states whether any form of establishment of trust
+ // should occur.
+ CORBA::Boolean const establish_trust =
+ trust.trust_in_target || trust.trust_in_client;
+
+ // @@ Should this be in a "policy validator?"
+ //
+ // If the SSL port is zero, then no SSLIOP tagged component was
+ // available in the IOR, meaning that there is no way to establish
+ // trust. Throw an exception.
+ if (ssl_endpoint->ssl_component ().port == 0
+ && establish_trust)
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("TAO_SSLIOP (%P|%t) ERROR: ")
+ ACE_TEXT ("Cannot establish trust since ")
+ ACE_TEXT ("no SSLIOP tagged component was ")
+ ACE_TEXT ("found in the IOR.\n")));
+ }
+
+ ACE_THROW_RETURN (CORBA::INV_POLICY (), // @@ Correct exception?
+ 0);
+ }
+
+ // Check if the user overrode the default Quality-of-Protection for
+ // the current object.
+ policy = resolver->stub ()->get_policy (::Security::SecQOPPolicy
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ SecurityLevel2::QOPPolicy_var qop_policy =
+ SecurityLevel2::QOPPolicy::_narrow (policy.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Temporary variable used to avoid overwriting the default value
+ // set when the ORB was initialized.
+ ::Security::QOP qop = this->qop_;
+
+ if (!CORBA::is_nil (qop_policy.in ()))
+ {
+ qop = qop_policy->qop (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ }
+
+ // If the SSL port is zero, then no SSLIOP tagged component was
+ // available in the IOR, meaning that there is no way to make a
+ // secure invocation. Throw an exception.
+ if (qop != ::Security::SecQOPNoProtection
+ && ssl_endpoint->ssl_component ().port == 0)
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("TAO_SSLIOP (%P|%t) ERROR: ")
+ ACE_TEXT ("Cannot make secure invocation since ")
+ ACE_TEXT ("no SSLIOP tagged component was ")
+ ACE_TEXT ("found in the IOR.\n")));
+ }
+
+ ACE_THROW_RETURN (CORBA::INV_POLICY (), // @@ Correct exception?
+ 0);
+ }
+
+ if ((!establish_trust && qop == ::Security::SecQOPNoProtection)
+ || ssl_endpoint->ssl_component ().port == 0)
+ {
+ return this->iiop_connect (ssl_endpoint,
+ resolver,
+ timeout
+ ACE_ENV_ARG_PARAMETER);
+ }
+
+ return this->ssliop_connect (ssl_endpoint,
+ qop,
+ trust,
+ resolver,
+ desc,
+ timeout
+ ACE_ENV_ARG_PARAMETER);
+}
+
+
+TAO_Profile *
+TAO::SSLIOP::Connector::create_profile (TAO_InputCDR& cdr)
+{
+ TAO_Profile *pfile = 0;
+ ACE_NEW_RETURN (pfile,
+ TAO_SSLIOP_Profile (this->orb_core ()),
+ 0);
+
+ const int r = pfile->decode (cdr);
+ if (r == -1)
+ {
+ pfile->_decr_refcnt ();
+ pfile = 0;
+ }
+
+ return pfile;
+}
+
+TAO_Profile *
+TAO::SSLIOP::Connector::make_profile (ACE_ENV_SINGLE_ARG_DECL)
+{
+ // The endpoint should be of the form:
+ // N.n@host:port/object_key
+ // or:
+ // host:port/object_key
+
+ TAO_Profile *profile = 0;
+ ACE_NEW_THROW_EX (profile,
+ TAO_SSLIOP_Profile (this->orb_core (),
+ 0), // SSL component
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ return profile;
+}
+
+
+TAO_Profile *
+TAO::SSLIOP::Connector::make_secure_profile (ACE_ENV_SINGLE_ARG_DECL)
+{
+ // The endpoint should be of the form:
+ // N.n@host:port/object_key
+ // or:
+ // host:port/object_key
+
+ TAO_Profile *profile = 0;
+ ACE_NEW_THROW_EX (profile,
+ TAO_SSLIOP_Profile (this->orb_core (),
+ 1), // SSL component
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ return profile;
+}
+
+
+
+TAO_Profile *
+TAO::SSLIOP::Connector::corbaloc_scan (const char *endpoint,
+ size_t &len
+ ACE_ENV_ARG_DECL)
+{
+ int ssl_only = 0;
+ if (this->check_prefix (endpoint) == 0)
+ {
+ ssl_only = 1;
+ }
+ else
+ {
+ if (this->TAO_IIOP_Connector::check_prefix (endpoint) != 0)
+ return 0;
+ }
+
+ // Determine the (first in a list of possibly > 1) endpoint address
+ const char *comma_pos = ACE_OS::strchr (endpoint,',');
+ const char *slash_pos = ACE_OS::strchr (endpoint,'/');
+ if (comma_pos == 0 && slash_pos == 0)
+ {
+ if (TAO_debug_level)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("(%P|%t) SSLIOP_Connector::corbaloc_scan warning: ")
+ ACE_TEXT("supplied string contains no comma or slash: %s\n"),
+ endpoint));
+ }
+ len = ACE_OS::strlen (endpoint);
+ }
+ else if (slash_pos != 0 || comma_pos > slash_pos)
+ {
+ // The endpoint address does not extend past the first '/' or ','
+ len = slash_pos - endpoint;
+ }
+ else
+ {
+ len = comma_pos - endpoint;
+ }
+
+ //Create the corresponding profile
+ TAO_Profile *ptmp = 0;
+ if (ssl_only)
+ {
+ ptmp = this->make_secure_profile (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ }
+ else
+ {
+ ptmp = this->make_profile (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ }
+
+ return ptmp;
+}
+
+
+int
+TAO::SSLIOP::Connector::check_prefix (const char *endpoint)
+{
+ // Check for a valid string
+ if (!endpoint || !*endpoint) return -1; // Failure
+
+ const char *protocol[] = { "ssliop", "sslioploc" };
+
+ size_t first_slot = ACE_OS::strchr (endpoint, ':') - endpoint;
+
+ size_t len0 = ACE_OS::strlen (protocol[0]);
+ size_t len1 = ACE_OS::strlen (protocol[1]);
+
+ // Check for the proper prefix in the IOR. If the proper prefix
+ // isn't in the IOR then it is not an IOR we can use.
+ if (first_slot == len0 && ACE_OS::strncmp (endpoint, protocol[0], len0) == 0)
+ return 0;
+
+ if (first_slot == len1 && ACE_OS::strncmp (endpoint, protocol[1], len1) == 0)
+ return 0;
+
+ // Failure: not an SSLIOP IOR
+ // DO NOT throw an exception here.
+ return -1;
+}
+
+
+TAO_Transport*
+TAO::SSLIOP::Connector::iiop_connect (
+ TAO_SSLIOP_Endpoint *ssl_endpoint,
+ TAO::Profile_Transport_Resolver *resolver,
+ ACE_Time_Value *timeout
+ ACE_ENV_ARG_DECL)
+{
+ const ::SSLIOP::SSL &ssl_component = ssl_endpoint->ssl_component ();
+
+ // Only allow connection to the insecure IIOP port if the endpoint
+ // explicitly allows it, i.e. if the Security::NoProtection security
+ // association bit is set in the SSLIOP::SSL::target_supports field.
+ // The server performs the same permission check, so this check is
+ // an optimization since a connection will not be established
+ // needlessly, i.e. rejected due to lack of permission.
+ //
+ // Note that it is still possible for the standard non-SSLIOP aware
+ // IIOP pluggable protocol to attempt to connect to the insecure
+ // port. In that case, the server will have to prevent the
+ // connection, and subsequently the request, from completing.
+ if (ACE_BIT_DISABLED (ssl_component.target_supports,
+ ::Security::NoProtection))
+ ACE_THROW_RETURN (CORBA::NO_PERMISSION (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EPERM),
+ CORBA::COMPLETED_NO),
+ 0);
+
+ TAO_IIOP_Endpoint *iiop_endpoint = ssl_endpoint->iiop_endpoint ();
+
+ // An IIOP-only transport descriptor must be used instead of the one
+ // passed to this method since the latter is used for SSLIOP
+ // connections. Doing so prevents an IIOP-only cached transport
+ // from being associated with an SSLIOP connection.
+ TAO_Base_Transport_Property iiop_desc (iiop_endpoint);
+
+ // Note that the IIOP-only transport descriptor is used!
+ return
+ this->TAO::IIOP_SSL_Connector::connect (
+ resolver,
+ &iiop_desc,
+ timeout
+ ACE_ENV_ARG_PARAMETER);
+}
+
+TAO_Transport *
+TAO::SSLIOP::Connector::ssliop_connect (
+ TAO_SSLIOP_Endpoint *ssl_endpoint,
+ ::Security::QOP qop,
+ const ::Security::EstablishTrust &trust,
+ TAO::Profile_Transport_Resolver *resolver,
+ TAO_Transport_Descriptor_Interface *desc,
+ ACE_Time_Value *max_wait_time
+ ACE_ENV_ARG_DECL)
+{
+ const ::SSLIOP::SSL &ssl_component = ssl_endpoint->ssl_component ();
+
+ // @@ The following check for "required insecurity" seems odd, but
+ // I haven't seen anything in the Security spec that says this
+ // policy isn't possible.
+ // -Ossama
+
+ // If the endpoint requires an insecure connection, i.e. the
+ // Security::NoProtection security association bit in the
+ // SSLIOP::SSL::target_requires field is enabled, then prevent an
+ // SSL connection from occuring.
+ if (ACE_BIT_ENABLED (ssl_component.target_requires,
+ ::Security::NoProtection))
+ ACE_THROW_RETURN (CORBA::NO_PERMISSION (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EPERM),
+ CORBA::COMPLETED_NO),
+ 0);
+
+ // If the invocation wants integrity without confidentiality but the
+ // server does not support "no protection," then it won't be
+ // possible to provide integrity. In order to support integrity
+ // without confidentiality, encryption must be disabled but secure
+ // hashes must remain enabled. This is achieved using the "eNULL"
+ // cipher. However, the "eNULL" cipher is only enabled on the
+ // server side if "no protection" is enabled.
+ if (ACE_BIT_DISABLED (ssl_component.target_supports,
+ ::Security::NoProtection)
+ && qop == ::Security::SecQOPIntegrity)
+ ACE_THROW_RETURN (CORBA::INV_POLICY (), 0);
+
+ const ACE_INET_Addr &remote_address =
+ ssl_endpoint->object_addr ();
+
+ // Verify that the remote ACE_INET_Addr was initialized
+ // properly. Failure can occur if hostname lookup failed when
+ // initializing the remote ACE_INET_Addr.
+ if (remote_address.get_type () != AF_INET)
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) SSLIOP connection failed.\n")
+ ACE_TEXT ("TAO (%P|%t) This is most likely ")
+ ACE_TEXT ("due to a hostname lookup ")
+ ACE_TEXT ("failure.\n")));
+ }
+
+ return 0;
+ }
+
+ int result = 0;
+ TAO::SSLIOP::Connection_Handler *svc_handler = 0;
+ TAO_Transport *transport = 0;
+
+ // Before we can check the cache to find an existing connection, we
+ // need to make sure the ssl_endpoint is fully initialized with the
+ // local security information. This endpoint initalized by the
+ // profile does not (and cannot) contain the desired QOP, trust, or
+ // credential information which is necesary to uniquely identify
+ // this connection.
+ if (!ssl_endpoint->credentials_set ())
+ {
+ if (TAO_debug_level > 2)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) Initializing SSLIOP_Endpoint \n")
+ ));
+
+ if (this->base_connector_.creation_strategy ()->make_svc_handler (
+ svc_handler) != 0)
+ {
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) Unable to create SSLIOP ")
+ ACE_TEXT ("service handler.\n")));
+
+ return 0;
+ }
+
+ ACE_Auto_Basic_Ptr<TAO::SSLIOP::Connection_Handler>
+ safe_handler (svc_handler);
+ TAO::SSLIOP::OwnCredentials_var credentials =
+ this->retrieve_credentials (resolver->stub (),
+ svc_handler->peer ().ssl ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ svc_handler = safe_handler.release ();
+ ssl_endpoint->set_sec_attrs (qop, trust, credentials.in());
+ }
+
+ // Check the Cache first for connections
+ if (this->orb_core ()->lane_resources ().transport_cache ().find_transport (
+ desc,
+ transport) == 0)
+ {
+ if (TAO_debug_level > 2)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, ")
+ ACE_TEXT ("got existing transport[%d]\n"),
+ transport->id ()));
+
+ // When the transport is not connected wait for completion
+ if (!transport->is_connected())
+ {
+ if (!this->wait_for_connection_completion (resolver,
+ transport,
+ max_wait_time))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect,")
+ ACE_TEXT ("wait for completion failed\n")));
+
+ }
+ }
+ }
+ else
+ {
+ if (TAO_debug_level > 4)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, ")
+ ACE_TEXT ("making a new connection \n")));
+
+ // Purge connections (if necessary)
+ this->orb_core ()->lane_resources ().transport_cache ().purge ();
+
+ // The svc_handler is created beforehand so that we can get
+ // access to the underlying ACE_SSL_SOCK_Stream (the peer) and
+ // its SSL pointer member prior to descending into the
+ // ACE_Strategy_Connector (the "base_connector_"). This is
+ // thread-safe and reentrant, hence no synchronization is
+ // necessary.
+ //
+ // The make_svc_handler() method creates the service handler and
+ // bumps the #REFCOUNT# up one extra. The extra reference count
+ // in TAO_Connect_Creation_Strategy::make_svc_handler() is
+ // needed in the case when connection completion is pending and
+ // we are going to wait on a variable in the handler to changes,
+ // signifying success or failure. Note, that this increment
+ // cannot be done once the connect() returns since this might be
+ // too late if another thread pick up the completion and
+ // potentially deletes the handler before we get a chance to
+ // increment the reference count.
+ if (svc_handler == 0 &&
+ this->base_connector_.creation_strategy ()->make_svc_handler (
+ svc_handler) != 0)
+ {
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) Unable to create SSLIOP ")
+ ACE_TEXT ("service handler.\n")));
+
+ return 0;
+ }
+
+ ACE_Auto_Basic_Ptr<TAO::SSLIOP::Connection_Handler>
+ safe_handler (svc_handler);
+
+ // Setup the establishment of trust connection properties, if
+ // any.
+ int verify_mode = 0;
+
+ // On the server side, "trust_in_client" requires that a peer
+ // (client) certificate exist. Fail if one doesn't exist.
+ //
+ // In SSLIOP's case, trust_in_client also implies
+ // trust_in_target.
+ if (trust.trust_in_client)
+ verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+
+ // Require verification of the target's certificate.
+ else if (trust.trust_in_target)
+ verify_mode = SSL_VERIFY_PEER;
+
+ // Trust in neither the client nor the target is explicitly
+ // specified. Use the default setting.
+ else
+ verify_mode =
+ ACE_SSL_Context::instance ()->default_verify_mode ();
+
+ ::SSL_set_verify (svc_handler->peer ().ssl (),
+ verify_mode,
+ 0);
+
+ // The "eNULL" cipher disables encryption but still uses a
+ // secure hash (e.g. SHA1 or MD5) to ensure integrity. (Try the
+ // command "openssl ciphers -v eNULL".)
+ //
+ // Note that it is not possible to completely disable protection
+ // here.
+ if ((qop == ::Security::SecQOPNoProtection
+ || qop == ::Security::SecQOPIntegrity)
+ && ::SSL_set_cipher_list (svc_handler->peer ().ssl (),
+ "eNULL") == 0)
+ {
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) Unable to set eNULL ")
+ ACE_TEXT ("SSL cipher.\n")));
+
+ ACE_THROW_RETURN (CORBA::INV_POLICY (), 0);
+ }
+
+ svc_handler = safe_handler.release ();
+
+ // Get the right synch options
+ ACE_Synch_Options synch_options;
+
+ this->active_connect_strategy_->synch_options (max_wait_time,
+ synch_options);
+
+ // If we don't need to block for a transport just set the timeout to
+ // be zero.
+ ACE_Time_Value tmp_zero (ACE_Time_Value::zero);
+ if (!resolver->blocked_connect ())
+ {
+ synch_options.timeout (ACE_Time_Value::zero);
+ max_wait_time = &tmp_zero;
+ }
+
+ // We obtain the transport in the <svc_handler> variable. As we
+ // know now that the connection is not available in Cache we can
+ // make a new connection
+ result = this->base_connector_.connect (svc_handler,
+ remote_address,
+ synch_options);
+
+ // There are three possibilities from calling connect(): (a)
+ // connection succeeds immediately - in this case, the
+ // #REFCOUNT# on the handler is two; (b) connection completion
+ // is pending - in this case, the #REFCOUNT# on the handler is
+ // also two; (c) connection fails immediately - in this case,
+ // the #REFCOUNT# on the handler is one since close() gets
+ // called on the handler.
+
+ // Make sure that we always do a remove_reference
+ ACE_Event_Handler_var svc_handler_auto_ptr (svc_handler);
+
+ transport =
+ svc_handler->transport ();
+
+ if (result == -1)
+ {
+ // No immediate result, wait for completion
+ if (errno == EWOULDBLOCK)
+ {
+ // Try to wait until connection completion. Incase we block, then we
+ // get a connected transport or not. In case of non block we get
+ // a connected or not connected transport
+ if (!this->wait_for_connection_completion (resolver,
+ transport,
+ max_wait_time))
+ {
+ if (TAO_debug_level > 2)
+ ACE_ERROR ((LM_ERROR, "TAO (%P|%t) - SSLIOP_Connector::"
+ "ssliop_connect, "
+ "wait for completion failed\n"));
+ }
+ }
+ else
+ {
+ // Transport is not usable
+ transport = 0;
+ }
+ }
+
+ // In case of errors transport is zero
+ if (transport == 0)
+ {
+ // Give users a clue to the problem.
+ if (TAO_debug_level)
+ {
+ char buffer [MAXHOSTNAMELEN + 6 + 1];
+ ssl_endpoint->addr_to_string (buffer,
+ sizeof (buffer) - 1);
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) - SSL connection to ")
+ ACE_TEXT ("<%s:%d> failed (%p)\n"),
+ buffer,
+ remote_address.get_port_number (),
+ ACE_TEXT ("errno")));
+ }
+
+ return 0;
+ }
+
+ // At this point, the connection has be successfully connected.
+ // #REFCOUNT# is one.
+ if (TAO_debug_level > 2)
+ ACE_DEBUG ((LM_DEBUG,
+ "TAO (%P|%t) - SSLIOP_Connector::ssliop_connect, "
+ "new SSL connection to port %d on transport[%d]\n",
+ remote_address.get_port_number (),
+ svc_handler->peer ().get_handle ()));
+
+ // Add the handler to Cache
+ int retval =
+ this->orb_core ()->
+ lane_resources ().transport_cache ().cache_transport (desc,
+ transport);
+
+ // Failure in adding to cache.
+ if (retval != 0)
+ {
+ // Close the handler.
+ svc_handler->close ();
+
+ if (TAO_debug_level > 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "TAO (%P|%t) - SLIIOP_Connector::ssliop_connect, "
+ "could not add the new connection to cache\n"));
+ }
+
+ return 0;
+ }
+
+ if (transport->is_connected () &&
+ transport->wait_strategy ()->register_handler () != 0)
+ {
+ // Registration failures.
+
+ // Purge from the connection cache, if we are not in the cache, this
+ // just does nothing.
+ (void) transport->purge_entry ();
+
+ // Close the handler.
+ (void) transport->close_connection ();
+
+ if (TAO_debug_level > 0)
+ ACE_ERROR ((LM_ERROR,
+ "TAO (%P|%t) - SSLIOP_Connector [%d]::ssliop_connect, "
+ "could not register the transport "
+ "in the reactor.\n",
+ transport->id ()));
+
+ return 0;
+ }
+ }
+
+ return transport;
+}
+
+TAO::SSLIOP::OwnCredentials *
+TAO::SSLIOP::Connector::retrieve_credentials (TAO_Stub *stub,
+ SSL *ssl
+ ACE_ENV_ARG_DECL)
+{
+ // Check if the user overrode the default invocation credentials.
+ CORBA::Policy_var policy =
+ stub->get_policy (::SecurityLevel3::ContextEstablishmentPolicyType
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
+
+ SecurityLevel3::ContextEstablishmentPolicy_var creds_policy =
+ SecurityLevel3::ContextEstablishmentPolicy::_narrow (
+ policy.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
+
+ TAO::SSLIOP::OwnCredentials_var ssliop_credentials;
+
+ // Set the Credentials (X.509 certificates and corresponding private
+ // keys) to be used for this invocation.
+ if (!CORBA::is_nil (creds_policy.in ()))
+ {
+ SecurityLevel3::OwnCredentialsList_var creds_list =
+ creds_policy->creds_list (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
+
+ if (creds_list->length () > 0)
+ {
+ // Assume that we've got an SSLIOP credential.
+ SecurityLevel3::Credentials_ptr credentials =
+ creds_list[0u];
+
+ ssliop_credentials =
+ TAO::SSLIOP::OwnCredentials::_narrow (credentials
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
+
+ if (!CORBA::is_nil (ssliop_credentials.in ()))
+ {
+ TAO::SSLIOP::X509_var x509 = ssliop_credentials->x509 ();
+ if (::SSL_use_certificate (ssl, x509.in ()) != 1)
+ return TAO::SSLIOP::OwnCredentials::_nil ();
+
+ TAO::SSLIOP::EVP_PKEY_var evp = ssliop_credentials->evp ();
+ if (evp.in () != 0
+ && ::SSL_use_PrivateKey (ssl, evp.in ()) != 1)
+ {
+ // Invalidate the certificate we just set.
+ (void) ::SSL_use_certificate (ssl, 0);
+ return TAO::SSLIOP::OwnCredentials::_nil ();
+ }
+ }
+ }
+ }
+ else
+ {
+ // Use the default certificate and private key, i.e. the one set
+ // in the SSL_CTX that was used when creating the SSL data
+ // structure.
+
+ /**
+ * @todo Check if the CredentialsCurator contains a default set
+ * of SSLIOP OwnCredentials.
+ */
+
+ TAO::SSLIOP::OwnCredentials_ptr & c = ssliop_credentials.out ();
+ ACE_NEW_THROW_EX (c,
+ TAO::SSLIOP::OwnCredentials (
+ ::SSL_get_certificate (ssl),
+ ::SSL_get_privatekey (ssl)),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (TAO::SSLIOP::OwnCredentials::_nil ());
+ }
+
+ return ssliop_credentials._retn ();
+}
+
+int
+TAO::SSLIOP::Connector::cancel_svc_handler (
+ TAO_Connection_Handler * svc_handler)
+{
+ TAO::SSLIOP::Connection_Handler* handler=
+ dynamic_cast<TAO::SSLIOP::Connection_Handler*> (svc_handler);
+
+ if (handler)
+ // Cancel from the connector
+ return this->base_connector_.cancel (handler);
+
+ return -1;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL