diff options
Diffstat (limited to 'trunk/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Endpoint.cpp')
-rw-r--r-- | trunk/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Endpoint.cpp | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/trunk/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Endpoint.cpp b/trunk/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Endpoint.cpp new file mode 100644 index 00000000000..c2315dbca3c --- /dev/null +++ b/trunk/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Endpoint.cpp @@ -0,0 +1,382 @@ +#include "orbsvcs/SSLIOP/SSLIOP_Endpoint.h" + +#include "tao/IIOP_Endpoint.h" + +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" +#include "ace/os_include/os_netdb.h" + +#include "tao/debug.h" + +ACE_RCSID (SSLIOP, + SSLIOP_Endpoint, + "$Id$") + + +#if !defined (__ACE_INLINE__) +# include "orbsvcs/SSLIOP/SSLIOP_Endpoint.inl" +#endif /* __ACE_INLINE__ */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_SSLIOP_Endpoint::TAO_SSLIOP_Endpoint (const ::SSLIOP::SSL *ssl_component, + TAO_IIOP_Endpoint *iiop_endp) + : TAO_Endpoint (IOP::TAG_INTERNET_IOP), + object_addr_ (), + next_ (0), + iiop_endpoint_ (iiop_endp), + destroy_iiop_endpoint_ (false), + qop_ (::Security::SecQOPIntegrityAndConfidentiality), +#if !defined (VXWORKS) && !defined (__QNX__) + // Some compilers don't like the initialization + trust_ (), +#endif /* !VXWORKS && !__QNX__ */ + credentials_ (), + credentials_set_ (0) +{ + if (ssl_component != 0) + { + // Copy the security association options in the IOR's SSL tagged + // component. + this->ssl_component_.target_supports = ssl_component->target_supports; + this->ssl_component_.target_requires = ssl_component->target_requires; + this->ssl_component_.port = ssl_component->port; + } + else + { + // No SSL tagged component is available so construct a default + // set of security association options, in addition to the IANA + // assigned IIOP over SSL port (684). This is generally a + // client side issue. + + // Clear all bits in the SSLIOP::SSL association option fields. + this->ssl_component_.target_supports = 0; + this->ssl_component_.target_requires = 0; + + // SSLIOP requires these Security::AssociationOptions by default. + ACE_SET_BITS (this->ssl_component_.target_requires, + ::Security::Integrity + | ::Security::Confidentiality + | ::Security::NoDelegation); + + // SSLIOP supports these Security::AssociationOptions by + // default. + // + // Note that the Security::NoProtection bit is set since we + // can't be sure if the server supports SSL, and TAO's SSLIOP + // implementation must support IIOP over SSL and plain IIOP. + ACE_SET_BITS (this->ssl_component_.target_supports, + ::Security::Integrity + | ::Security::Confidentiality + | ::Security::EstablishTrustInTarget + | ::Security::NoProtection + | ::Security::NoDelegation); + + // Initialize the default SSL port to zero, not the IANA + // assigned IIOP over SSL port (684). We usually only get here + // if we're creating a profile on the client side using an IOR + // that does not contain an SSLIOP tagged component. + this->ssl_component_.port = 0; + } + + // Invalidate the Addr until the first attempt to use it is made. + this->object_addr_.set_type (-1); + + this->trust_.trust_in_target = 1; + this->trust_.trust_in_client = 1; +} + +TAO_SSLIOP_Endpoint::~TAO_SSLIOP_Endpoint (void) +{ + if (this->destroy_iiop_endpoint_) + delete this->iiop_endpoint_; +} + +#if 0 +static void +dump_endpoint (const char* msg, const TAO_Endpoint *other_endpoint) +{ + + TAO_Endpoint *endpt = const_cast<TAO_Endpoint *> (other_endpoint); + + TAO_SSLIOP_Endpoint *endpoint = + dynamic_cast<TAO_SSLIOP_Endpoint *> (endpt); + + if (endpoint == 0) + { + ACE_DEBUG ((LM_DEBUG, "TAO (%P|%t) endpoint - %s: Unable to cast an endpoint to SSLIOP_Endpoint\n", msg)); + return; + } + + char hostaddr[MAXHOSTNAMELEN + 16]; + int gothost = endpoint->addr_to_string (hostaddr, sizeof hostaddr); + + ACE_DEBUG ((LM_INFO, "TAO (%P|%t) SSLIOPEndpoint %s - %@ {%s, ssl=%d, iiop=%d," + " qop=%d, trst=(%d,%d), c=%@, crdh=0x%x}, h=0x%x\n", + msg, + endpoint, + (gothost == 0 ? hostaddr : "*UNKNOWN*"), + endpoint->ssl_component ().port , + endpoint->iiop_endpoint ()->port (), + endpoint->qop() , + endpoint->trust().trust_in_target , + endpoint->trust().trust_in_client , + endpoint->credentials() , + (endpoint->credentials_set () ? endpoint->credentials()->hash () : 0) , + endpoint->hash ())); +} +#endif /* 0 */ + +int +TAO_SSLIOP_Endpoint::addr_to_string (char *buffer, size_t length) +{ + size_t actual_len = + ACE_OS::strlen (this->iiop_endpoint_->host ()) // chars in host name + + sizeof (':') // delimiter + + ACE_OS::strlen ("65536") // max port + + sizeof ('\0'); + + if (length < actual_len) + return -1; + + ACE_OS::sprintf (buffer, + "%s:%d", + this->iiop_endpoint_->host (), + this->ssl_component_.port); + + return 0; +} + + +TAO_Endpoint * +TAO_SSLIOP_Endpoint::next (void) +{ + return this->next_; +} + +CORBA::Boolean +TAO_SSLIOP_Endpoint::is_equivalent (const TAO_Endpoint *other_endpoint) +{ + TAO_Endpoint *endpt = const_cast<TAO_Endpoint *> (other_endpoint); + + TAO_SSLIOP_Endpoint *endpoint = + dynamic_cast<TAO_SSLIOP_Endpoint *> (endpt); + + if (endpoint == 0) + return 0; + + ::Security::EstablishTrust t = endpoint->trust (); + + if ((this->ssl_component_.port != 0 + && endpoint->ssl_component_.port != 0 + && this->ssl_component_.port != endpoint->ssl_component_.port) + || this->qop_ != endpoint->qop () + || this->trust_.trust_in_target != t.trust_in_target + || this->trust_.trust_in_client != t.trust_in_client + || (!CORBA::is_nil (this->credentials_.in ()) + && !(*this->credentials_.in () == *endpoint->credentials ()))) + { + return 0; + } + + // Comparing the underlying iiop endpoints is wrong, as their port + // numbers often may not make sense. Or may not being used anyway. + // Therefore, we only need to directly compare the hosts. See also the + // comments in the hash() method. + if (this->iiop_endpoint() == 0 || endpoint->iiop_endpoint() == 0) + return 0; + + if ((ACE_OS::strcmp (this->iiop_endpoint()->host (), + endpoint->iiop_endpoint()->host ()) != 0)) + return 0; + + return 1; +} + +TAO_Endpoint * +TAO_SSLIOP_Endpoint::duplicate (void) +{ + TAO_SSLIOP_Endpoint *endpoint = 0; + + // @@ We need to set the priority of the newly formed endpoint. It + // shouldnt be a problem as long as SSL is not used with RTCORBA. + ACE_NEW_RETURN (endpoint, + TAO_SSLIOP_Endpoint (&this->ssl_component_, + 0), + 0); + + if (this->credentials_set_) + endpoint->set_sec_attrs (this->qop_,this->trust_, this->credentials_.in()); + + endpoint->iiop_endpoint (this->iiop_endpoint_, true); + endpoint->hash_val_ = this->hash_val_; + return endpoint; +} + +CORBA::ULong +TAO_SSLIOP_Endpoint::hash (void) +{ + // there is actually the potential for a race of the inverse case, + // since setting the security attributes will reset the hash_val_, + // it is possible this test to pass, but then have the hash reset + // before the value is returned. + if (this->hash_val_ != 0) + return this->hash_val_; + + // Do this with no locks held, as it may try to acquire it, too. + const ACE_INET_Addr &oaddr = this->object_addr(); + + { // nested scope for the lock + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, + guard, + this->addr_lookup_lock_, + this->hash_val_); + // .. DCL + if (this->hash_val_ != 0) + return this->hash_val_; + + + // Note that we are not using the underlying IIOP endpoint's hash + // value in order to avoid the influence of the IIOP port number, + // since it is ignored anyway. When it features a + // purely fictional port number, as when accepting an SSL + // connection, the unsecured port is undefined and + // had we used it in computing the hash it would have broken the + // bi-directional support - as the 'guessed' IIOP port value will + // hardly match the one specified in the bi-dir service context. + this->hash_val_ = + oaddr.get_ip_address () + + this->ssl_component_.port; + } + + return this->hash_val_; +} + + +const ACE_INET_Addr & +TAO_SSLIOP_Endpoint::object_addr (void) const +{ + // The object_addr_ is initialized here, rather than at IOR decode + // time for several reasons: + // 1. A request on the object may never be invoked. + // 2. The DNS setup may have changed dynamically. + // ...etc.. + + // Double checked locking optimization. + if (this->object_addr_.get_type () != AF_INET) + { + const ACE_INET_Addr &iiop_addr = this->iiop_endpoint_->object_addr (); + + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, + guard, + this->addr_lookup_lock_, + this->object_addr_); + + if (this->object_addr_.get_type () != AF_INET) + { + this->object_addr_ = iiop_addr; + this->object_addr_.set_port_number (this->ssl_component_.port); + } + } + + return this->object_addr_; +} + +void +TAO_SSLIOP_Endpoint::set_sec_attrs (::Security::QOP q, + const ::Security::EstablishTrust &t, + const TAO::SSLIOP::OwnCredentials_ptr c) +{ + if (this->credentials_set_) + return; + + ACE_GUARD (TAO_SYNCH_MUTEX, + guard, + this->addr_lookup_lock_); + + // double-check + if (this->credentials_set_) + return; + + this->qop_ = q; + this->trust_ = t; + this->credentials_ = TAO::SSLIOP::OwnCredentials::_duplicate (c); + this->credentials_set_ = 1; + + // reset the hash value to force a recomputation. + this->hash_val_ = 0; +} + + + + +TAO_SSLIOP_Synthetic_Endpoint::~TAO_SSLIOP_Synthetic_Endpoint () +{ +} + +TAO_SSLIOP_Synthetic_Endpoint::TAO_SSLIOP_Synthetic_Endpoint (const ::SSLIOP::SSL *ssl) + : TAO_SSLIOP_Endpoint (ssl, 0) +{ +} + + +TAO_SSLIOP_Synthetic_Endpoint::TAO_SSLIOP_Synthetic_Endpoint (TAO_IIOP_Endpoint *iiop_endp) + : TAO_SSLIOP_Endpoint ((const ::SSLIOP::SSL *)0, iiop_endp) +{ + this->ssl_component_.port = iiop_endp->port (); +} + + +CORBA::Boolean +TAO_SSLIOP_Synthetic_Endpoint::is_equivalent (const TAO_Endpoint *other_endpoint) +{ + TAO_Endpoint *endpt = const_cast<TAO_Endpoint *> (other_endpoint); + + TAO_SSLIOP_Endpoint *endpoint = + dynamic_cast<TAO_SSLIOP_Endpoint *> (endpt); + + if (endpoint == 0) + return 0; + + if ((this->ssl_component ().port != 0 + && endpoint->ssl_component ().port != 0 + && this->ssl_component ().port != endpoint->ssl_component ().port) + || this->qop () < endpoint->qop ()) + { + return 0; + } + + // Comparing the underlying iiop endpoints is wrong, as their port + // numbers often may not make sense, or are not being used anyway. + // Therefore, directly comparing the hosts at this point. See also the + // comments in the hash() method + if (this->iiop_endpoint() == 0 || endpoint->iiop_endpoint() == 0) + return 0; + + if ((ACE_OS::strcmp (this->iiop_endpoint()->host (), + endpoint->iiop_endpoint()->host ()) != 0)) + return 0; + + return 1; +} + +TAO_Endpoint * +TAO_SSLIOP_Synthetic_Endpoint::duplicate (void) +{ + TAO_SSLIOP_Synthetic_Endpoint *endpoint = 0; + + // @@ We need to set the priority of the newly formed endpoint. It + // shouldnt be a problem as long as SSL is not used with RTCORBA. + ACE_NEW_RETURN (endpoint, + TAO_SSLIOP_Synthetic_Endpoint (&(this->ssl_component ())), + 0); + + if (this->credentials_set()) + endpoint->set_sec_attrs (this->qop (),this->trust (), this->credentials ()); + + endpoint->iiop_endpoint (this->iiop_endpoint (), true); + endpoint->hash_val_ = this->hash (); + return endpoint; +} + +TAO_END_VERSIONED_NAMESPACE_DECL |