<pathentry kind="src" path="saml/signature"/>\r
<pathentry kind="src" path="saml/util"/>\r
<pathentry kind="src" path="samltest/signature"/>\r
-<pathentry excluding="saml1/core/impl/|signature/|saml2/core/impl/|saml2/metadata/|security/" kind="src" path="samltest"/>\r
+<pathentry excluding="saml1/core/impl/|signature/|saml2/core/impl/|saml2/metadata/|security/|saml1/binding/" kind="src" path="samltest"/>\r
<pathentry kind="src" path="samltest/saml1/core/impl"/>\r
<pathentry kind="src" path="samltest/saml2/core/impl"/>\r
<pathentry kind="src" path="samltest/saml2/metadata"/>\r
<pathentry kind="src" path="samltest/security"/>\r
+<pathentry kind="src" path="samltest/saml1/binding"/>\r
</item>\r
</data>\r
</cdtproject>\r
// Check recipient URL.
auto_ptr_char recipient(response->getRecipient());
const char* recipient2 = httpRequest.getRequestURL();
- if (!recipient2 || !*recipient2 || strcmp(recipient.get(),recipient2)) {
+ if (!recipient.get() || !*(recipient.get())) {
+ log.error("response missing Recipient attribute");
+ throw BindingException("SAML response did not contain Recipient attribute identifying intended destination.");
+ }
+ else if (!recipient2 || !*recipient2 || strcmp(recipient.get(),recipient2)) {
log.error("POST targeted at (%s), but delivered to (%s)", recipient.get(), recipient2 ? recipient2 : "none");
throw BindingException("SAML message delivered with POST to incorrect server URL.");
}
+ // Check freshness.
time_t now = time(NULL);
if (response->getIssueInstant()->getEpoch() < now-(2*XMLToolingConfig::getConfig().clock_skew_secs))
throw BindingException("Detected expired POST profile response.");
-
+
+ // Check replay.
ReplayCache* replayCache = SAMLConfig::getConfig().getReplayCache();
if (replayCache) {
auto_ptr_char id(response->getResponseID());
- if (!replayCache->check("SAML1POST", id.get(), response->getIssueInstant()->getEpoch() + (2*XMLToolingConfig::getConfig().clock_skew_secs)))
+ if (!replayCache->check("SAML1POST", id.get(), response->getIssueInstant()->getEpoch() + (2*XMLToolingConfig::getConfig().clock_skew_secs))) {
+ log.error("replay detected of response ID (%s)", id.get());
throw BindingException("Rejecting replayed response ID ($1).", params(1,id.get()));
+ }
}
else
log.warn("replay cache was not provided, this is a serious security risk!");
+ /* For SAML 1, the issuer can only be established from any assertions in the message.
+ * Generally, errors aren't delivered like this, so there should be one.
+ * The Issuer attribute is matched against metadata, and then trust checking can be
+ * applied.
+ */
issuer = NULL;
issuerTrusted = false;
log.debug("attempting to establish issuer and integrity of message...");
const vector<Assertion*>& assertions=const_cast<const Response*>(response)->getAssertions();
if (!assertions.empty()) {
+ log.debug("searching metadata for assertion issuer...");
const EntityDescriptor* provider=
metadataProvider ? metadataProvider->getEntityDescriptor(assertions.front()->getIssuer()) : NULL;
if (provider) {
+ log.debug("matched assertion issuer against metadata, searching for applicable role...");
pair<bool,int> minor = response->getMinorVersion();
issuer=provider->getRoleDescriptor(
*role,
(minor.first && minor.second==0) ? SAMLConstants::SAML10_PROTOCOL_ENUM : SAMLConstants::SAML11_PROTOCOL_ENUM
);
- if (issuer && trustEngine && response->getSignature()) {
- issuerTrusted = static_cast<const TrustEngine*>(trustEngine)->validate(
- *(response->getSignature()), *issuer, metadataProvider->getKeyResolver()
+ if (issuer) {
+ if (trustEngine && response->getSignature()) {
+ issuerTrusted = static_cast<const TrustEngine*>(trustEngine)->validate(
+ *(response->getSignature()), *issuer, metadataProvider->getKeyResolver()
+ );
+ if (!issuerTrusted)
+ log.error("unable to verify signature on message with supplied trust engine");
+ }
+ else {
+ log.warn("unable to verify integrity of the message, leaving untrusted");
+ }
+ }
+ else {
+ log.warn(
+ "unable to find compatible SAML 1.%d role (%s) in metadata",
+ (minor.first && minor.second==0) ? 0 : 1,
+ role->toString().c_str()
);
- if (!issuerTrusted)
- log.error("signature on message could not be verified by supplied trust engine");
}
if (log.isDebugEnabled()) {
auto_ptr_char iname(assertions.front()->getIssuer());
log.debug("message from (%s), integrity %sverified", iname.get(), issuerTrusted ? "" : "NOT ");
}
}
- else
- log.warn("no metadata provider supplied, can't establish identity of issuer");
+ else {
+ auto_ptr_char temp(assertions.front()->getIssuer());
+ log.warn("no metadata found, can't establish identity of issuer (%s)", temp.get());
+ }
}
- else
+ else {
log.warn("no assertions found, can't establish identity of issuer");
+ }
}
catch (XMLToolingException& ex) {
// Check for an Issuer.
const EntityDescriptor* provider=metadataProvider->getEntityDescriptor(assertions.front()->getIssuer(),false);
if (provider) {
pair<bool,int> minor = response->getMinorVersion();
- const IDPSSODescriptor* role=provider->getIDPSSODescriptor(
+ issuer=provider->getRoleDescriptor(
+ *role,
(minor.first && minor.second==0) ? SAMLConstants::SAML10_PROTOCOL_ENUM : SAMLConstants::SAML11_PROTOCOL_ENUM
);
- if (role) annotateException(&ex,role); // throws it
+ if (issuer) annotateException(&ex,issuer); // throws it
annotateException(&ex,provider); // throws it
}
}
signature/SAML2AssertionTest.h \
security/AbstractPKIXTrustEngineTest.h \
security/ExplicitKeyTrustEngineTest.h \
+ saml1/binding/impl/SAML1POSTTest.h \
saml1/core/impl/ActionTest.h \
saml1/core/impl/AdviceTest.h \
saml1/core/impl/AssertionIDReferenceTest.h \
saml2/metadata/FilesystemMetadataProviderTest.h
noinst_HEADERS = \
+ binding.h \
internal.h \
signature/SAMLSignatureTestBase.h
--- /dev/null
+/*
+ * 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.
+ */
+
+#include "internal.h"
+
+#include <saml/SAMLConfig.h>
+#include <saml/binding/MessageDecoder.h>
+#include <saml/binding/MessageEncoder.h>
+#include <saml/saml2/metadata/MetadataProvider.h>
+#include <saml/security/X509TrustEngine.h>
+
+using namespace saml2md;
+using namespace xmlsignature;
+
+class SAMLBindingBaseTestCase : public MessageDecoder::HTTPRequest
+{
+protected:
+ CredentialResolver* m_creds;
+ MetadataProvider* m_metadata;
+ opensaml::X509TrustEngine* m_trust;
+ map<string,string> m_fields;
+
+public:
+ void setUp() {
+ m_creds=NULL;
+ m_metadata=NULL;
+ m_trust=NULL;
+ m_fields.clear();
+
+ try {
+ string config = data_path + "binding/ExampleMetadataProvider.xml";
+ ifstream in(config.c_str());
+ DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
+ XercesJanitor<DOMDocument> janitor(doc);
+
+ auto_ptr_XMLCh path("path");
+ string s = data_path + "binding/example-metadata.xml";
+ auto_ptr_XMLCh file(s.c_str());
+ doc->getDocumentElement()->setAttributeNS(NULL,path.get(),file.get());
+
+ m_metadata = SAMLConfig::getConfig().MetadataProviderManager.newPlugin(
+ FILESYSTEM_METADATA_PROVIDER,doc->getDocumentElement()
+ );
+ m_metadata->init();
+
+ config = data_path + "FilesystemCredentialResolver.xml";
+ ifstream in2(config.c_str());
+ DOMDocument* doc2=XMLToolingConfig::getConfig().getParser().parse(in2);
+ XercesJanitor<DOMDocument> janitor2(doc2);
+ m_creds = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(
+ FILESYSTEM_CREDENTIAL_RESOLVER,doc2->getDocumentElement()
+ );
+
+ m_trust = dynamic_cast<X509TrustEngine*>(
+ SAMLConfig::getConfig().TrustEngineManager.newPlugin(EXPLICIT_KEY_SAMLTRUSTENGINE, NULL)
+ );
+ }
+ catch (XMLToolingException& ex) {
+ TS_TRACE(ex.what());
+ tearDown();
+ throw;
+ }
+
+ }
+
+ void tearDown() {
+ delete m_creds;
+ delete m_metadata;
+ delete m_trust;
+ m_creds=NULL;
+ m_metadata=NULL;
+ m_trust=NULL;
+ m_fields.clear();
+ }
+
+ const char* getParameter(const char* name) const {
+ map<string,string>::const_iterator i=m_fields.find(name);
+ return i==m_fields.end() ? NULL : i->second.c_str();
+ }
+
+ vector<const char*>::size_type getParameters(const char* name, vector<const char*>& values) const {
+ values.clear();
+ map<string,string>::const_iterator i=m_fields.find(name);
+ if (i!=m_fields.end())
+ values.push_back(i->second.c_str());
+ return values.size();
+ }
+};
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<FilesystemMetadataProvider path="../samltest/data/binding/example-metadata.xml" validate="0"/>
--- /dev/null
+<EntitiesDescriptor\r
+ xmlns="urn:oasis:names:tc:SAML:2.0:metadata"\r
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"\r
+ validUntil="2010-01-01T00:00:00Z">\r
+\r
+ <EntityDescriptor entityID="https://idp.example.org/">\r
+ \r
+ <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">\r
+ <KeyDescriptor use="signing">\r
+ <ds:KeyInfo>\r
+ <ds:X509Data>\r
+ <ds:X509Certificate>\r
+ MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV
+ BAYTAlVTMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDnNwLmV4YW1wbGUu
+ b3JnMB4XDTA1MDYyMDE1NDgzNFoXDTMyMTEwNTE1NDgzNFowOjELMAkGA1UEBhMC
+ VVMxEjAQBgNVBAoTCUludGVybmV0MjEXMBUGA1UEAxMOc3AuZXhhbXBsZS5vcmcw
+ gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANlZ1L1mKzYbUVKiMQLhZlfGDyYa
+ /jjCiaXP0WhLNgvJpOTeajvsrApYNnFX5MLNzuC3NeQIjXUNLN2Yo2MCSthBIOL5
+ qE5dka4z9W9zytoflW1LmJ8vXpx8Ay/meG4z//J5iCpYVEquA0xl28HUIlownZUF
+ 7w7bx0cF/02qrR23AgMBAAGjgZwwgZkwHQYDVR0OBBYEFJZiO1qsyAyc3HwMlL9p
+ JpN6fbGwMGoGA1UdIwRjMGGAFJZiO1qsyAyc3HwMlL9pJpN6fbGwoT6kPDA6MQsw
+ CQYDVQQGEwJVUzESMBAGA1UEChMJSW50ZXJuZXQyMRcwFQYDVQQDEw5zcC5leGFt
+ cGxlLm9yZ4IJAKk8t1hYcMkhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD
+ gYEAMFq/UeSQyngE0GpZueyD2UW0M358uhseYOgGEIfm+qXIFQF6MYwNoX7WFzhC
+ LJZ2E6mEvZZFHCHUtl7mGDvsRwgZ85YCtRbvleEpqfgNQToto9pLYe+X6vvH9Z6p
+ gmYsTmak+kxO93JprrOd9xp8aZPMEprL7VCdrhbZEfyYER0=
+ </ds:X509Certificate>\r
+ </ds:X509Data>\r
+ </ds:KeyInfo>\r
+ </KeyDescriptor>\r
+\r
+ <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:protocol"\r
+ Location="https://idp.example.org/SSO"/>\r
+ </IDPSSODescriptor>\r
+ \r
+ <Organization>\r
+ <OrganizationName xml:lang="en">Example Identity Provider</OrganizationName>\r
+ <OrganizationDisplayName xml:lang="en">Identities 'R' Us</OrganizationDisplayName>\r
+ <OrganizationURL xml:lang="en">http://idp.example.org/</OrganizationURL>\r
+ </Organization>\r
+ <ContactPerson contactType="technical">\r
+ <SurName>Technical Support</SurName>\r
+ <EmailAddress>support@idp.example.org</EmailAddress>\r
+ </ContactPerson>\r
+\r
+ </EntityDescriptor>\r
+\r
+ <EntityDescriptor entityID="https://sp.example.org/">\r
+ \r
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">\r
+ <KeyDescriptor use="signing">\r
+ <ds:KeyInfo>\r
+ <ds:X509Data>\r
+ <ds:X509Certificate>\r
+ MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV
+ BAYTAlVTMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDnNwLmV4YW1wbGUu
+ b3JnMB4XDTA1MDYyMDE1NDgzNFoXDTMyMTEwNTE1NDgzNFowOjELMAkGA1UEBhMC
+ VVMxEjAQBgNVBAoTCUludGVybmV0MjEXMBUGA1UEAxMOc3AuZXhhbXBsZS5vcmcw
+ gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANlZ1L1mKzYbUVKiMQLhZlfGDyYa
+ /jjCiaXP0WhLNgvJpOTeajvsrApYNnFX5MLNzuC3NeQIjXUNLN2Yo2MCSthBIOL5
+ qE5dka4z9W9zytoflW1LmJ8vXpx8Ay/meG4z//J5iCpYVEquA0xl28HUIlownZUF
+ 7w7bx0cF/02qrR23AgMBAAGjgZwwgZkwHQYDVR0OBBYEFJZiO1qsyAyc3HwMlL9p
+ JpN6fbGwMGoGA1UdIwRjMGGAFJZiO1qsyAyc3HwMlL9pJpN6fbGwoT6kPDA6MQsw
+ CQYDVQQGEwJVUzESMBAGA1UEChMJSW50ZXJuZXQyMRcwFQYDVQQDEw5zcC5leGFt
+ cGxlLm9yZ4IJAKk8t1hYcMkhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD
+ gYEAMFq/UeSQyngE0GpZueyD2UW0M358uhseYOgGEIfm+qXIFQF6MYwNoX7WFzhC
+ LJZ2E6mEvZZFHCHUtl7mGDvsRwgZ85YCtRbvleEpqfgNQToto9pLYe+X6vvH9Z6p
+ gmYsTmak+kxO93JprrOd9xp8aZPMEprL7VCdrhbZEfyYER0=
+ </ds:X509Certificate>\r
+ </ds:X509Data>\r
+ </ds:KeyInfo>\r
+ </KeyDescriptor>\r
+ \r
+ <AssertionConsumerService index="1" isDefault="true"\r
+ Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post"\r
+ Location="https://sp.example.org/SAML/POST"/>\r
+\r
+ </SPSSODescriptor>\r
+\r
+ <Organization>\r
+ <OrganizationName xml:lang="en">Example Service Provider</OrganizationName>\r
+ <OrganizationDisplayName xml:lang="en">Services 'R' Us</OrganizationDisplayName>\r
+ <OrganizationURL xml:lang="en">http://sp.example.org/</OrganizationURL>\r
+ </Organization>\r
+ <ContactPerson contactType="technical">\r
+ <SurName>Technical Support</SurName>\r
+ <EmailAddress>support@sp.example.org</EmailAddress>\r
+ </ContactPerson>\r
+ \r
+ </EntityDescriptor>\r
+\r
+</EntitiesDescriptor>\r
--- /dev/null
+<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="1970-01-02T01:01:02.100Z"
+MajorVersion="1" MinorVersion="1" ResponseID="rident" Recipient="https://sp.example.org/SAML/POST">
+ <samlp:Status><samlp:StatusCode Value="samlp:Success"/></samlp:Status>
+ <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="aident"
+ IssueInstant="1970-01-02T01:01:02.100Z" Issuer="https://idp.example.org/" MajorVersion="1" MinorVersion="1">
+ <saml:AuthenticationStatement AuthenticationInstant="1970-01-02T01:01:02.100Z" AuthenticationMethod="method">
+ <saml:Subject><saml:NameIdentifier>John Doe</saml:NameIdentifier></saml:Subject>
+ </saml:AuthenticationStatement>
+ </saml:Assertion>
+</samlp:Response>
#include <fstream>
#include <saml/exceptions.h>
#include <saml/util/SAMLConstants.h>
-#include <xmltooling/exceptions.h>
-#include <xmltooling/validation/Validator.h>
#include <xmltooling/XMLObject.h>
#include <xmltooling/XMLObjectBuilder.h>
#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/validation/Validator.h>
using namespace opensaml;
using namespace xmltooling;
--- /dev/null
+/*\r
+ * Copyright 2001-2005 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "binding.h"\r
+\r
+#include <saml/saml1/core/Protocols.h>\r
+\r
+using namespace opensaml::saml1p;\r
+using namespace opensaml::saml1;\r
+\r
+class SAML1POSTTest : public CxxTest::TestSuite, public SAMLBindingBaseTestCase {\r
+public:\r
+ void setUp() {\r
+ m_fields.clear();\r
+ SAMLBindingBaseTestCase::setUp();\r
+ }\r
+\r
+ void tearDown() {\r
+ m_fields.clear();\r
+ SAMLBindingBaseTestCase::tearDown();\r
+ }\r
+\r
+ void testSAML1POSTTrusted() {\r
+ try {\r
+ // Read message to use from file.\r
+ string path = data_path + "saml1/binding/SAML1Response.xml";\r
+ ifstream in(path.c_str());\r
+ DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);\r
+ XercesJanitor<DOMDocument> janitor(doc);\r
+ auto_ptr<Response> toSend(\r
+ dynamic_cast<Response*>(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(),true))\r
+ );\r
+ janitor.release();\r
+\r
+ // Freshen timestamp.\r
+ toSend->setIssueInstant(time(NULL));\r
+ \r
+ // Encode message.\r
+ auto_ptr<MessageEncoder> encoder(SAMLConfig::getConfig().MessageEncoderManager.newPlugin(SAML1_POST_ENCODER, NULL));\r
+ encoder->encode(m_fields,toSend.get(),"https://sp.example.org/","state",m_creds);\r
+ toSend.release();\r
+ \r
+ // Decode message.\r
+ string relayState;\r
+ const RoleDescriptor* issuer=NULL;\r
+ bool trusted=false;\r
+ QName idprole(SAMLConstants::SAML20MD_NS, IDPSSODescriptor::LOCAL_NAME);\r
+ auto_ptr<MessageDecoder> decoder(SAMLConfig::getConfig().MessageDecoderManager.newPlugin(SAML1_POST_DECODER, NULL));\r
+ auto_ptr<Response> response(\r
+ dynamic_cast<Response*>(\r
+ decoder->decode(relayState,issuer,trusted,*this,m_metadata,&idprole,m_trust)\r
+ )\r
+ );\r
+ \r
+ // Test the results.\r
+ TSM_ASSERT_EQUALS("TARGET was not the expected result.", relayState, "state");\r
+ TSM_ASSERT("SAML Response not decoded successfully.", response.get());\r
+ TSM_ASSERT("Message was not verified.", issuer && trusted);\r
+ auto_ptr_char entityID(dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID());\r
+ TSM_ASSERT("Issuer was not expected.", !strcmp(entityID.get(),"https://idp.example.org/"));\r
+ TSM_ASSERT_EQUALS("Assertion count was not correct.", response->getAssertions().size(), 1);\r
+ }\r
+ catch (XMLToolingException& ex) {\r
+ TS_TRACE(ex.what());\r
+ throw;\r
+ }\r
+ }\r
+\r
+ void testSAML1POSTUntrusted() {\r
+ try {\r
+ // Read message to use from file.\r
+ string path = data_path + "saml1/binding/SAML1Response.xml";\r
+ ifstream in(path.c_str());\r
+ DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);\r
+ XercesJanitor<DOMDocument> janitor(doc);\r
+ auto_ptr<Response> toSend(\r
+ dynamic_cast<Response*>(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(),true))\r
+ );\r
+ janitor.release();\r
+\r
+ // Freshen timestamp and clear ID.\r
+ toSend->setIssueInstant(time(NULL));\r
+ toSend->setResponseID(NULL);\r
+ \r
+ // Encode message.\r
+ auto_ptr<MessageEncoder> encoder(SAMLConfig::getConfig().MessageEncoderManager.newPlugin(SAML1_POST_ENCODER, NULL));\r
+ encoder->encode(m_fields,toSend.get(),"https://sp.example.org/","state");\r
+ toSend.release();\r
+ \r
+ // Decode message.\r
+ string relayState;\r
+ const RoleDescriptor* issuer=NULL;\r
+ bool trusted=false;\r
+ QName idprole(SAMLConstants::SAML20MD_NS, IDPSSODescriptor::LOCAL_NAME);\r
+ auto_ptr<MessageDecoder> decoder(SAMLConfig::getConfig().MessageDecoderManager.newPlugin(SAML1_POST_DECODER, NULL));\r
+ auto_ptr<Response> response(\r
+ dynamic_cast<Response*>(\r
+ decoder->decode(relayState,issuer,trusted,*this,m_metadata,&idprole)\r
+ )\r
+ );\r
+ \r
+ // Test the results.\r
+ TSM_ASSERT_EQUALS("TARGET was not the expected result.", relayState, "state");\r
+ TSM_ASSERT("SAML Response not decoded successfully.", response.get());\r
+ TSM_ASSERT("Message was verified.", issuer && !trusted);\r
+ auto_ptr_char entityID(dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID());\r
+ TSM_ASSERT("Issuer was not expected.", !strcmp(entityID.get(),"https://idp.example.org/"));\r
+ TSM_ASSERT_EQUALS("Assertion count was not correct.", response->getAssertions().size(), 1);\r
+\r
+ // Trigger a replay.\r
+ TSM_ASSERT_THROWS("Did not catch the replay.", \r
+ decoder->decode(relayState,issuer,trusted,*this,m_metadata,&idprole,m_trust),\r
+ BindingException);\r
+ }\r
+ catch (XMLToolingException& ex) {\r
+ TS_TRACE(ex.what());\r
+ throw;\r
+ }\r
+ }\r
+\r
+ const char* getMethod() const {\r
+ return "POST";\r
+ } \r
+\r
+ const char* getRequestURL() const {\r
+ return "https://sp.example.org/SAML/POST";\r
+ }\r
+ \r
+ const char* getQueryString() const {\r
+ return NULL;\r
+ }\r
+};\r
*/\r
\r
#include "internal.h"\r
-#include <saml/SAMLConfig.h>
+#include <saml/SAMLConfig.h>\r
+#include <saml/binding/ReplayCache.h>\r
\r
#include <fstream>\r
#include <cxxtest/GlobalFixture.h>\r
XMLToolingConfig::getConfig().log_config();\r
if (!SAMLConfig::getConfig().init())\r
return false;\r
+ SAMLConfig::getConfig().setReplayCache(new ReplayCache());\r
+\r
if (getenv("SAMLTEST_DATA"))\r
data_path=std::string(getenv("SAMLTEST_DATA")) + "/";\r
//std::string catpath=data_path + "catalog.xml";\r
</File>\r
</Filter>\r
</Filter>\r
+ <Filter\r
+ Name="binding"\r
+ >\r
+ <File\r
+ RelativePath=".\saml1\binding\SAML1POSTTest.cpp"\r
+ >\r
+ </File>\r
+ </Filter>\r
</Filter>\r
<Filter\r
Name="signature"\r
>\r
</File>\r
</Filter>\r
+ <Filter\r
+ Name="binding"\r
+ >\r
+ </Filter>\r
</Filter>\r
<Filter\r
Name="security"\r
>\r
<Tool\r
Name="VCCustomBuildTool"\r
- CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputDir)$(InputName)".cpp "$(InputPath)""\r
+ CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputDir)$(InputName)".cpp "$(InputPath)"
"\r
Outputs=""$(InputDir)$(InputName)".cpp"\r
/>\r
</FileConfiguration>\r
>\r
<Tool\r
Name="VCCustomBuildTool"\r
- CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputDir)$(InputName)".cpp "$(InputPath)""\r
+ CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputDir)$(InputName)".cpp "$(InputPath)"
"\r
Outputs=""$(InputDir)$(InputName)".cpp"\r
/>\r
</FileConfiguration>\r
</File>\r
<File\r
+ RelativePath=".\binding.h"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\internal.h"\r
>\r
</File>\r
</File>\r
</Filter>\r
</Filter>\r
+ <Filter\r
+ Name="bnding"\r
+ >\r
+ <File\r
+ RelativePath=".\saml1\binding\SAML1POSTTest.h"\r
+ >\r
+ <FileConfiguration\r
+ Name="Debug|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputDir)$(InputName)".cpp "$(InputPath)""\r
+ Outputs=""$(InputDir)$(InputName)".cpp"\r
+ />\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputDir)$(InputName)".cpp "$(InputPath)""\r
+ Outputs=""$(InputDir)$(InputName)".cpp"\r
+ />\r
+ </FileConfiguration>\r
+ </File>\r
+ </Filter>\r
</Filter>\r
<Filter\r
Name="signature"\r
</FileConfiguration>\r
</File>\r
</Filter>\r
+ <Filter\r
+ Name="binding"\r
+ >\r
+ </Filter>\r
</Filter>\r
<Filter\r
Name="security"\r