📄 ssliop_connector.cpp
字号:
{
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;
// 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 ("(%P|%t) SSLIOP_Connector::connect ")
ACE_TEXT ("got existing transport[%d]\n"),
transport->id ()));
}
else
{
if (TAO_debug_level > 4)
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("(%P|%t) SSLIOP_Connector::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 (this->base_connector_.creation_strategy ()->make_svc_handler (
svc_handler) != 0)
{
if (TAO_debug_level > 0)
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("(%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);
}
TAO_SSLIOP_Credentials_var credentials =
this->retrieve_credentials (resolver->stub (),
svc_handler->peer ().ssl ()
ACE_ENV_ARG_PARAMETER);
ACE_CHECK_RETURN (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);
// 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.
// No immediate result. Wait for completion.
if (result == -1 && errno == EWOULDBLOCK)
{
if (TAO_debug_level > 2)
ACE_DEBUG ((LM_DEBUG,
"TAO (%P|%t) - SSLIOP_Connector::ssliop_connect(), "
"going to wait for connection completion on local"
"handle [%d]\n",
svc_handler->get_handle ()));
// Wait for connection completion. No need to specify timeout
// to wait() since the correct timeout was passed to the
// Connector. The Connector will close the handler in the case
// of timeouts, so the event will complete (either success or
// failure) within timeout.
result =
this->active_connect_strategy_->wait (svc_handler,
0);
if (TAO_debug_level > 2)
{
ACE_DEBUG ((LM_DEBUG,
"TAO (%P|%t) - IIOP_Connector::make_connection"
"wait done for handle[%d], result = %d\n",
svc_handler->get_handle (), result));
}
// There are three possibilities when wait() returns: (a)
// connection succeeded; (b) connection failed; (c) wait()
// failed because of some other error. It is easy to deal with
// (a) and (b). (c) is tricky since the connection is still
// pending and may get completed by some other thread. The
// following code deals with (c).
// Check if the handler has been closed.
int closed =
svc_handler->is_closed ();
// In case of failures and close() has not be called.
if (result == -1 &&
!closed)
{
// First, cancel from connector.
this->base_connector_.cancel (svc_handler);
// Double check to make sure the handler has not been closed
// yet. This double check is required to ensure that the
// connection handler was not closed yet by some other
// thread since it was still registered with the connector.
// Once connector.cancel() has been processed, we are
// assured that the connector will no longer open/close this
// handler.
closed =
svc_handler->is_closed ();
// If closed, there is nothing to do here. If not closed,
// it was either opened or is still pending.
if (!closed)
{
// Check if the handler has been opened.
int open =
svc_handler->is_open ();
// Some other thread was able to open the handler even
// though wait failed for this thread.
if (open)
// Overwrite <result>.
result = 0;
else
{
// Assert that it is still connecting.
ACE_ASSERT (svc_handler->is_connecting ());
// Force close the handler now.
svc_handler->close ();
}
}
}
}
// Irrespective of success or failure, remove the extra #REFCOUNT#.
svc_handler->remove_reference ();
// In case of errors.
if (result == -1)
{
// 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) %N:%l, 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 ()));
transport =
svc_handler->transport ();
ssl_endpoint->qop (qop);
ssl_endpoint->trust (trust);
ssl_endpoint->credentials (credentials.in ());
// 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) - IIOP_Connector::make_connection, "
"could not add the new connection to cache\n"));
}
return 0;
}
// If the wait strategy wants us to be registered with the reactor
// then we do so. If registeration is required and it succeeds,
// #REFCOUNT# becomes two.
retval = transport->wait_strategy ()->register_handler ();
// Registration failures.
if (retval != 0)
{
// Purge from the connection cache.
transport->purge_entry ();
// Close the handler.
svc_handler->close ();
if (TAO_debug_level > 0)
{
ACE_ERROR ((LM_ERROR,
"TAO (%P|%t) - IIOP_Connector::make_connection, "
"could not register the new connection in the reactor\n"));
}
return 0;
}
}
return transport;
}
TAO_SSLIOP_Credentials *
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 (Security::SecInvocationCredentialsPolicy
ACE_ENV_ARG_PARAMETER);
ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_nil ());
SecurityLevel2::InvocationCredentialsPolicy_var creds_policy =
SecurityLevel2::InvocationCredentialsPolicy::_narrow (
policy.in ()
ACE_ENV_ARG_PARAMETER);
ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_nil ());
TAO_SSLIOP_Credentials_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 ()))
{
SecurityLevel2::CredentialsList_var creds_list =
creds_policy->creds (ACE_ENV_SINGLE_ARG_PARAMETER);
ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_nil ());
if (creds_list->length () > 0)
{
// Only use the first credential. All others are supposed
// to be used for delegation but SSLIOP in CSIv1 does not
// support delegation. (Compare to CSIv2.)
SecurityLevel2::Credentials_ptr credentials =
creds_list[(CORBA::ULong) 0];
ssliop_credentials =
TAO_SSLIOP_Credentials::_narrow (credentials
ACE_ENV_ARG_PARAMETER);
ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_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_Credentials::_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_Credentials::_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.
TAO_SSLIOP_Credentials_ptr & c = ssliop_credentials.out ();
ACE_NEW_THROW_EX (c,
TAO_SSLIOP_Credentials (::SSL_get_certificate (ssl),
::SSL_get_privatekey (ssl)),
CORBA::NO_MEMORY ());
ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_nil ());
}
return ssliop_credentials._retn ();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -