diff options
author | Chris Cleeland <chris.cleeland@gmail.com> | 2007-04-03 19:37:44 +0000 |
---|---|---|
committer | Chris Cleeland <chris.cleeland@gmail.com> | 2007-04-03 19:37:44 +0000 |
commit | 781d35d7fb08201a8a23b0756c69bf00c0e3ee67 (patch) | |
tree | b9010cffc74a15f7d467223a28448a2397cf9b2d /TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp | |
parent | 6effa16ea8dfbb4a1aaefb7e1b9fab3ef356b5ab (diff) | |
download | ATCD-781d35d7fb08201a8a23b0756c69bf00c0e3ee67.tar.gz |
Committing changes thus far in preparation to migrate them to the newoci_mixed_security
oci_mixed_security_2 branch.
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp')
-rw-r--r-- | TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Invocation_Interceptor.cpp | 285 |
1 files changed, 264 insertions, 21 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 |