diff options
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/SSLIOP')
3 files changed, 289 insertions, 50 deletions
diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp index 5ce2d53c82c..57bedb1ed32 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,49 @@ 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? + } + + obj = info->resolve_initial_references ("POACurrent"); + this->poa_current_ = PortableServer::Current::_narrow (obj.in ()); } TAO::SSLIOP::Server_Invocation_Interceptor::~Server_Invocation_Interceptor ( @@ -30,6 +69,7 @@ TAO::SSLIOP::Server_Invocation_Interceptor::~Server_Invocation_Interceptor ( { } + char * TAO::SSLIOP::Server_Invocation_Interceptor::name () ACE_THROW_SPEC ((CORBA::SystemException)) @@ -46,10 +86,43 @@ TAO::SSLIOP::Server_Invocation_Interceptor::destroy () void TAO::SSLIOP::Server_Invocation_Interceptor::receive_request_service_contexts ( - PortableInterceptor::ServerRequestInfo_ptr /*ri*/) + PortableInterceptor::ServerRequestInfo_ptr /* ri */) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableInterceptor::ForwardRequest)) +{ +#if 1 + // This operation is where the old security implementation used to + // makes its simplistic decision whether to permit or deny, but with + // the introduction of more detailed checking, there's a need to + // have access to information that's not available until later in + // the PI flow. So, it's now all moved into receive_request(). + + + 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 + // (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) + throw CORBA::NO_PERMISSION (); +#endif +} + + +void +TAO::SSLIOP::Server_Invocation_Interceptor::receive_request ( + PortableInterceptor::ServerRequestInfo_ptr ri) ACE_THROW_SPEC ((CORBA::SystemException, PortableInterceptor::ForwardRequest)) { +#if 0 // 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. @@ -59,14 +132,192 @@ TAO::SSLIOP::Server_Invocation_Interceptor::receive_request_service_contexts ( // 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 1 + /* + // Of course, since we're implementing a SecurityManager, we can do + // this now! But we want to keep the default behavior, too... - if (no_ssl && this->qop_ != ::Security::SecQOPNoProtection) - throw CORBA::NO_PERMISSION (); + Q: It's also not clear how we're supposed to query the securitymanager + "for the current object's SecureInvocationPolicy". Maybe we need to + query the policies on the object itself? Maybe we can ask the + ServerRequestInfo via get_server_policy()? + + A: The spec says that "This operation returns the policy in effect + for this operation for the given policy type. The returned + CORBA::Policy object shall only be a policy whose type was + registered via register_policy_factory()", so that should give us + what we want. + */ + + SecurityLevel2::AccessDecision_var ad = + this->sec2manager_->access_decision (); + + + 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 + // (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) +#if 0 + throw CORBA::NO_PERMISSION (); + if ( ! CORBA:is_nil (ad.in ()) + && ri->get_server_policy(SecureInvocationPolicy) == SecTargetSecureInvocationPolicy) +#endif + { + /* + * 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 + + /* Get the target object */ + CORBA::Object_var target = CORBA::Object::_nil (); + +#if 0 // we want to use the POACurrent::get_reference()! + // I suppose that we can derive this using server_id, adapter_id + // and object_id using id_to_reference. One problem is that, + // according to the spec, id_to_reference() can only be used + // when the POA in question has the RETAIN policy so this would + // be unavailable when the POA has NO_RETAIN. + try { + int no_args = 0; + CORBA::ORB_var orb = CORBA::ORB_init (no_args, 0, ri->orb_id()); + CORBA::Object_var obj = orb->resolve_initial_references ("RootPOA"); + PortableServer::POA_var rootpoa = + PortableServer::POA::_narrow (obj.in ()); + if (CORBA::is_nil (rootpoa.in ())) + // Probably not a good choice for exception, but we need to + // throw something. + throw PortableServer::POA::AdapterNonExistent(); + + // @@CJC Grrr...of course nothing is ever easy. What we'd really + // like to be able to do is something like... + // rootpoa->find_POA (ri->adapter_id (), false); // don't activate + // to get a reference to the POA indicated here. Sigh. CORBA 3.0 + // provides adapter_name(), so maybe I'll get lucky and that'll be + // available. Otherwise, I'm going to have to resort to ugliness + // and proprietary hacks to get this info, b/c adapter_id() + // returns an opaque octet sequence. + // + // The good news is that adapter_name() exists, but it doesn't + // return a name suitable for submission to find_POA(). Rather, + // it returns a string sequence. Exactly what's in that sequence + // we don't know, but I'll guess that it's supposed to be an in-order + // list of the poa path down to the poa that's hosting the target + // CORBA Object. So, if we look at the last element in the sequence + // we should get the name of the hosting POA. <fingers crossed> + PortableInterceptor::AdapterName_var poa_path = ri->adapter_name (); + size_t last_component_index = poa_path->length() - 1; + + const char* last_component = poa_path[last_component_index]; + PortableServer::POA_var poa = + rootpoa->find_POA (last_component, + false); // don't activate + + // Yow. Sometimes the C++ mapping mystifies me in its oddities. + // One would expect that, since the requestinfo has an ObjectId + // attribute, and the id_to_reference() operation takes an ObjectId + // as an "in" argument, that one could simply do + // target = poa->id_to_reference (ri->object_id()) + // Alas, 'tis not that simple. The mapping for a return value for + // an unbounded sequence is T*, and the mapping for an "in" is + // const T&, which means that we have to dereference the pointer. + // + // Damn, that's really ugly. But I'm glad that's off my chest. + target = poa->id_to_reference (*(ri->object_id ())); + } +#define quote(x) #x + catch (const PortableServer::POA::ObjectNotActive& e) { + // thrown by id_to_reference() + e._tao_print_exception ("ssliop_invocation_interceptor::receive_request @ " quote(__LINE__)); + } + catch (const PortableServer::POA::WrongPolicy& e) { + // thrown by id_to_reference() + e._tao_print_exception ("ssliop_invocation_interceptor::receive_request @ " quote(__LINE__)); + } + catch (const PortableServer::POA::AdapterNonExistent& e) { + // thrown by find_POA() + e._tao_print_exception ("yoyoyo ssliop_invocation_interceptor::receive_request @ " quote(__LINE__)); + } + catch (const CORBA::ORB::InvalidName& e) { + // thrown by resolve_initial_references() + e._tao_print_exception ("ssliop_invocation_interceptor::receive_request @ " quote(__LINE__)); + } +#else + target = this->poa_current_->get_reference (); +#endif + + char* operation_name = ri->operation (); + char* target_interface_name = ri->target_most_derived_interface(); // is this the repository ID? + + CORBA::Boolean it_should_happen = false; + if (ad) + it_should_happen = ad->access_allowed (cred_list, + target.in(), + operation_name, + target_interface_name); + else + it_should_happen = true; // if no access_decision, then let it all through + + if (! it_should_happen) + { + throw CORBA::NO_PERMISSION (); + } + } + else +#endif + { + // PREVIOUS DEFAULT BEHAVIOR + + 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 + // (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) + throw CORBA::NO_PERMISSION (); + } #if defined(DEBUG_PEER_CERTIFICATES) try @@ -126,15 +377,7 @@ TAO::SSLIOP::Server_Invocation_Interceptor::receive_request_service_contexts ( throw CORBA::NO_PERMISSION (); } #endif /* DEBUG_PEER_CERTIFICATES */ -} - - -void -TAO::SSLIOP::Server_Invocation_Interceptor::receive_request ( - PortableInterceptor::ServerRequestInfo_ptr /* ri */) - ACE_THROW_SPEC ((CORBA::SystemException, - PortableInterceptor::ForwardRequest)) -{ +#endif } void diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.h b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.h index e382a2042a2..2ae6d0bc9a7 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 @@ -124,9 +134,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 102fbeb2246..faccc92f0f1 100644 --- a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_ORBInitializer.cpp +++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_ORBInitializer.cpp @@ -88,35 +88,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) - { - const size_t 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, @@ -161,7 +140,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 ()); |