diff options
author | Phil Mesnier <mesnier_p@ociweb.com> | 2007-07-12 17:10:11 +0000 |
---|---|---|
committer | Phil Mesnier <mesnier_p@ociweb.com> | 2007-07-12 17:10:11 +0000 |
commit | 6162ee8bee93cff083ff63c024fecc172e4f01fb (patch) | |
tree | c5212f5864609dc97de2e5e96a92c645d3a46346 /TAO/orbsvcs/orbsvcs | |
parent | deac37b9ee25368f0337d10682ea2c574962bb4a (diff) | |
download | ATCD-6162ee8bee93cff083ff63c024fecc172e4f01fb.tar.gz |
Thu Jul 12 16:51:30 UTC 2007 Phil Mesnier <mesnier_p@ociweb.com>
Diffstat (limited to 'TAO/orbsvcs/orbsvcs')
-rw-r--r-- | TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp | 2 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp | 205 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.h | 22 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_ORBInitializer.cpp | 31 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Security/SL2_SecurityManager.cpp | 325 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Security/SL2_SecurityManager.h | 226 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Security/Security_ORBInitializer.cpp | 74 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/SecurityLevel2.idl | 35 |
8 files changed, 781 insertions, 139 deletions
diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp index a1bd7d9b1ec..c192d1b8066 100644 --- a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp +++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connector.cpp @@ -348,6 +348,7 @@ TAO::SSLIOP::Connector::iiop_connect ( TAO::Profile_Transport_Resolver *resolver, ACE_Time_Value *timeout) { +#if 0 const ::SSLIOP::SSL &ssl_component = ssl_endpoint->ssl_component (); // Only allow connection to the insecure IIOP port if the endpoint @@ -368,6 +369,7 @@ TAO::SSLIOP::Connector::iiop_connect ( TAO::VMCID, EPERM), CORBA::COMPLETED_NO); +#endif TAO_IIOP_Endpoint *iiop_endpoint = ssl_endpoint->iiop_endpoint (); diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp index f1542176fa3..ddcf5182e5e 100644 --- a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp +++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp @@ -1,9 +1,11 @@ #include "orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.h" +#include "orbsvcs/SSLIOP/SSLIOP_Current.h" #include "orbsvcs/SecurityLevel2C.h" #include "tao/ORB_Constants.h" #include "tao/PortableServer/PS_CurrentC.h" +#include "tao/PortableServer/POAC.h" #include "tao/debug.h" #if defined (SSLIOP_DEBUG_PEER_CERTIFICATE) @@ -17,12 +19,54 @@ ACE_RCSID (SSLIOP, TAO_BEGIN_VERSIONED_NAMESPACE_DECL -TAO::SSLIOP::Server_Invocation_Interceptor::Server_Invocation_Interceptor ( - ::SSLIOP::Current_ptr current, - ::Security::QOP qop) - : ssliop_current_ (::SSLIOP::Current::_duplicate (current)), - qop_ (qop) +TAO::SSLIOP::Server_Invocation_Interceptor::Server_Invocation_Interceptor +( + PortableInterceptor::ORBInitInfo_ptr info, + ::Security::QOP default_qop, + size_t tss_slot +) +: qop_ (default_qop) { + /* + * Cache references to the "Current" objects that we'll need during + * during invocations. + */ + + CORBA::Object_var obj = + info->resolve_initial_references ("SSLIOPCurrent"); + + this->ssliop_current_ = ::SSLIOP::Current::_narrow (obj.in ()); + + if (!CORBA::is_nil (this->ssliop_current_.in ())) + { + TAO::SSLIOP::Current *tao_current = + dynamic_cast<TAO::SSLIOP::Current *> (this->ssliop_current_.in ()); + + if (tao_current != 0) + { + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, "TAO (%P|%t) SSLIOP_Invocation_Interceptor::CTOR--setting up SSLIOP Current with slot %d\n", tss_slot)); + tao_current->tss_slot (tss_slot); + } + else + throw CORBA::INTERNAL (); + } + + obj = info->resolve_initial_references ("SecurityLevel2:SecurityManager"); + this->sec2manager_ = SecurityLevel2::SecurityManager::_narrow (obj.in ()); + + if (! CORBA::is_nil (this->sec2manager_.in ())) + { + // set the slot id? things seem to work without doing this + } + +#if 0 + // Don't need this now that we're not using access_allowed(), but + // I'm leaving the code here just in case it would become convenient + // for some other use. + obj = info->resolve_initial_references ("POACurrent"); + this->poa_current_ = PortableServer::Current::_narrow (obj.in ()); +#endif } TAO::SSLIOP::Server_Invocation_Interceptor::~Server_Invocation_Interceptor ( @@ -45,93 +89,84 @@ void TAO::SSLIOP::Server_Invocation_Interceptor::receive_request_service_contexts ( PortableInterceptor::ServerRequestInfo_ptr /*ri*/) { - // The current upcall is not being performed through an SSL - // connection. If server is configured to disallow insecure - // invocations then throw a CORBA::NO_PERMISSION exception. - // @@ TODO: Once the SecurityManager is implemented, query it - // for the current object's - // SecureInvocationPolicy of type - // SecTargetSecureInvocationPolicy so that we can - // accept or reject requests on a per-object basis - // instead on a per-endpoint basis. - CORBA::Boolean const no_ssl = this->ssliop_current_->no_context (); - - if (TAO_debug_level >= 3) - ACE_DEBUG ((LM_DEBUG, "SSLIOP (%P|%t) Interceptor (context), ssl=%d\n", !(no_ssl))); - - if (no_ssl && this->qop_ != ::Security::SecQOPNoProtection) - throw CORBA::NO_PERMISSION (); - -#if defined(SSLIOP_DEBUG_PEER_CERTIFICATE) - try - { - // If the request was not made through an SSL connection, then - // this method will throw the SSLIOP::Current::NoContext - // exception. Otherwise, it will return a DER encoded X509 - // certificate. - ::SSLIOP::ASN_1_Cert_var cert = - this->ssliop_current_->get_peer_certificate (); - - // @@ The following debugging code works but I don't think that - // we should include it since it dumps alot of information, - // i.e. prints two lines of information per request. - if (TAO_debug_level > 1) - { - const CORBA::Octet *der_cert = cert->get_buffer (); - - ::X509 *peer = ::d2i_X509 (0, &der_cert, cert->length ()); - if (peer != 0) - { - char buf[BUFSIZ] = { 0 }; - - ::X509_NAME_oneline (::X509_get_subject_name (peer), - buf, - BUFSIZ); +} - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Certificate subject: %s\n", - buf)); - ::X509_NAME_oneline (::X509_get_issuer_name (peer), - buf, - BUFSIZ); +void +TAO::SSLIOP::Server_Invocation_Interceptor::receive_request ( + PortableInterceptor::ServerRequestInfo_ptr ri ) +{ + SecurityLevel2::AccessDecision_var ad_tmp = + this->sec2manager_->access_decision (); + TAO::SL2::AccessDecision_var ad = + TAO::SL2::AccessDecision::_narrow (ad_tmp.in ()); - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Certificate issuer: %s\n", - buf)); + CORBA::Boolean const no_ssl = + this->ssliop_current_->no_context (); + if (TAO_debug_level >= 3) + ACE_DEBUG ((LM_DEBUG, "SSLIOP (%P|%t) Interceptor (context), ssl=%d\n", !(no_ssl))); - ::X509_free (peer); - } - else - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) No certificate info\n")); - } - } - } - catch (const ::SSLIOP::Current::NoContext& ) + // if + // (1) no SSL session state is available (which means that the + // invocation is received across a non-SSL transport) + // AND + // (2) the required Quality of Protection is something other + // than SecQOPNoProtection (set via -SSLNoProtection) + if (no_ssl && this->qop_ != ::Security::SecQOPNoProtection) { - // The current upcall is not being performed through an SSL - // connection. If server is configured to disallow insecure - // invocations then throw a CORBA::NO_PERMISSION exception. - // @@ TODO: Once the SecurityManager is implemented, query it - // for the current object's - // SecureInvocationPolicy of type - // SecTargetSecureInvocationPolicy so that we can - // accept or reject requests on a per-object basis - // instead on a per-endpoint basis. - if (this->qop_ != ::Security::SecQOPNoProtection) - throw CORBA::NO_PERMISSION (); + /* + * Set up all the arguments needed by the call + * to AccessDecision::access_allowed() + */ + + /* Get the credentials from SSLIOP */ + SecurityLevel2::CredentialsList cred_list; // initial empty? +#if 0 + try { + SecurityLevel2::ReceivedCredentials_var rcvd_creds = + this->sec2_current_->received_credentials (); + // this gets the credentials received from the other side. We + // should be able to put this into a CredentialsList with no + // problem. + // + // Do I really need to implement a sec2_current, or can I hack + // the conversion at this level? I probably ought to do it as + // a real sec2_current with the conversion from sec3->sec2 + // happening at a lower level. + + cred_list.length(1); + cred_list[0] = rcvd_creds.in (); + /* + So, in looking for how we can do this, I find that the + SL3_SecurityCurrent::client_credentials() delegates to SL3_SecurityCurrent_Impl::client_credentials(), which is pure virtual. + */ + } + catch (...) { + } +#endif + + /* Gather the elements that uniquely identify the target object */ + CORBA::ORBid_var orb_id = ri->orb_id (); + CORBA::OctetSeq_var adapter_id = ri->adapter_id (); + CORBA::OctetSeq_var object_id = ri->object_id (); + + CORBA::String_var operation_name = ri->operation (); + + CORBA::Boolean it_should_happen = false; + it_should_happen = ad->access_allowed_ex (orb_id.in (), + adapter_id.in (), + object_id.in (), + cred_list, + operation_name.in()); + if (TAO_debug_level >= 3) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) SL2::access_allowed_ex returned %s\n", + it_should_happen ? "true" : "false")); + + if (! it_should_happen) + throw CORBA::NO_PERMISSION (); } -#endif /* SSLIOP_DEBUG_PEER_CERTIFICATE */ -} - - -void -TAO::SSLIOP::Server_Invocation_Interceptor::receive_request ( - PortableInterceptor::ServerRequestInfo_ptr /* ri */) -{ } void diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.h b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.h index af09c09b702..9375c18ac2d 100644 --- a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.h +++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.h @@ -22,8 +22,11 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "orbsvcs/SSLIOPC.h" +#include "orbsvcs/SecurityLevel2C.h" #include "tao/PortableInterceptorC.h" +#include "tao/PI/ORBInitInfo.h" #include "tao/PI_Server/PI_Server.h" +#include "tao/PortableServer/PS_CurrentC.h" #include "tao/LocalObject.h" // This is to remove "inherits via dominance" warnings from MSVC. @@ -55,9 +58,16 @@ namespace TAO { public: - /// Constructor. - Server_Invocation_Interceptor (::SSLIOP::Current_ptr current, - ::Security::QOP qop); + /*! + \brief Constructor. + \param info reference to the ORBInitInfo object so that + the interceptor can get access to initial references, etc. + \param default_qop the default Quality of Protection + \param tss_slot the TSS slot used by the various security features. + */ + Server_Invocation_Interceptor (PortableInterceptor::ORBInitInfo_ptr info, + ::Security::QOP default_qop, + size_t tss_slot); /** * @name PortableInterceptor::ServerRequestInterceptor Methods @@ -113,9 +123,15 @@ namespace TAO /// Reference to the current SSLIOP execution context. ::SSLIOP::Current_var ssliop_current_; + /// Reference to the POA current + PortableServer::Current_var poa_current_; + /// The default quality-of-protection settings in use. ::Security::QOP qop_; + /// SecurityLevel2 security manager reference + SecurityLevel2::SecurityManager_var sec2manager_; + SecurityLevel2::Current_var sec2_current_; }; } // End SSLIOP namespace. diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_ORBInitializer.cpp b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_ORBInitializer.cpp index c5d7846cb29..d0e0e91d04e 100644 --- a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_ORBInitializer.cpp +++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_ORBInitializer.cpp @@ -84,34 +84,14 @@ TAO::SSLIOP::ORBInitializer::post_init ( // object is registered for each ORB in this ORBInitializer's // pre_init() method. - CORBA::Object_var obj = - info->resolve_initial_references ("SSLIOPCurrent"); - - SSLIOP::Current_var ssliop_current = - SSLIOP::Current::_narrow (obj.in ()); - - if (!CORBA::is_nil (ssliop_current.in ())) - { - TAO::SSLIOP::Current *tao_current = - dynamic_cast<TAO::SSLIOP::Current *> (ssliop_current.in ()); - - if (tao_current != 0) - { - size_t const slot = this->get_tss_slot_id (info); - - tao_current->tss_slot (slot); - } - else - throw CORBA::INTERNAL (); - } - // Create the SSLIOP secure invocation server request interceptor. PortableInterceptor::ServerRequestInterceptor_ptr si = PortableInterceptor::ServerRequestInterceptor::_nil (); ACE_NEW_THROW_EX (si, - TAO::SSLIOP::Server_Invocation_Interceptor ( - ssliop_current.in (), - this->qop_), + TAO::SSLIOP::Server_Invocation_Interceptor + (info, + this->qop_, + this->get_tss_slot_id (info)), CORBA::NO_MEMORY ( CORBA::SystemException::_tao_minor_code ( TAO::VMCID, @@ -156,7 +136,8 @@ TAO::SSLIOP::ORBInitializer::post_init ( // Register the SSLIOP-specific vault with the // PrincipalAuthenticator. - obj = info->resolve_initial_references ("SecurityLevel3:SecurityManager"); + CORBA::Object_var obj = + info->resolve_initial_references ("SecurityLevel3:SecurityManager"); SecurityLevel3::SecurityManager_var manager = SecurityLevel3::SecurityManager::_narrow (obj.in ()); diff --git a/TAO/orbsvcs/orbsvcs/Security/SL2_SecurityManager.cpp b/TAO/orbsvcs/orbsvcs/Security/SL2_SecurityManager.cpp new file mode 100644 index 00000000000..8e7b22c66d1 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Security/SL2_SecurityManager.cpp @@ -0,0 +1,325 @@ +// $Id$ + +#include "orbsvcs/Security/SL2_SecurityManager.h" + +#include "tao/ORB_Constants.h" +#include "ace/Functor.h" +#include "tao/Object_KeyC.h" +#include "tao/PortableServer/Root_POA.h" +#include "tao/PortableServer/Object_Adapter.h" +#include "tao/PortableServer/Creation_Time.h" + +ACE_RCSID (Security, + SL2_SecurityManager, + "$Id$") + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO::Security::SecurityManager::SecurityManager (/* unknown */) + : principal_authenticator_ (SecurityLevel2::PrincipalAuthenticator::_nil ()) +{ + // this needs to change to access decision + SecurityLevel2::AccessDecision_ptr ad; + ACE_NEW_THROW_EX (ad, + TAO::Security::AccessDecision, + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + ENOMEM), + CORBA::COMPLETED_NO)); + + this->access_decision_ = ad; +} + +TAO::Security::SecurityManager::~SecurityManager (void) +{ +} + +Security::MechandOptionsList* +TAO::Security::SecurityManager::supported_mechanisms () +{ + throw CORBA::NO_IMPLEMENT (); +} + +SecurityLevel2::CredentialsList* +TAO::Security::SecurityManager::own_credentials () +{ + throw CORBA::NO_IMPLEMENT (); +} + +SecurityLevel2::RequiredRights_ptr +TAO::Security::SecurityManager::required_rights_object () +{ + throw CORBA::NO_IMPLEMENT (); +} + +SecurityLevel2::PrincipalAuthenticator_ptr +TAO::Security::SecurityManager::principal_authenticator () +{ + return SecurityLevel2::PrincipalAuthenticator::_duplicate + (this->principal_authenticator_.in () ); +} + +SecurityLevel2::AccessDecision_ptr +TAO::Security::SecurityManager::access_decision () +{ + return SecurityLevel2::AccessDecision::_duplicate (this->access_decision_.in () ); +} + +SecurityLevel2::AuditDecision_ptr +TAO::Security::SecurityManager::audit_decision () +{ + throw CORBA::NO_IMPLEMENT (); +} + +SecurityLevel2::TargetCredentials_ptr +TAO::Security::SecurityManager::get_target_credentials (CORBA::Object_ptr /*o*/) +{ + throw CORBA::NO_IMPLEMENT (); +} + +void +TAO::Security::SecurityManager::remove_own_credentials + (SecurityLevel2::Credentials_ptr /*creds*/) +{ + throw CORBA::NO_IMPLEMENT (); +} + +CORBA::Policy_ptr +TAO::Security::SecurityManager::get_security_policy +(CORBA::PolicyType /*policy_type */) +{ + throw CORBA::NO_IMPLEMENT (); +} + +/* + * AccessDecision stuff below here + */ + +bool +TAO::Security::AccessDecision::ReferenceKeyType::operator== + (const ReferenceKeyType& other) const +{ + ::CORBA::ULong olen = this->oid_->length(); + ::CORBA::ULong alen = this->adapter_id_->length(); + + if (olen == other.oid_->length() && + alen == other.adapter_id_->length()) + return (ACE_OS::memcmp (this->oid_->get_buffer(), + other.oid_->get_buffer(),olen) == 0 && + ACE_OS::memcmp (this->adapter_id_->get_buffer(), + other.adapter_id_->get_buffer(),alen) == 0 && + ACE_OS_String::strcmp (this->orbid_.in(), other.orbid_.in()) == 0); + return false; +} + +CORBA::ULong +TAO::Security::AccessDecision::ReferenceKeyType::hash () const +{ + return 0; +} + +TAO::Security::AccessDecision::ReferenceKeyType::operator const char* () const +{ + return "<hardcoded refkey>"; +} + +TAO::Security::AccessDecision::AccessDecision () + : default_allowance_decision_ (false) +{ +} + +TAO::Security::AccessDecision::~AccessDecision () +{ +} + +TAO::Security::AccessDecision::OBJECT_KEY +TAO::Security::AccessDecision::map_key_from_objref (CORBA::Object_ptr /*obj */) +{ + ACE_ERROR ((LM_ERROR,"map_key_from_objref is currently not implemented\n")); + throw CORBA::NO_IMPLEMENT(); + + OBJECT_KEY key; + return key; +} + +CORBA::Boolean +TAO::Security::AccessDecision::access_allowed_i (OBJECT_KEY &key, + const char *operation_name) +{ + // LOCK THE MAP! + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->map_lock_, + this->default_allowance_decision_); + + ACE_Hash<OBJECT_KEY> hash; + + // Look up the target in access_map_; if there, return the value, + // otherwise return the default value. + CORBA::Boolean access_decision; + if (this->access_map_.find (key, access_decision) == -1) + { + // Couldn't find the IOR in the map, so we use the default + access_decision = this->default_allowance_decision_; + if (TAO_debug_level >= 3) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) SL2_AccessDecision::access_decision(%x,%s)" + " NOT FOUND using default %d\n", + hash.operator()(key), + operation_name, access_decision)); + } + else if (TAO_debug_level >= 3) + { + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) SL2_AccessDecision::access_decision(%x,%s)" + " found with decision %d\n", + hash.operator()(key), + operation_name, access_decision)); + } + + // For now we just return the default. + return access_decision; + +} + +CORBA::Boolean +TAO::Security::AccessDecision::access_allowed_ex ( + const char * orb_id, + const ::CORBA::OctetSeq & adapter_id, + const ::CORBA::OctetSeq & object_id, + const ::SecurityLevel2::CredentialsList & /*cred_list */, + const char * operation_name) +{ + OBJECT_KEY key; + key.orbid_ = orb_id; + key.adapter_id_ = adapter_id; + key.oid_ = object_id; + + return this->access_allowed_i (key, operation_name); +} + +CORBA::Boolean +TAO::Security::AccessDecision::access_allowed + (const ::SecurityLevel2::CredentialsList & /*cred_list */, + ::CORBA::Object_ptr target, + const char * operation_name, + const char * /*target_interface_name */) +{ + // @@ I still don't know what we do with the cred_list in here... + // Do we inspect it? + + // Turn the target into what we'll use as a key into the map. + OBJECT_KEY key = this->map_key_from_objref (target); + return this->access_allowed_i (key, operation_name); +} + +void +TAO::Security::AccessDecision::add_object + (const char * orb_id, + const ::CORBA::OctetSeq & adapter_id, + const ::CORBA::OctetSeq & object_id, + CORBA::Boolean allow_insecure_access) +{ + // make a key from 'obj' + OBJECT_KEY key; + key.orbid_ = orb_id; + key.adapter_id_ = adapter_id; + key.oid_ = object_id; + + // bind it into the access_map_, replacing anything that's there. + // LOCK THE MAP! + ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->map_lock_); + + ACE_Hash<OBJECT_KEY> hash; + + // Since we want to replace any existing entry in the map, we just + // use rebind. + errno = 0; // Not sure if this gets set if rebind fails...it only + // appears to fail when an allocation thru the allocator's + // malloc() fails. Depending on the malloc() implementation, + // errno could get set OR an exception thrown. + int ret = this->access_map_.rebind (key, allow_insecure_access); + if (ret == -1) + { + // rebind shouldn't fail under normal circumstances + if (TAO_debug_level > 1) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t): SL2_AccessDecision::add_object(%x,%d) " + "unexpectedly failed (errno=%d)\n", + hash.operator()(key), + allow_insecure_access, + errno)); + throw + CORBA::NO_MEMORY(CORBA::SystemException::_tao_minor_code (TAO::VMCID, + errno), + CORBA::COMPLETED_NO); + } + else + { + if (TAO_debug_level >= 3) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t): SL2_AccessDecision::add_object(%x,%d) okay\n", + hash.operator()(key), + allow_insecure_access)); + } +} + +void +TAO::Security::AccessDecision::remove_object + (const char * orb_id, + const ::CORBA::OctetSeq & adapter_id, + const ::CORBA::OctetSeq & object_id) +{ + OBJECT_KEY key; + key.orbid_ = orb_id; + key.adapter_id_ = adapter_id; + key.oid_ = object_id; + + ACE_Hash<OBJECT_KEY> hash; + + // unbind it from access_map_, no matter if it's not in there... + // LOCK THE MAP! + ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->map_lock_); + + errno = 0; + int ret = this->access_map_.unbind (key); + if (ret == -1) + { + if (errno == ENOENT) + { + // ignore b/c we don't care...maybe log a debug message for info + if (TAO_debug_level >= 3) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t): SL2_AccessDecision::remove_object(%x) " + "object not found in access map\n", + hash.operator()(key))); + } + else + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t): SL2_AccessDecision::remove_object(%x) " + " unexpected error during unbind from map (errno=%d\n)", + hash.operator()(key), + errno)); + throw + CORBA::UNKNOWN (CORBA::SystemException::_tao_minor_code (TAO::VMCID, + errno), + CORBA::COMPLETED_NO); + } + } +} + +CORBA::Boolean +TAO::Security::AccessDecision::default_decision (void) +{ + return this->default_allowance_decision_; +} + +void +TAO::Security::AccessDecision::default_decision (CORBA::Boolean d) +{ + this->default_allowance_decision_ = d; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Security/SL2_SecurityManager.h b/TAO/orbsvcs/orbsvcs/Security/SL2_SecurityManager.h new file mode 100644 index 00000000000..32da7a31219 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Security/SL2_SecurityManager.h @@ -0,0 +1,226 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file SL2_SecurityManager.h + * + * $Id$ + * + * @author Chris Cleeland <cleeland@ociweb.com> + */ +//============================================================================= + + +#ifndef TAO_SL2_SECURITY_MANAGER_H +#define TAO_SL2_SECURITY_MANAGER_H + +#include /**/ "ace/pre.h" +#include "orbsvcs/Security/security_export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/SecurityC.h" +#include "orbsvcs/SecurityLevel2C.h" + +#include "tao/LocalObject.h" +#include "tao/PortableServer/PS_ForwardC.h" + +#include "ace/Hash_Map_Manager_T.h" +#include "ace/Null_Mutex.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4250) +#endif /* _MSC_VER */ + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + // would prefer SL2, but all the other SL2 stuff is in the Security namespace + namespace Security + { + // This should move out of here probably, but it's easier to stick it + // here for the moment...(CJC) + /** + * @class AccessDecision + * + * @brief + */ + class AccessDecision + : public virtual TAO::SL2::AccessDecision, + public virtual TAO_Local_RefCounted_Object + { + public: + /*! Constructor */ + AccessDecision (/* not yet known */); + ~AccessDecision (void); + + virtual ::CORBA::Boolean access_allowed ( + const ::SecurityLevel2::CredentialsList & cred_list, + ::CORBA::Object_ptr target, + const char * operation_name, + const char * target_interface_name + ); + + virtual ::CORBA::Boolean access_allowed_ex ( + const char * orb_id, + const ::CORBA::OctetSeq & adapter_id, + const ::CORBA::OctetSeq & object_id, + const ::SecurityLevel2::CredentialsList & cred_list, + const char * operation_name); + + virtual ::CORBA::Boolean default_decision (void); + virtual void default_decision (::CORBA::Boolean d); + + virtual void add_object (const char * orbid, + const ::CORBA::OctetSeq & adapter_id, + const ::CORBA::OctetSeq & object_id, + ::CORBA::Boolean allow_insecure_access); + + virtual void remove_object (const char * orbid, + const ::CORBA::OctetSeq & adapter_id, + const ::CORBA::OctetSeq & object_id); + + private: + /*! + * This is the default value that's returned from access_allowed() + * when the access table doesn't contain an entry for the reference. + */ + ::CORBA::Boolean default_allowance_decision_; + + /*! + * Map containing references and their designated insecure access. + */ + // What sorts of maps are available in ACE? We'll be mapping + // an object reference to a boolean, basically. Looks like for + // now we'll map a stringified IOR to the boolean, and provide some + // (for now) simple keys and functions for comparing them. + // + // Locking on this needs to be exclusive to add_object, + // remove_object, and access_allowed. I think that the lock on the + // map itself will be sufficient, but we'll model this after the + // Active Object map in the POA...so whatever way that goes, so, too, + // will this. + struct ReferenceKeyType + { + PortableServer::ObjectId_var oid_; + CORBA::OctetSeq_var adapter_id_; + CORBA::String_var orbid_; + + // operations/methods necessary for functors in HashMap; might + // need to add operator< if we decide to use an RB_Tree + bool operator== (const ReferenceKeyType& other) const; + CORBA::ULong hash() const; + + // operator kind of like a "toString()" for debug statements + operator const char * () const; + }; + typedef ReferenceKeyType OBJECT_KEY; + // This is typedef'd because we might try to do something fancier + // where, rather than having just a string as the key, we have a + // structure and the structure precomputes some of the information + // for the actual key. Thus, we could then customize the hash and + // comparison functors so that they use the precomputed information + // rather than computing it each time. For now, though, I want to + // make this easy to get things working. + typedef ACE_Hash_Map_Manager_Ex<OBJECT_KEY, + CORBA::Boolean, // access_allowed? + ACE_Hash<OBJECT_KEY>, + ACE_Equal_To<OBJECT_KEY>, + ACE_Null_Mutex> // not sure this is right + ACCESS_MAP_TYPE; + + ACCESS_MAP_TYPE access_map_; + + // Lock for accessing the map. It may be possible to get away with + // just using a lock directly in the map, but I'm not sure, so I'll err + // conservatively. + TAO_SYNCH_MUTEX map_lock_; + + private: + /*! + * @brief Encapsulates a TAO-specific way to do object_to_string() without having an ORB reference handy. + * + * @note If OBJECT_KEY changes as described above, this should change + * so that it generates an OBJECT_KEY. + */ + OBJECT_KEY map_key_from_objref (CORBA::Object_ptr obj); + + // + // This is the private implementation that is common to both + // access_allowed and access_allowed_ex. + ::CORBA::Boolean access_allowed_i (OBJECT_KEY& key, + const char *operation_name); + + }; + + /** + * @class SecurityManager + * + * @brief + * + */ + class SecurityManager + : public virtual SecurityLevel2::SecurityManager, + public virtual TAO_Local_RefCounted_Object + { + public: + + /// Constructor + SecurityManager (/* not sure what's needed yet */); + + /** + * @name SecurityLevel2::SecurityManager Methods + * + * Methods required by the SecurityLevel2::SecurityManager + * interface. + */ + //@{ + virtual ::Security::MechandOptionsList* supported_mechanisms (); + virtual SecurityLevel2::CredentialsList* own_credentials (); + virtual SecurityLevel2::RequiredRights_ptr required_rights_object (); + virtual SecurityLevel2::PrincipalAuthenticator_ptr principal_authenticator (); + virtual SecurityLevel2::AccessDecision_ptr access_decision (); + virtual SecurityLevel2::AuditDecision_ptr audit_decision (); + virtual SecurityLevel2::TargetCredentials_ptr get_target_credentials (CORBA::Object_ptr o); + virtual void remove_own_credentials (SecurityLevel2::Credentials_ptr creds); + virtual CORBA::Policy_ptr get_security_policy (CORBA::PolicyType policy_type); + //@} + + protected: + + /// Destructor + /** + * Protected destructor to enforce proper memory management + * through the reference counting mechanism. + */ + virtual ~SecurityManager (void); + + private: + + /// The ORB-specific SecurityLevel2::PrincipalAuthenticator + /// reference. + // Except we're not going to have one of these right now + SecurityLevel2::PrincipalAuthenticator_var principal_authenticator_; + + // AccessDecision instance + SecurityLevel2::AccessDecision_var access_decision_; + }; + + } // End SL3 namespace +} // End TAO namespace + +TAO_END_VERSIONED_NAMESPACE_DECL + + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /* _MSC_VER */ + +#include /**/ "ace/post.h" + +#endif /* TAO_SL2_SECURITY_MANAGER_H */ diff --git a/TAO/orbsvcs/orbsvcs/Security/Security_ORBInitializer.cpp b/TAO/orbsvcs/orbsvcs/Security/Security_ORBInitializer.cpp index 970aff6e1dd..d6a665341a5 100644 --- a/TAO/orbsvcs/orbsvcs/Security/Security_ORBInitializer.cpp +++ b/TAO/orbsvcs/orbsvcs/Security/Security_ORBInitializer.cpp @@ -7,7 +7,10 @@ ACE_RCSID (Security, "$Id$") -// #include "Security_Current.h" +#if 1 +#include "orbsvcs/Security/Security_Current.h" +#include "orbsvcs/Security/SL2_SecurityManager.h" +#endif #include "orbsvcs/Security/SL3_SecurityCurrent.h" #include "orbsvcs/Security/SL3_CredentialsCurator.h" #include "orbsvcs/Security/SL3_SecurityManager.h" @@ -41,36 +44,57 @@ TAO::Security::ORBInitializer::pre_init ( throw CORBA::INTERNAL (); } -// // Reserve a TSS slot in the ORB core internal TSS resources for the -// // thread-specific portion of Security::Current. -// size_t old_tss_slot = tao_info->allocate_tss_slot_id (0 -//); + // Reserve a TSS slot in the ORB core internal TSS resources for the + // thread-specific portion of Security::Current. + size_t tss_slot = tao_info->allocate_tss_slot_id (0 /* no cleanup function */); -// CORBA::String_var orb_id = info->orb_id (); +#if 1 -// // Create the SecurityLevel2::Current object. -// SecurityLevel2::Current_ptr current = SecurityLevel2::Current::_nil (); -// ACE_NEW_THROW_EX (current, -// TAO_Security_Current (old_tss_slot, orb_id.in ()), -// CORBA::NO_MEMORY ( -// CORBA::SystemException::_tao_minor_code ( -// TAO::VMCID, -// ENOMEM), -// CORBA::COMPLETED_NO)); +#if 0 // why am I getting a BAD_OPERATION from no SSL context?! + CORBA::String_var orb_id = info->orb_id (); -// SecurityLevel2::Current_var security_current = current; + // Create the SecurityLevel2::Current object. + SecurityLevel2::Current_ptr current = SecurityLevel2::Current::_nil (); + ACE_NEW_THROW_EX (current, + TAO_Security_Current (tss_slot, orb_id.in ()), + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + ENOMEM), + CORBA::COMPLETED_NO)); -// // Register the SecurityLevel2::Current object reference with the -// // ORB. -// info->register_initial_reference ("SecurityCurrent", -// security_current.in () -//); + SecurityLevel2::Current_var security_current = current; - // Reserve a TSS slot in the ORB core internal TSS resources for the - // thread-specific portion of SecurityLevel3::SecurityCurrent - // object. - size_t tss_slot = tao_info->allocate_tss_slot_id (0); + // Register the SecurityLevel2::Current object reference with the + // ORB. + info->register_initial_reference ("SecurityCurrent", + security_current.in ()); +#endif + /* + * Instantiate and register the SecurityLevel2::SecurityManager + */ + SecurityLevel2::SecurityManager_ptr manager2; + ACE_NEW_THROW_EX (manager2, + TAO::Security::SecurityManager (/*need args*/), + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + ENOMEM), + CORBA::COMPLETED_NO)); + + SecurityLevel2::SecurityManager_var security_manager2 = manager2; + + // Register the SecurityLevel2::SecurityManager object reference + // with the ORB. + info->register_initial_reference ("SecurityLevel2:SecurityManager", + security_manager2.in ()); + +#endif + // Rather than reserve another TSS slot in the ORB core internal TSS + // resources for the thread-specific portion of + // SecurityLevel3::SecurityCurrent object, we will re-use the slot + // allocated earlier. // Create the SecurityLevel3::Current object. SecurityLevel3::SecurityCurrent_ptr current3; diff --git a/TAO/orbsvcs/orbsvcs/SecurityLevel2.idl b/TAO/orbsvcs/orbsvcs/SecurityLevel2.idl index 4826c449ed4..c59afee58bc 100644 --- a/TAO/orbsvcs/orbsvcs/SecurityLevel2.idl +++ b/TAO/orbsvcs/orbsvcs/SecurityLevel2.idl @@ -189,7 +189,6 @@ module SecurityLevel2 { ); }; - // Policy interfaces to control bindings local interface QOPPolicy : CORBA::Policy { @@ -271,4 +270,38 @@ module SecurityLevel2 { #pragma prefix "" +module TAO { + module SL2 { + local interface AccessDecision : SecurityLevel2::AccessDecision + { + /* TAO-specific access_allowed that works around deficiencies in + the SecurityLevel2::AccessDecision::access_allowed() operation. */ + // Parameter object_id should be PortableInterceptor::ObjectId, but + // using that type would require including the PI_Forward.pidl file. + // By using the real type, we can avoid that dependency. + boolean access_allowed_ex (in ::CORBA::ORBid orb_id, + in ::CORBA::OctetSeq adapter_id, + in ::CORBA::OctetSeq object_id, + in ::SecurityLevel2::CredentialsList cred_list, + in ::CORBA::Identifier operation_name); + + /*! Default value returned when a reference is not in the list. */ + // Can't come up with a good name for this. + attribute boolean default_decision; + + /*! Establish whether a particular object can be accessed via insecure + means. */ + void add_object (in ::CORBA::ORBid orb_id, + in ::CORBA::OctetSeq adapter_id, + in ::CORBA::OctetSeq object_id, + in boolean allow_insecure_access); + void remove_object (in ::CORBA::ORBid orb_id, + in ::CORBA::OctetSeq adapter_id, + in ::CORBA::OctetSeq object_id); + + // Should there be some kind of "find" interface? + }; + }; +}; + #endif /* _SECURITY_LEVEL_2_IDL_ */ |