From a8f6dec243698e3a18b04762ebe3947ed0d246cb Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Thu, 9 Aug 2007 04:24:23 +0000 Subject: [PATCH] Sync up with policy API changes. Add ADFS message rule to fix collision with SAML 1.x rule. Skip policy step inside decoder. Fix WST element name. --- adfs/adfs.cpp | 127 +++++++++++++++++++++++++++++-------- shibsp/security/SecurityPolicy.cpp | 13 ++-- 2 files changed, 107 insertions(+), 33 deletions(-) diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp index cbbd56d..529e013 100644 --- a/adfs/adfs.cpp +++ b/adfs/adfs.cpp @@ -77,6 +77,42 @@ using namespace std; namespace { +#ifndef SHIBSP_LITE + class SHIBSP_DLLLOCAL ADFSDecoder : public MessageDecoder + { + auto_ptr_XMLCh m_ns; + public: + ADFSDecoder() : m_ns(WSTRUST_NS) {} + virtual ~ADFSDecoder() {} + + XMLObject* decode(string& relayState, const GenericRequest& genericRequest, SecurityPolicy& policy) const; + }; + + MessageDecoder* ADFSDecoderFactory(const pair& p) + { + return new ADFSDecoder(); + } + + class SHIBSP_DLLLOCAL ADFSMessageRule : public SecurityPolicyRule + { + public: + ADFSMessageRule(const DOMElement* e) : m_protocol(WSFED_NS) {} + virtual ~ADFSMessageRule() {} + + const char* getType() const { + return "ADFSMessage"; + } + void evaluate(const XMLObject& message, const GenericRequest* request, const XMLCh* protocol, SecurityPolicy& policy) const; + + auto_ptr_XMLCh m_protocol; + }; + + SecurityPolicyRule* ADFSMessageRuleFactory(const DOMElement* const & e) + { + return new ADFSMessageRule(e); + } +#endif + #if defined (_MSC_VER) #pragma warning( push ) #pragma warning( disable : 4250 ) @@ -129,7 +165,7 @@ namespace { ADFSConsumer(const DOMElement* e, const char* appId) : shibsp::AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".SSO.ADFS")) #ifndef SHIBSP_LITE - ,m_binding(WSFED_NS) + ,m_messageRule(e) #endif {} virtual ~ADFSConsumer() {} @@ -143,7 +179,7 @@ namespace { const PropertySet* settings, const XMLObject& xmlObject ) const; - auto_ptr_XMLCh m_binding; + ADFSMessageRule m_messageRule; #endif }; @@ -209,23 +245,6 @@ namespace { #pragma warning( pop ) #endif -#ifndef SHIBSP_LITE - class ADFSDecoder : public MessageDecoder - { - auto_ptr_XMLCh m_ns; - public: - ADFSDecoder() : m_ns(WSTRUST_NS) {} - virtual ~ADFSDecoder() {} - - XMLObject* decode(string& relayState, const GenericRequest& genericRequest, SecurityPolicy& policy) const; - }; - - MessageDecoder* ADFSDecoderFactory(const pair& p) - { - return new ADFSDecoder(); - } -#endif - SessionInitiator* ADFSSessionInitiatorFactory(const pair& p) { return new ADFSSessionInitiator(p.first, p.second); @@ -254,8 +273,9 @@ extern "C" int ADFS_EXPORTS xmltooling_extension_init(void*) conf.AssertionConsumerServiceManager.registerFactory(WSFED_NS, ADFSLogoutFactory); #ifndef SHIBSP_LITE SAMLConfig::getConfig().MessageDecoderManager.registerFactory(WSFED_NS, ADFSDecoderFactory); + SAMLConfig::getConfig().SecurityPolicyRuleManager.registerFactory("ADFSMessage", ADFSMessageRuleFactory); XMLObjectBuilder::registerBuilder(QName(WSTRUST_NS,"RequestedSecurityToken"), new AnyElementBuilder()); - XMLObjectBuilder::registerBuilder(QName(WSTRUST_NS,"RequestedSecurityTokenResponse"), new AnyElementBuilder()); + XMLObjectBuilder::registerBuilder(QName(WSTRUST_NS,"RequestSecurityTokenResponse"), new AnyElementBuilder()); #endif return 0; } @@ -270,6 +290,7 @@ extern "C" void ADFS_EXPORTS xmltooling_extension_term() conf.AssertionConsumerServiceManager.deregisterFactory(WSFED_NS); #ifndef SHIBSP_LITE SAMLConfig::getConfig().MessageDecoderManager.deregisterFactory(WSFED_NS); + SAMLConfig::getConfig().SecurityPolicyRuleManager.deregisterFactory("ADFSMessage"); #endif */ } @@ -489,12 +510,67 @@ XMLObject* ADFSDecoder::decode(string& relayState, const GenericRequest& generic if (!policy.getValidating()) SchemaValidators.validate(xmlObject.get()); - // Run through the policy. - policy.evaluate(*xmlObject.get(), &genericRequest); + // Skip policy step here, there's no security in the wrapper. + // policy.evaluate(*xmlObject.get(), &genericRequest); return xmlObject.release(); } +void ADFSMessageRule::evaluate(const XMLObject& message, const GenericRequest* request, const XMLCh* protocol, SecurityPolicy& policy) const +{ + Category& log=Category::getInstance(SHIBSP_LOGCAT".SecurityPolicyRule.ADFSMessage"); + + if (!XMLString::equals(protocol, m_protocol.get())) + return; + + const QName& q = message.getElementQName(); + if (!XMLString::equals(q.getNamespaceURI(), samlconstants::SAML1_NS) || + !XMLString::equals(q.getLocalPart(), saml1::Assertion::LOCAL_NAME)) + return; + + try { + const saml1::Assertion& token = dynamic_cast(message); + policy.setMessageID(token.getAssertionID()); + policy.setIssueInstant(token.getIssueInstantEpoch()); + + log.debug("extracting issuer from message"); + + policy.setIssuer(token.getIssuer()); + + if (log.isDebugEnabled()) { + auto_ptr_char iname(token.getIssuer()); + log.debug("message from (%s)", iname.get()); + } + + if (policy.getIssuerMetadata()) { + log.debug("metadata for issuer already set, leaving in place"); + return; + } + + if (policy.getMetadataProvider() && policy.getRole()) { + log.debug("searching metadata for message issuer..."); + const EntityDescriptor* entity = policy.getMetadataProvider()->getEntityDescriptor(token.getIssuer()); + if (!entity) { + auto_ptr_char temp(token.getIssuer()); + log.warn("no metadata found, can't establish identity of issuer (%s)", temp.get()); + return; + } + + log.debug("matched message issuer against metadata, searching for applicable role..."); + const RoleDescriptor* roledesc=entity->getRoleDescriptor(*policy.getRole(), m_protocol.get()); + if (!roledesc) { + log.warn("unable to find compatible role (%s) in metadata", policy.getRole()->toString().c_str()); + return; + } + policy.setIssuerMetadata(roledesc); + } + } + catch (bad_cast&) { + // Just trap it. + log.warn("caught a bad_cast while examining message"); + } +} + string ADFSConsumer::implementProtocol( const Application& application, const HTTPRequest& httpRequest, @@ -520,7 +596,8 @@ string ADFSConsumer::implementProtocol( // Run the policy over the assertion. Handles issuer consistency, replay, freshness, // and signature verification, assuming the relevant rules are configured. - policy.evaluate(*token); + policy.getRules().insert(policy.getRules().begin(), &m_messageRule); + policy.evaluate(*token, NULL, m_messageRule.m_protocol.get()); // If no security is in place now, we kick it. if (!policy.isSecure()) @@ -611,7 +688,7 @@ string ADFSConsumer::implementProtocol( resolveAttributes( application, issuerMetadata, - m_binding.get(), + m_messageRule.m_protocol.get(), nameid.get(), ssoStatement->getAuthenticationMethod(), NULL, @@ -635,7 +712,7 @@ string ADFSConsumer::implementProtocol( application, httpRequest.getRemoteAddr().c_str(), issuerMetadata, - m_binding.get(), + m_messageRule.m_protocol.get(), nameid.get(), ssoStatement->getAuthenticationInstant() ? ssoStatement->getAuthenticationInstant()->getRawData() : NULL, NULL, diff --git a/shibsp/security/SecurityPolicy.cpp b/shibsp/security/SecurityPolicy.cpp index ec9c28a..6e260d4 100644 --- a/shibsp/security/SecurityPolicy.cpp +++ b/shibsp/security/SecurityPolicy.cpp @@ -28,12 +28,9 @@ using namespace shibsp; SecurityPolicy::SecurityPolicy(const Application& application, const xmltooling::QName* role, bool validate) - : opensaml::SecurityPolicy( - application.getServiceProvider().getPolicyRules(application.getString("policyId").second), - application.getMetadataProvider(), - role, - application.getTrustEngine(), - validate), - m_application(application) -{ + : opensaml::SecurityPolicy(application.getMetadataProvider(), role, application.getTrustEngine(), validate), m_application(application) { + + const std::vector& rules = + application.getServiceProvider().getPolicyRules(application.getString("policyId").second); + getRules().assign(rules.begin(), rules.end()); } -- 2.1.4