From: Scott Cantor Date: Sun, 12 Nov 2006 00:07:53 +0000 (+0000) Subject: SOAP decoders. X-Git-Tag: 2.0-alpha1~146 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-opensaml.git;a=commitdiff_plain;h=14057fc9aa90e32cfcb43947397d963c6563fa91 SOAP decoders. --- diff --git a/saml/Makefile.am b/saml/Makefile.am index f03cc16..70fe4a7 100644 --- a/saml/Makefile.am +++ b/saml/Makefile.am @@ -76,7 +76,8 @@ saml1bindinclude_HEADERS = \ saml1/binding/SAML1ArtifactDecoder.h \ saml1/binding/SAML1ArtifactEncoder.h \ saml1/binding/SAML1POSTDecoder.h \ - saml1/binding/SAML1POSTEncoder.h + saml1/binding/SAML1POSTEncoder.h \ + saml1/binding/SAML1SOAPDecoder.h saml2coreinclude_HEADERS = \ saml2/core/Assertions.h \ @@ -91,7 +92,8 @@ saml2bindinclude_HEADERS = \ saml2/binding/SAML2POSTEncoder.h \ saml2/binding/SAML2Redirect.h \ saml2/binding/SAML2RedirectDecoder.h \ - saml2/binding/SAML2RedirectEncoder.h + saml2/binding/SAML2RedirectEncoder.h \ + saml2/binding/SAML2SOAPDecoder.h saml2mdinclude_HEADERS = \ saml2/metadata/AbstractMetadataProvider.h \ @@ -126,6 +128,7 @@ libsaml_la_SOURCES = \ saml1/binding/impl/SAML1ArtifactEncoder.cpp \ saml1/binding/impl/SAML1POSTDecoder.cpp \ saml1/binding/impl/SAML1POSTEncoder.cpp \ + saml1/binding/impl/SAML1SOAPDecoder.cpp \ saml2/core/impl/Assertions20Impl.cpp \ saml2/core/impl/Assertions20SchemaValidators.cpp \ saml2/core/impl/Protocols20Impl.cpp \ @@ -149,6 +152,7 @@ libsaml_la_SOURCES = \ saml2/binding/impl/SAML2Redirect.cpp \ saml2/binding/impl/SAML2RedirectDecoder.cpp \ saml2/binding/impl/SAML2RedirectEncoder.cpp \ + saml2/binding/impl/SAML2SOAPDecoder.cpp \ encryption/EncryptedKeyResolver.cpp \ security/impl/TrustEngine.cpp \ security/impl/AbstractPKIXTrustEngine.cpp \ diff --git a/saml/saml.vcproj b/saml/saml.vcproj index 2a461bf..f8190eb 100644 --- a/saml/saml.vcproj +++ b/saml/saml.vcproj @@ -253,6 +253,10 @@ > + + @@ -428,6 +432,10 @@ RelativePath=".\saml2\binding\impl\SAML2RedirectEncoder.cpp" > + + @@ -628,6 +636,10 @@ > + + @@ -735,6 +747,10 @@ RelativePath=".\saml2\binding\SAML2RedirectEncoder.h" > + + +#include + + +namespace opensaml { + namespace saml1p { + + /** + * SAML 1.x SOAP binding message decoder + */ + class SAML_API SAML1SOAPDecoder : public MessageDecoder + { + public: + SAML1SOAPDecoder(const DOMElement* e); + virtual ~SAML1SOAPDecoder() {} + + Request* decode( + std::string& relayState, + const GenericRequest& genericRequest, + SecurityPolicy& policy + ) const; + }; + + }; +}; diff --git a/saml/saml1/binding/impl/SAML1SOAPDecoder.cpp b/saml/saml1/binding/impl/SAML1SOAPDecoder.cpp new file mode 100644 index 0000000..6df390b --- /dev/null +++ b/saml/saml1/binding/impl/SAML1SOAPDecoder.cpp @@ -0,0 +1,104 @@ +/* + * Copyright 2001-2006 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. + */ + +/** + * SAML1SOAPDecoder.cpp + * + * SAML 1.x SOAP binding message decoder + */ + +#include "internal.h" +#include "exceptions.h" +#include "saml1/binding/SAML1SOAPDecoder.h" + +#include +#include +#include +#include + +using namespace opensaml::saml1p; +using namespace opensaml; +using namespace soap11; +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +namespace opensaml { + namespace saml1p { + MessageDecoder* SAML_DLLLOCAL SAML1SOAPDecoderFactory(const DOMElement* const & e) + { + return new SAML1SOAPDecoder(e); + } + }; +}; + +SAML1SOAPDecoder::SAML1SOAPDecoder(const DOMElement* e) {} + +Request* SAML1SOAPDecoder::decode( + string& relayState, + const GenericRequest& genericRequest, + SecurityPolicy& policy + ) const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("decode"); +#endif + Category& log = Category::getInstance(SAML_LOGCAT".MessageDecoder.SAML1SOAP"); + + log.debug("validating input"); + string s = genericRequest.getContentType(); + if (s != "text/xml") { + log.warn("ignoring incorrect Content Type (%s)", s.c_str() ? s.c_str() : "none"); + return NULL; + } + + const char* data = genericRequest.getRequestBody(); + if (!data) { + log.warn("empty request body"); + return NULL; + } + istringstream is(data); + + // Parse and bind the document into an XMLObject. + DOMDocument* doc = (m_validate ? 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 (!m_validate) + SchemaValidators.validate(env); + + Body* body = env->getBody(); + if (body && body->hasChildren()) { + Request* request = dynamic_cast(body->getXMLObjects().front()); + if (request) { + // Run through the policy at two layers. + policy.evaluate(genericRequest, *env); + policy.evaluate(genericRequest, *request); + xmlObject.release(); + body->detach(); // frees Envelope + request->detach(); // frees Body + return request; + } + } + + throw BindingException("SOAP Envelope did not contain a SAML Request."); +} diff --git a/saml/saml2/binding/SAML2SOAPDecoder.h b/saml/saml2/binding/SAML2SOAPDecoder.h new file mode 100644 index 0000000..5043852 --- /dev/null +++ b/saml/saml2/binding/SAML2SOAPDecoder.h @@ -0,0 +1,47 @@ +/* + * Copyright 2001-2006 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. + */ + +/** + * @file saml/saml2/binding/SAML2SOAPDecoder.h + * + * SAML 2.0 SOAP binding message decoder + */ + +#include +#include + + +namespace opensaml { + namespace saml2p { + + /** + * SAML 2.0 SOAP binding message decoder + */ + class SAML_API SAML2SOAPDecoder : public MessageDecoder + { + public: + SAML2SOAPDecoder(const DOMElement* e); + virtual ~SAML2SOAPDecoder() {} + + RequestAbstractType* decode( + std::string& relayState, + const GenericRequest& genericRequest, + SecurityPolicy& policy + ) const; + }; + + }; +}; diff --git a/saml/saml2/binding/impl/SAML2SOAPDecoder.cpp b/saml/saml2/binding/impl/SAML2SOAPDecoder.cpp new file mode 100644 index 0000000..3a100a6 --- /dev/null +++ b/saml/saml2/binding/impl/SAML2SOAPDecoder.cpp @@ -0,0 +1,104 @@ +/* + * Copyright 2001-2006 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. + */ + +/** + * SAML2SOAPDecoder.cpp + * + * SAML 2.0 SOAP binding message decoder + */ + +#include "internal.h" +#include "exceptions.h" +#include "saml2/binding/SAML2SOAPDecoder.h" + +#include +#include +#include +#include + +using namespace opensaml::saml2p; +using namespace opensaml; +using namespace soap11; +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +namespace opensaml { + namespace saml2p { + MessageDecoder* SAML_DLLLOCAL SAML2SOAPDecoderFactory(const DOMElement* const & e) + { + return new SAML2SOAPDecoder(e); + } + }; +}; + +SAML2SOAPDecoder::SAML2SOAPDecoder(const DOMElement* e) {} + +RequestAbstractType* SAML2SOAPDecoder::decode( + string& relayState, + const GenericRequest& genericRequest, + SecurityPolicy& policy + ) const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("decode"); +#endif + Category& log = Category::getInstance(SAML_LOGCAT".MessageDecoder.SAML2SOAP"); + + log.debug("validating input"); + string s = genericRequest.getContentType(); + if (s != "text/xml") { + log.warn("ignoring incorrect Content Type (%s)", s.c_str() ? s.c_str() : "none"); + return NULL; + } + + const char* data = genericRequest.getRequestBody(); + if (!data) { + log.warn("empty request body"); + return NULL; + } + istringstream is(data); + + // Parse and bind the document into an XMLObject. + DOMDocument* doc = (m_validate ? 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 (!m_validate) + SchemaValidators.validate(env); + + Body* body = env->getBody(); + if (body && body->hasChildren()) { + RequestAbstractType* request = dynamic_cast(body->getXMLObjects().front()); + if (request) { + // Run through the policy at two layers. + policy.evaluate(genericRequest, *env); + policy.evaluate(genericRequest, *request); + xmlObject.release(); + body->detach(); // frees Envelope + request->detach(); // frees Body + return request; + } + } + + throw BindingException("SOAP Envelope did not contain a SAML Request."); +} diff --git a/saml/util/SAMLConstants.cpp b/saml/util/SAMLConstants.cpp index 8bf84ce..1069ea4 100644 --- a/saml/util/SAMLConstants.cpp +++ b/saml/util/SAMLConstants.cpp @@ -177,10 +177,14 @@ const XMLCh samlconstants::SAML20P_THIRDPARTY_EXT_NS[] = // urn:oasis:names:tc:S const XMLCh samlconstants::SAML20P_THIRDPARTY_EXT_PREFIX[] = UNICODE_LITERAL_6(t,h,r,p,t,y); +const char samlconstants::SAML1_BINDING_SOAP[] = "urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"; + const char samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT[] = "urn:oasis:names:tc:SAML:1.0:profiles:artifact-01"; const char samlconstants::SAML1_PROFILE_BROWSER_POST[] = "urn:oasis:names:tc:SAML:1.0:profiles:browser-post"; +const char samlconstants::SAML20_BINDING_SOAP[] = "urn:oasis:names:tc:SAML:2.0:bindings:SOAP"; + const char samlconstants::SAML20_BINDING_HTTP_ARTIFACT[] = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"; const char samlconstants::SAML20_BINDING_HTTP_POST[] = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"; diff --git a/saml/util/SAMLConstants.h b/saml/util/SAMLConstants.h index 17de531..edb7207 100644 --- a/saml/util/SAMLConstants.h +++ b/saml/util/SAMLConstants.h @@ -123,12 +123,18 @@ namespace samlconstants { /** SAML Third-Party Request Protocol Extension QName prefix ("query") */ extern SAML_API const XMLCh SAML20P_THIRDPARTY_EXT_PREFIX[]; - /** SAML 1.x Browser Artifact profile ("urn:oasis:names:tc:SAML:1.0:profiles:artifact-01")*/ + /** SAML 1.x SOAP binding ("urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding") */ + extern SAML_API const char SAML1_BINDING_SOAP[]; + + /** SAML 1.x Browser Artifact profile ("urn:oasis:names:tc:SAML:1.0:profiles:artifact-01") */ extern SAML_API const char SAML1_PROFILE_BROWSER_ARTIFACT[]; /** SAML 1.x Browser POST profile ("urn:oasis:names:tc:SAML:1.0:profiles:browser-post") */ extern SAML_API const char SAML1_PROFILE_BROWSER_POST[]; + /** SAML 2.0 SOAP binding ("urn:oasis:names:tc:SAML:2.0:bindings:SOAP") */ + extern SAML_API const char SAML20_BINDING_SOAP[]; + /** SAML 2.0 HTTP-Artifact binding ("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact") */ extern SAML_API const char SAML20_BINDING_HTTP_ARTIFACT[];