From eda9dda3aa909dfa8d505dd59ea86d5cc10d776a Mon Sep 17 00:00:00 2001 From: cantor Date: Tue, 6 Nov 2007 23:39:22 +0000 Subject: [PATCH] ECP message decoder. git-svn-id: https://svn.middleware.georgetown.edu/cpp-opensaml2/trunk@334 fb386ef7-a10c-0410-8ebf-fd3f8e989ab0 --- saml/Makefile.am | 3 +- saml/binding/impl/MessageDecoder.cpp | 2 + saml/saml.vcproj | 4 + saml/saml2/binding/impl/SAML2ECPDecoder.cpp | 137 ++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 saml/saml2/binding/impl/SAML2ECPDecoder.cpp diff --git a/saml/Makefile.am b/saml/Makefile.am index 9c6cab4..b8171ff 100644 --- a/saml/Makefile.am +++ b/saml/Makefile.am @@ -149,6 +149,8 @@ libsaml_la_SOURCES = \ saml2/binding/impl/SAML2ArtifactType0004.cpp \ saml2/binding/impl/SAML2ArtifactDecoder.cpp \ saml2/binding/impl/SAML2ArtifactEncoder.cpp \ + saml2/binding/impl/SAML2ECPDecoder.cpp \ + saml2/binding/impl/SAML2ECPEncoder.cpp \ saml2/binding/impl/SAML2MessageDecoder.cpp \ saml2/binding/impl/SAML2POSTDecoder.cpp \ saml2/binding/impl/SAML2POSTEncoder.cpp \ @@ -157,7 +159,6 @@ libsaml_la_SOURCES = \ saml2/binding/impl/SAML2RedirectEncoder.cpp \ saml2/binding/impl/SAML2SOAPDecoder.cpp \ saml2/binding/impl/SAML2SOAPEncoder.cpp \ - saml2/binding/impl/SAML2ECPEncoder.cpp \ saml2/binding/impl/SAML2SOAPClient.cpp \ saml2/profile/Assertion20Validator.cpp \ saml2/profile/BrowserSSOProfile20Validator.cpp \ diff --git a/saml/binding/impl/MessageDecoder.cpp b/saml/binding/impl/MessageDecoder.cpp index 3017680..070d90d 100644 --- a/saml/binding/impl/MessageDecoder.cpp +++ b/saml/binding/impl/MessageDecoder.cpp @@ -40,6 +40,7 @@ namespace opensaml { SAML_DLLLOCAL PluginManager< MessageDecoder,string,pair >::Factory SAML2POSTDecoderFactory; SAML_DLLLOCAL PluginManager< MessageDecoder,string,pair >::Factory SAML2RedirectDecoderFactory; SAML_DLLLOCAL PluginManager< MessageDecoder,string,pair >::Factory SAML2SOAPDecoderFactory; + SAML_DLLLOCAL PluginManager< MessageDecoder,string,pair >::Factory SAML2ECPDecoderFactory; }; }; @@ -54,4 +55,5 @@ void SAML_API opensaml::registerMessageDecoders() conf.MessageDecoderManager.registerFactory(samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN, saml2p::SAML2POSTDecoderFactory); conf.MessageDecoderManager.registerFactory(samlconstants::SAML20_BINDING_HTTP_REDIRECT, saml2p::SAML2RedirectDecoderFactory); conf.MessageDecoderManager.registerFactory(samlconstants::SAML20_BINDING_SOAP, saml2p::SAML2SOAPDecoderFactory); + conf.MessageDecoderManager.registerFactory(samlconstants::SAML20_BINDING_PAOS, saml2p::SAML2ECPDecoderFactory); } diff --git a/saml/saml.vcproj b/saml/saml.vcproj index 401ea47..efb495c 100644 --- a/saml/saml.vcproj +++ b/saml/saml.vcproj @@ -436,6 +436,10 @@ + + diff --git a/saml/saml2/binding/impl/SAML2ECPDecoder.cpp b/saml/saml2/binding/impl/SAML2ECPDecoder.cpp new file mode 100644 index 0000000..9d4e2fd --- /dev/null +++ b/saml/saml2/binding/impl/SAML2ECPDecoder.cpp @@ -0,0 +1,137 @@ +/* + * Copyright 2001-2007 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * SAML2ECPDecoder.cpp + * + * SAML 2.0 ECP profile message decoder + */ + +#include "internal.h" +#include "exceptions.h" +#include "saml2/binding/SAML2MessageDecoder.h" +#include "saml2/core/Protocols.h" + +#include +#include +#include +#include + +using namespace opensaml::saml2p; +using namespace opensaml; +using namespace soap11; +using namespace xmltooling::logging; +using namespace xmltooling; +using namespace std; + +namespace opensaml { + namespace saml2p { + class SAML_DLLLOCAL SAML2ECPDecoder : public SAML2MessageDecoder + { + public: + SAML2ECPDecoder() {} + virtual ~SAML2ECPDecoder() {} + + xmltooling::XMLObject* decode( + std::string& relayState, + const GenericRequest& genericRequest, + SecurityPolicy& policy + ) const; + }; + + MessageDecoder* SAML_DLLLOCAL SAML2ECPDecoderFactory(const pair& p) + { + return new SAML2ECPDecoder(); + } + }; +}; + +XMLObject* SAML2ECPDecoder::decode( + string& relayState, + const GenericRequest& genericRequest, + SecurityPolicy& policy + ) const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("decode"); +#endif + Category& log = Category::getInstance(SAML_LOGCAT".MessageDecoder.SAML2ECP"); + + log.debug("validating input"); + string s = genericRequest.getContentType(); + if (s.find("application/vnd.paos+xml") == string::npos) { + log.warn("ignoring incorrect content type (%s)", s.c_str() ? s.c_str() : "none"); + throw BindingException("Invalid content type for PAOS message."); + } + + const char* data = genericRequest.getRequestBody(); + if (!data) + throw BindingException("PAOS message had an empty request body."); + istringstream is(data); + + // Parse and bind the document into an XMLObject. + DOMDocument* doc = (policy.getValidating() ? XMLToolingConfig::getConfig().getValidatingParser() + : XMLToolingConfig::getConfig().getParser()).parse(is); + XercesJanitor janitor(doc); + auto_ptr xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true)); + janitor.release(); + + Envelope* env = dynamic_cast(xmlObject.get()); + if (!env) + throw BindingException("Decoded message was not a SOAP 1.1 Envelope."); + + if (!policy.getValidating()) + SchemaValidators.validate(env); + + Body* body = env->getBody(); + if (body && body->hasChildren()) { + Response* response = dynamic_cast(body->getUnknownXMLObjects().front()); + if (response) { + // Run through the policy at two layers. + extractMessageDetails(*env, genericRequest, samlconstants::SAML20P_NS, policy); + policy.evaluate(*env, &genericRequest); + policy.reset(true); + extractMessageDetails(*response, genericRequest, samlconstants::SAML20P_NS, policy); + policy.evaluate(*response, &genericRequest); + + // Check for RelayState header. + if (env->getHeader()) { + const vector& blocks = const_cast(env->getHeader())->getUnknownXMLObjects(); + for (vector::const_iterator h = blocks.begin(); h != blocks.end(); ++h) { + static const XMLCh RelayState[] = UNICODE_LITERAL_10(R,e,l,a,y,S,t,a,t,e); + if (XMLString::equals((*h)->getElementQName().getLocalPart(), RelayState) && + XMLString::equals((*h)->getElementQName().getNamespaceURI(), samlconstants::SAML20ECP_NS)) { + const ElementProxy* ep = dynamic_cast(*h); + if (ep) { + auto_ptr_char rs(ep->getTextContent()); + if (rs.get()) { + relayState = rs.get(); + break; + } + } + } + } + } + + xmlObject.release(); + body->detach(); // frees Envelope + response->detach(); // frees Body + return response; + } + } + + throw BindingException("SOAP Envelope did not contain a SAML Response."); +} -- 2.1.4